• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/gettext-0.17/gettext-tools/src/
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