No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / src / format-c.c
blobcead658fdf49fe1c847dc24eace6dc985cf0e518
1 /* C format strings.
2 Copyright (C) 2001-2004 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 2, or (at your option)
8 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, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #include <stdbool.h>
24 #include <stdlib.h>
26 #include "format.h"
27 #include "c-ctype.h"
28 #include "xalloc.h"
29 #include "xerror.h"
30 #include "format-invalid.h"
31 #include "gettext.h"
33 #define _(str) gettext (str)
35 /* C format strings are described in POSIX (IEEE P1003.1 2001), section
36 XSH 3 fprintf(). See also Linux fprintf(3) manual page.
37 A directive
38 - starts with '%' or '%m$' where m is a positive integer,
39 - is optionally followed by any of the characters '#', '0', '-', ' ', '+',
40 "'", or - only in msgstr strings - the string "I", each of which acts as
41 a flag,
42 - is optionally followed by a width specification: '*' (reads an argument)
43 or '*m$' or a nonempty digit sequence,
44 - is optionally followed by '.' and a precision specification: '*' (reads
45 an argument) or '*m$' or a nonempty digit sequence,
46 - is either continued like this:
47 - is optionally followed by a size specifier, one of 'hh' 'h' 'l' 'll'
48 'L' 'q' 'j' 'z' 't',
49 - is finished by a specifier
50 - '%', that needs no argument,
51 - 'c', 'C', that need a character argument,
52 - 's', 'S', that need a string argument,
53 - 'i', 'd', that need a signed integer argument,
54 - 'o', 'u', 'x', 'X', that need an unsigned integer argument,
55 - 'e', 'E', 'f', 'F', 'g', 'G', 'a', 'A', that need a floating-point
56 argument,
57 - 'p', that needs a 'void *' argument,
58 - 'n', that needs a pointer to integer.
59 or is finished by a specifier '<' inttypes-macro '>' where inttypes-macro
60 is an ISO C 99 section 7.8.1 format directive.
61 Numbered ('%m$' or '*m$') and unnumbered argument specifications cannot
62 be used in the same string. When numbered argument specifications are
63 used, specifying the Nth argument requires that all the leading arguments,
64 from the first to the (N-1)th, are specified in the format string.
67 enum format_arg_type
69 FAT_NONE = 0,
70 /* Basic types */
71 FAT_INTEGER = 1,
72 FAT_DOUBLE = 2,
73 FAT_CHAR = 3,
74 FAT_STRING = 4,
75 FAT_OBJC_OBJECT = 5,
76 FAT_POINTER = 6,
77 FAT_COUNT_POINTER = 7,
78 /* Flags */
79 FAT_UNSIGNED = 1 << 3,
80 FAT_SIZE_SHORT = 1 << 4,
81 FAT_SIZE_CHAR = 2 << 4,
82 FAT_SIZE_LONG = 1 << 6,
83 FAT_SIZE_LONGLONG = 2 << 6,
84 FAT_SIZE_8_T = 1 << 8,
85 FAT_SIZE_16_T = 1 << 9,
86 FAT_SIZE_32_T = 1 << 10,
87 FAT_SIZE_64_T = 1 << 11,
88 FAT_SIZE_LEAST8_T = 1 << 12,
89 FAT_SIZE_LEAST16_T = 1 << 13,
90 FAT_SIZE_LEAST32_T = 1 << 14,
91 FAT_SIZE_LEAST64_T = 1 << 15,
92 FAT_SIZE_FAST8_T = 1 << 16,
93 FAT_SIZE_FAST16_T = 1 << 17,
94 FAT_SIZE_FAST32_T = 1 << 18,
95 FAT_SIZE_FAST64_T = 1 << 19,
96 FAT_SIZE_INTMAX_T = 1 << 20,
97 FAT_SIZE_INTPTR_T = 1 << 21,
98 FAT_SIZE_SIZE_T = 1 << 22,
99 FAT_SIZE_PTRDIFF_T = 1 << 23,
100 FAT_WIDE = FAT_SIZE_LONG,
101 /* Meaningful combinations of basic types and flags:
102 'signed char' = FAT_INTEGER | FAT_SIZE_CHAR,
103 'unsigned char' = FAT_INTEGER | FAT_SIZE_CHAR | FAT_UNSIGNED,
104 'short' = FAT_INTEGER | FAT_SIZE_SHORT,
105 'unsigned short' = FAT_INTEGER | FAT_SIZE_SHORT | FAT_UNSIGNED,
106 'int' = FAT_INTEGER,
107 'unsigned int' = FAT_INTEGER | FAT_UNSIGNED,
108 'long int' = FAT_INTEGER | FAT_SIZE_LONG,
109 'unsigned long int' = FAT_INTEGER | FAT_SIZE_LONG | FAT_UNSIGNED,
110 'long long int' = FAT_INTEGER | FAT_SIZE_LONGLONG,
111 'unsigned long long int' = FAT_INTEGER | FAT_SIZE_LONGLONG | FAT_UNSIGNED,
112 'double' = FAT_DOUBLE,
113 'long double' = FAT_DOUBLE | FAT_SIZE_LONGLONG,
114 'char'/'int' = FAT_CHAR,
115 'wchar_t'/'wint_t' = FAT_CHAR | FAT_SIZE_LONG,
116 'const char *' = FAT_STRING,
117 'const wchar_t *' = FAT_STRING | FAT_SIZE_LONG,
118 'void *' = FAT_POINTER,
119 FAT_COUNT_SCHAR_POINTER = FAT_COUNT_POINTER | FAT_SIZE_CHAR,
120 FAT_COUNT_SHORT_POINTER = FAT_COUNT_POINTER | FAT_SIZE_SHORT,
121 FAT_COUNT_INT_POINTER = FAT_COUNT_POINTER,
122 FAT_COUNT_LONGINT_POINTER = FAT_COUNT_POINTER | FAT_SIZE_LONG,
123 FAT_COUNT_LONGLONGINT_POINTER = FAT_COUNT_POINTER | FAT_SIZE_LONGLONG,
125 /* Bitmasks */
126 FAT_SIZE_MASK = (FAT_SIZE_SHORT | FAT_SIZE_CHAR
127 | FAT_SIZE_LONG | FAT_SIZE_LONGLONG
128 | FAT_SIZE_8_T | FAT_SIZE_16_T
129 | FAT_SIZE_32_T | FAT_SIZE_64_T
130 | FAT_SIZE_LEAST8_T | FAT_SIZE_LEAST16_T
131 | FAT_SIZE_LEAST32_T | FAT_SIZE_LEAST64_T
132 | FAT_SIZE_FAST8_T | FAT_SIZE_FAST16_T
133 | FAT_SIZE_FAST32_T | FAT_SIZE_FAST64_T
134 | FAT_SIZE_INTMAX_T | FAT_SIZE_INTPTR_T
135 | FAT_SIZE_SIZE_T | FAT_SIZE_PTRDIFF_T)
138 struct numbered_arg
140 unsigned int number;
141 enum format_arg_type type;
144 struct unnumbered_arg
146 enum format_arg_type type;
149 struct spec
151 unsigned int directives;
152 unsigned int unnumbered_arg_count;
153 unsigned int allocated;
154 struct unnumbered_arg *unnumbered;
155 unsigned int sysdep_directives_count;
156 const char **sysdep_directives;
159 /* Locale independent test for a decimal digit.
160 Argument can be 'char' or 'unsigned char'. (Whereas the argument of
161 <ctype.h> isdigit must be an 'unsigned char'.) */
162 #undef isdigit
163 #define isdigit(c) ((unsigned int) ((c) - '0') < 10)
166 static int
167 numbered_arg_compare (const void *p1, const void *p2)
169 unsigned int n1 = ((const struct numbered_arg *) p1)->number;
170 unsigned int n2 = ((const struct numbered_arg *) p2)->number;
172 return (n1 > n2 ? 1 : n1 < n2 ? -1 : 0);
175 #define INVALID_C99_MACRO(directive_number) \
176 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)
178 static void *
179 format_parse (const char *format, bool translated, bool objc_extensions,
180 char **invalid_reason)
182 struct spec spec;
183 unsigned int numbered_arg_count;
184 struct numbered_arg *numbered;
185 struct spec *result;
187 spec.directives = 0;
188 numbered_arg_count = 0;
189 spec.unnumbered_arg_count = 0;
190 spec.allocated = 0;
191 numbered = NULL;
192 spec.unnumbered = NULL;
193 spec.sysdep_directives_count = 0;
194 spec.sysdep_directives = NULL;
196 for (; *format != '\0';)
197 if (*format++ == '%')
199 /* A directive. */
200 unsigned int number = 0;
201 enum format_arg_type type;
202 enum format_arg_type size;
204 spec.directives++;
206 if (isdigit (*format))
208 const char *f = format;
209 unsigned int m = 0;
213 m = 10 * m + (*f - '0');
214 f++;
216 while (isdigit (*f));
218 if (*f == '$')
220 if (m == 0)
222 *invalid_reason = INVALID_ARGNO_0 (spec.directives);
223 goto bad_format;
225 number = m;
226 format = ++f;
230 /* Parse flags. */
231 for (;;)
233 if (*format == ' ' || *format == '+' || *format == '-'
234 || *format == '#' || *format == '0' || *format == '\'')
235 format++;
236 else if (translated && *format == 'I')
238 spec.sysdep_directives =
239 (const char **)
240 xrealloc (spec.sysdep_directives,
241 2 * (spec.sysdep_directives_count + 1)
242 * sizeof (const char *));
243 spec.sysdep_directives[2 * spec.sysdep_directives_count] = format;
244 spec.sysdep_directives[2 * spec.sysdep_directives_count + 1] = format + 1;
245 spec.sysdep_directives_count++;
246 format++;
248 else
249 break;
252 /* Parse width. */
253 if (*format == '*')
255 unsigned int width_number = 0;
257 format++;
259 if (isdigit (*format))
261 const char *f = format;
262 unsigned int m = 0;
266 m = 10 * m + (*f - '0');
267 f++;
269 while (isdigit (*f));
271 if (*f == '$')
273 if (m == 0)
275 *invalid_reason =
276 INVALID_WIDTH_ARGNO_0 (spec.directives);
277 goto bad_format;
279 width_number = m;
280 format = ++f;
284 if (width_number)
286 /* Numbered argument. */
288 /* Numbered and unnumbered specifications are exclusive. */
289 if (spec.unnumbered_arg_count > 0)
291 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
292 goto bad_format;
295 if (spec.allocated == numbered_arg_count)
297 spec.allocated = 2 * spec.allocated + 1;
298 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg));
300 numbered[numbered_arg_count].number = width_number;
301 numbered[numbered_arg_count].type = FAT_INTEGER;
302 numbered_arg_count++;
304 else
306 /* Unnumbered argument. */
308 /* Numbered and unnumbered specifications are exclusive. */
309 if (numbered_arg_count > 0)
311 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
312 goto bad_format;
315 if (spec.allocated == spec.unnumbered_arg_count)
317 spec.allocated = 2 * spec.allocated + 1;
318 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
320 spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER;
321 spec.unnumbered_arg_count++;
324 else if (isdigit (*format))
326 do format++; while (isdigit (*format));
329 /* Parse precision. */
330 if (*format == '.')
332 format++;
334 if (*format == '*')
336 unsigned int precision_number = 0;
338 format++;
340 if (isdigit (*format))
342 const char *f = format;
343 unsigned int m = 0;
347 m = 10 * m + (*f - '0');
348 f++;
350 while (isdigit (*f));
352 if (*f == '$')
354 if (m == 0)
356 *invalid_reason =
357 INVALID_PRECISION_ARGNO_0 (spec.directives);
358 goto bad_format;
360 precision_number = m;
361 format = ++f;
365 if (precision_number)
367 /* Numbered argument. */
369 /* Numbered and unnumbered specifications are exclusive. */
370 if (spec.unnumbered_arg_count > 0)
372 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
373 goto bad_format;
376 if (spec.allocated == numbered_arg_count)
378 spec.allocated = 2 * spec.allocated + 1;
379 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg));
381 numbered[numbered_arg_count].number = precision_number;
382 numbered[numbered_arg_count].type = FAT_INTEGER;
383 numbered_arg_count++;
385 else
387 /* Unnumbered argument. */
389 /* Numbered and unnumbered specifications are exclusive. */
390 if (numbered_arg_count > 0)
392 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
393 goto bad_format;
396 if (spec.allocated == spec.unnumbered_arg_count)
398 spec.allocated = 2 * spec.allocated + 1;
399 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
401 spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER;
402 spec.unnumbered_arg_count++;
405 else if (isdigit (*format))
407 do format++; while (isdigit (*format));
411 if (*format == '<')
413 spec.sysdep_directives =
414 (const char **)
415 xrealloc (spec.sysdep_directives,
416 2 * (spec.sysdep_directives_count + 1)
417 * sizeof (const char *));
418 spec.sysdep_directives[2 * spec.sysdep_directives_count] = format;
420 format++;
421 /* Parse ISO C 99 section 7.8.1 format string directive.
422 Syntax:
423 P R I { d | i | o | u | x | X }
424 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
425 if (*format != 'P')
427 *invalid_reason = INVALID_C99_MACRO (spec.directives);
428 goto bad_format;
430 format++;
431 if (*format != 'R')
433 *invalid_reason = INVALID_C99_MACRO (spec.directives);
434 goto bad_format;
436 format++;
437 if (*format != 'I')
439 *invalid_reason = INVALID_C99_MACRO (spec.directives);
440 goto bad_format;
442 format++;
444 switch (*format)
446 case 'i': case 'd':
447 type = FAT_INTEGER;
448 break;
449 case 'u': case 'o': case 'x': case 'X':
450 type = FAT_INTEGER | FAT_UNSIGNED;
451 break;
452 default:
453 *invalid_reason = INVALID_C99_MACRO (spec.directives);
454 goto bad_format;
456 format++;
458 if (format[0] == 'M' && format[1] == 'A' && format[2] == 'X')
460 type |= FAT_SIZE_INTMAX_T;
461 format += 3;
463 else if (format[0] == 'P' && format[1] == 'T' && format[2] == 'R')
465 type |= FAT_SIZE_INTPTR_T;
466 format += 3;
468 else
470 if (format[0] == 'L' && format[1] == 'E' && format[2] == 'A'
471 && format[3] == 'S' && format[4] == 'T')
473 format += 5;
474 if (format[0] == '8')
476 type |= FAT_SIZE_LEAST8_T;
477 format++;
479 else if (format[0] == '1' && format[1] == '6')
481 type |= FAT_SIZE_LEAST16_T;
482 format += 2;
484 else if (format[0] == '3' && format[1] == '2')
486 type |= FAT_SIZE_LEAST32_T;
487 format += 2;
489 else if (format[0] == '6' && format[1] == '4')
491 type |= FAT_SIZE_LEAST64_T;
492 format += 2;
494 else
496 *invalid_reason = INVALID_C99_MACRO (spec.directives);
497 goto bad_format;
500 else if (format[0] == 'F' && format[1] == 'A'
501 && format[2] == 'S' && format[3] == 'T')
503 format += 4;
504 if (format[0] == '8')
506 type |= FAT_SIZE_FAST8_T;
507 format++;
509 else if (format[0] == '1' && format[1] == '6')
511 type |= FAT_SIZE_FAST16_T;
512 format += 2;
514 else if (format[0] == '3' && format[1] == '2')
516 type |= FAT_SIZE_FAST32_T;
517 format += 2;
519 else if (format[0] == '6' && format[1] == '4')
521 type |= FAT_SIZE_FAST64_T;
522 format += 2;
524 else
526 *invalid_reason = INVALID_C99_MACRO (spec.directives);
527 goto bad_format;
530 else
532 if (format[0] == '8')
534 type |= FAT_SIZE_8_T;
535 format++;
537 else if (format[0] == '1' && format[1] == '6')
539 type |= FAT_SIZE_16_T;
540 format += 2;
542 else if (format[0] == '3' && format[1] == '2')
544 type |= FAT_SIZE_32_T;
545 format += 2;
547 else if (format[0] == '6' && format[1] == '4')
549 type |= FAT_SIZE_64_T;
550 format += 2;
552 else
554 *invalid_reason = INVALID_C99_MACRO (spec.directives);
555 goto bad_format;
560 if (*format != '>')
562 *invalid_reason =
563 xasprintf (_("In the directive number %u, the token after '<' is not followed by '>'."), spec.directives);
564 goto bad_format;
567 spec.sysdep_directives[2 * spec.sysdep_directives_count + 1] = format + 1;
568 spec.sysdep_directives_count++;
570 else
572 /* Parse size. */
573 size = 0;
574 for (;; format++)
576 if (*format == 'h')
578 if (size & (FAT_SIZE_SHORT | FAT_SIZE_CHAR))
579 size = FAT_SIZE_CHAR;
580 else
581 size = FAT_SIZE_SHORT;
583 else if (*format == 'l')
585 if (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG))
586 size = FAT_SIZE_LONGLONG;
587 else
588 size = FAT_SIZE_LONG;
590 else if (*format == 'L')
591 size = FAT_SIZE_LONGLONG;
592 else if (*format == 'q')
593 /* Old BSD 4.4 convention. */
594 size = FAT_SIZE_LONGLONG;
595 else if (*format == 'j')
596 size = FAT_SIZE_INTMAX_T;
597 else if (*format == 'z' || *format == 'Z')
598 /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
599 because the warning facility in gcc-2.95.2 understands
600 only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
601 size = FAT_SIZE_SIZE_T;
602 else if (*format == 't')
603 size = FAT_SIZE_PTRDIFF_T;
604 else
605 break;
608 switch (*format)
610 case '%':
611 case 'm': /* glibc extension */
612 type = FAT_NONE;
613 break;
614 case 'c':
615 type = FAT_CHAR;
616 type |= (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG)
617 ? FAT_WIDE : 0);
618 break;
619 case 'C': /* obsolete */
620 type = FAT_CHAR | FAT_WIDE;
621 break;
622 case 's':
623 type = FAT_STRING;
624 type |= (size & (FAT_SIZE_LONG | FAT_SIZE_LONGLONG)
625 ? FAT_WIDE : 0);
626 break;
627 case 'S': /* obsolete */
628 type = FAT_STRING | FAT_WIDE;
629 break;
630 case 'i': case 'd':
631 type = FAT_INTEGER;
632 type |= (size & FAT_SIZE_MASK);
633 break;
634 case 'u': case 'o': case 'x': case 'X':
635 type = FAT_INTEGER | FAT_UNSIGNED;
636 type |= (size & FAT_SIZE_MASK);
637 break;
638 case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
639 case 'a': case 'A':
640 type = FAT_DOUBLE;
641 type |= (size & FAT_SIZE_LONGLONG);
642 break;
643 case '@':
644 if (objc_extensions)
646 type = FAT_OBJC_OBJECT;
647 break;
649 goto other;
650 case 'p':
651 type = FAT_POINTER;
652 break;
653 case 'n':
654 type = FAT_COUNT_POINTER;
655 type |= (size & FAT_SIZE_MASK);
656 break;
657 other:
658 default:
659 *invalid_reason =
660 (*format == '\0'
661 ? INVALID_UNTERMINATED_DIRECTIVE ()
662 : INVALID_CONVERSION_SPECIFIER (spec.directives, *format));
663 goto bad_format;
667 if (type != FAT_NONE)
669 if (number)
671 /* Numbered argument. */
673 /* Numbered and unnumbered specifications are exclusive. */
674 if (spec.unnumbered_arg_count > 0)
676 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
677 goto bad_format;
680 if (spec.allocated == numbered_arg_count)
682 spec.allocated = 2 * spec.allocated + 1;
683 numbered = (struct numbered_arg *) xrealloc (numbered, spec.allocated * sizeof (struct numbered_arg));
685 numbered[numbered_arg_count].number = number;
686 numbered[numbered_arg_count].type = type;
687 numbered_arg_count++;
689 else
691 /* Unnumbered argument. */
693 /* Numbered and unnumbered specifications are exclusive. */
694 if (numbered_arg_count > 0)
696 *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED ();
697 goto bad_format;
700 if (spec.allocated == spec.unnumbered_arg_count)
702 spec.allocated = 2 * spec.allocated + 1;
703 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
705 spec.unnumbered[spec.unnumbered_arg_count].type = type;
706 spec.unnumbered_arg_count++;
710 format++;
713 /* Sort the numbered argument array, and eliminate duplicates. */
714 if (numbered_arg_count > 1)
716 unsigned int i, j;
717 bool err;
719 qsort (numbered, numbered_arg_count,
720 sizeof (struct numbered_arg), numbered_arg_compare);
722 /* Remove duplicates: Copy from i to j, keeping 0 <= j <= i. */
723 err = false;
724 for (i = j = 0; i < numbered_arg_count; i++)
725 if (j > 0 && numbered[i].number == numbered[j-1].number)
727 enum format_arg_type type1 = numbered[i].type;
728 enum format_arg_type type2 = numbered[j-1].type;
729 enum format_arg_type type_both;
731 if (type1 == type2)
732 type_both = type1;
733 else
735 /* Incompatible types. */
736 type_both = FAT_NONE;
737 if (!err)
738 *invalid_reason =
739 INVALID_INCOMPATIBLE_ARG_TYPES (numbered[i].number);
740 err = true;
743 numbered[j-1].type = type_both;
745 else
747 if (j < i)
749 numbered[j].number = numbered[i].number;
750 numbered[j].type = numbered[i].type;
752 j++;
754 numbered_arg_count = j;
755 if (err)
756 /* *invalid_reason has already been set above. */
757 goto bad_format;
760 /* Verify that the format strings uses all arguments up to the highest
761 numbered one. */
762 if (numbered_arg_count > 0)
764 unsigned int i;
766 for (i = 0; i < numbered_arg_count; i++)
767 if (numbered[i].number != i + 1)
769 *invalid_reason =
770 xasprintf (_("The string refers to argument number %u but ignores argument number %u."), numbered[i].number, i + 1);
771 goto bad_format;
774 /* So now the numbered arguments array is equivalent to a sequence
775 of unnumbered arguments. */
776 spec.unnumbered_arg_count = numbered_arg_count;
777 spec.allocated = spec.unnumbered_arg_count;
778 spec.unnumbered = (struct unnumbered_arg *) xmalloc (spec.allocated * sizeof (struct unnumbered_arg));
779 for (i = 0; i < spec.unnumbered_arg_count; i++)
780 spec.unnumbered[i].type = numbered[i].type;
781 free (numbered);
782 numbered_arg_count = 0;
785 result = (struct spec *) xmalloc (sizeof (struct spec));
786 *result = spec;
787 return result;
789 bad_format:
790 if (numbered != NULL)
791 free (numbered);
792 if (spec.unnumbered != NULL)
793 free (spec.unnumbered);
794 if (spec.sysdep_directives != NULL)
795 free (spec.sysdep_directives);
796 return NULL;
799 static void *
800 format_c_parse (const char *format, bool translated, char **invalid_reason)
802 return format_parse (format, translated, false, invalid_reason);
805 static void *
806 format_objc_parse (const char *format, bool translated, char **invalid_reason)
808 return format_parse (format, translated, true, invalid_reason);
811 static void
812 format_free (void *descr)
814 struct spec *spec = (struct spec *) descr;
816 if (spec->unnumbered != NULL)
817 free (spec->unnumbered);
818 if (spec->sysdep_directives != NULL)
819 free (spec->sysdep_directives);
820 free (spec);
823 static int
824 format_get_number_of_directives (void *descr)
826 struct spec *spec = (struct spec *) descr;
828 return spec->directives;
831 static bool
832 format_check (void *msgid_descr, void *msgstr_descr, bool equality,
833 formatstring_error_logger_t error_logger,
834 const char *pretty_msgstr)
836 struct spec *spec1 = (struct spec *) msgid_descr;
837 struct spec *spec2 = (struct spec *) msgstr_descr;
838 bool err = false;
839 unsigned int i;
841 /* Check the argument types are the same. */
842 if (equality
843 ? spec1->unnumbered_arg_count != spec2->unnumbered_arg_count
844 : spec1->unnumbered_arg_count < spec2->unnumbered_arg_count)
846 if (error_logger)
847 error_logger (_("number of format specifications in 'msgid' and '%s' does not match"),
848 pretty_msgstr);
849 err = true;
851 else
852 for (i = 0; i < spec2->unnumbered_arg_count; i++)
853 if (spec1->unnumbered[i].type != spec2->unnumbered[i].type)
855 if (error_logger)
856 error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
857 pretty_msgstr, i + 1);
858 err = true;
861 return err;
865 struct formatstring_parser formatstring_c =
867 format_c_parse,
868 format_free,
869 format_get_number_of_directives,
870 format_check
874 struct formatstring_parser formatstring_objc =
876 format_objc_parse,
877 format_free,
878 format_get_number_of_directives,
879 format_check
883 void
884 get_sysdep_c_format_directives (const char *string, bool translated,
885 struct interval **intervalsp, size_t *lengthp)
887 /* Parse the format string with all possible extensions turned on. (The
888 caller has already verified that the format string is valid for the
889 particular language.) */
890 char *invalid_reason = NULL;
891 struct spec *descr =
892 (struct spec *) format_parse (string, translated, true, &invalid_reason);
894 if (descr != NULL && descr->sysdep_directives_count > 0)
896 unsigned int n = descr->sysdep_directives_count;
897 struct interval *intervals =
898 (struct interval *) xmalloc (n * sizeof (struct interval));
899 unsigned int i;
901 for (i = 0; i < n; i++)
903 intervals[i].startpos = descr->sysdep_directives[2 * i] - string;
904 intervals[i].endpos = descr->sysdep_directives[2 * i + 1] - string;
906 *intervalsp = intervals;
907 *lengthp = n;
909 else
911 *intervalsp = NULL;
912 *lengthp = 0;
915 if (descr != NULL)
916 format_free (descr);
917 else
918 free (invalid_reason);
922 #ifdef TEST
924 /* Test program: Print the argument list specification returned by
925 format_parse for strings read from standard input. */
927 #include <stdio.h>
928 #include "getline.h"
930 static void
931 format_print (void *descr)
933 struct spec *spec = (struct spec *) descr;
934 unsigned int i;
936 if (spec == NULL)
938 printf ("INVALID");
939 return;
942 printf ("(");
943 for (i = 0; i < spec->unnumbered_arg_count; i++)
945 if (i > 0)
946 printf (" ");
947 if (spec->unnumbered[i].type & FAT_UNSIGNED)
948 printf ("[unsigned]");
949 switch (spec->unnumbered[i].type & FAT_SIZE_MASK)
951 case 0:
952 break;
953 case FAT_SIZE_SHORT:
954 printf ("[short]");
955 break;
956 case FAT_SIZE_CHAR:
957 printf ("[char]");
958 break;
959 case FAT_SIZE_LONG:
960 printf ("[long]");
961 break;
962 case FAT_SIZE_LONGLONG:
963 printf ("[long long]");
964 break;
965 case FAT_SIZE_8_T:
966 printf ("[int8_t]");
967 break;
968 case FAT_SIZE_16_T:
969 printf ("[int16_t]");
970 break;
971 case FAT_SIZE_32_T:
972 printf ("[int32_t]");
973 break;
974 case FAT_SIZE_64_T:
975 printf ("[int64_t]");
976 break;
977 case FAT_SIZE_LEAST8_T:
978 printf ("[int_least8_t]");
979 break;
980 case FAT_SIZE_LEAST16_T:
981 printf ("[int_least16_t]");
982 break;
983 case FAT_SIZE_LEAST32_T:
984 printf ("[int_least32_t]");
985 break;
986 case FAT_SIZE_LEAST64_T:
987 printf ("[int_least64_t]");
988 break;
989 case FAT_SIZE_FAST8_T:
990 printf ("[int_fast8_t]");
991 break;
992 case FAT_SIZE_FAST16_T:
993 printf ("[int_fast16_t]");
994 break;
995 case FAT_SIZE_FAST32_T:
996 printf ("[int_fast32_t]");
997 break;
998 case FAT_SIZE_FAST64_T:
999 printf ("[int_fast64_t]");
1000 break;
1001 case FAT_SIZE_INTMAX_T:
1002 printf ("[intmax_t]");
1003 break;
1004 case FAT_SIZE_INTPTR_T:
1005 printf ("[intptr_t]");
1006 break;
1007 case FAT_SIZE_SIZE_T:
1008 printf ("[size_t]");
1009 break;
1010 case FAT_SIZE_PTRDIFF_T:
1011 printf ("[ptrdiff_t]");
1012 break;
1013 default:
1014 abort ();
1016 switch (spec->unnumbered[i].type & ~(FAT_UNSIGNED | FAT_SIZE_MASK))
1018 case FAT_INTEGER:
1019 printf ("i");
1020 break;
1021 case FAT_DOUBLE:
1022 printf ("f");
1023 break;
1024 case FAT_CHAR:
1025 printf ("c");
1026 break;
1027 case FAT_STRING:
1028 printf ("s");
1029 break;
1030 case FAT_OBJC_OBJECT:
1031 printf ("@");
1032 break;
1033 case FAT_POINTER:
1034 printf ("p");
1035 break;
1036 case FAT_COUNT_POINTER:
1037 printf ("n");
1038 break;
1039 default:
1040 abort ();
1043 printf (")");
1047 main ()
1049 for (;;)
1051 char *line = NULL;
1052 size_t line_size = 0;
1053 int line_len;
1054 char *invalid_reason;
1055 void *descr;
1057 line_len = getline (&line, &line_size, stdin);
1058 if (line_len < 0)
1059 break;
1060 if (line_len > 0 && line[line_len - 1] == '\n')
1061 line[--line_len] = '\0';
1063 invalid_reason = NULL;
1064 descr = format_c_parse (line, false, &invalid_reason);
1066 format_print (descr);
1067 printf ("\n");
1068 if (descr == NULL)
1069 printf ("%s\n", invalid_reason);
1071 free (invalid_reason);
1072 free (line);
1075 return 0;
1079 * For Emacs M-x compile
1080 * Local Variables:
1081 * compile-command: "/bin/sh ../libtool --mode=link gcc -o a.out -static -O -g -Wall -I.. -I../lib -I../intl -DHAVE_CONFIG_H -DTEST format-c.c ../lib/libgettextlib.la"
1082 * End:
1085 #endif /* TEST */