No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / src / format-gcc-internal.c
blob207adb9b8f95da949f1ddf799b08fbf2aaa665d5
1 /* GCC internal format strings.
2 Copyright (C) 2003-2004 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
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 /* GCC internal format strings consist of language frontend independent
36 format directives, implemented in gcc-3.3/gcc/diagnostic.c (function
37 output_format), plus some frontend dependent extensions:
38 - for the C/ObjC frontend in gcc-3.3/gcc/c-objc-common.c
39 - for the C++ frontend in gcc-3.3/gcc/cp/error.c
40 Taking these together, GCC internal format strings are specified as follows.
41 A directive
42 - starts with '%',
43 - is optionally followed by a size specifier 'l',
44 - is optionally followed by '+' (only the specifiers of gcc/cp/error.c),
45 - is optionally followed by '#' (only the specifiers of gcc/cp/error.c),
46 - is finished by a specifier
48 - '%', that needs no argument,
49 - 'c', that needs a character argument,
50 - 's', that needs a string argument,
51 - 'i', 'd', that need a signed integer argument,
52 - 'o', 'u', 'x', that need an unsigned integer argument,
53 - '.*s', that needs a signed integer argument and a string argument,
54 - 'H', that needs a 'location_t *' argument,
55 [see gcc/diagnostic.c]
57 - 'D', that needs a general declaration argument,
58 - 'F', that needs a function declaration argument,
59 - 'T', that needs a type argument,
60 [see gcc/c-objc-common.c and gcc/cp/error.c]
62 - 'A', that needs a function argument list argument,
63 - 'C', that needs a tree code argument,
64 - 'E', that needs an expression argument,
65 - 'L', that needs a language argument,
66 - 'O', that needs a binary operator argument,
67 - 'P', that needs a function parameter argument,
68 - 'Q', that needs an assignment operator argument,
69 - 'V', that needs a const/volatile qualifier argument.
70 [see gcc/cp/error.c]
73 enum format_arg_type
75 FAT_NONE = 0,
76 /* Basic types */
77 FAT_INTEGER = 1,
78 FAT_CHAR = 2,
79 FAT_STRING = 3,
80 FAT_LOCATION = 4,
81 FAT_TREE = 5,
82 FAT_TREE_CODE = 6,
83 FAT_LANGUAGES = 7,
84 /* Flags */
85 FAT_UNSIGNED = 1 << 3,
86 FAT_SIZE_LONG = 1 << 4,
87 FAT_TREE_DECL = 1 << 5,
88 FAT_TREE_FUNCDECL = 2 << 5,
89 FAT_TREE_TYPE = 3 << 5,
90 FAT_TREE_ARGUMENT = 4 << 5,
91 FAT_TREE_EXPRESSION = 5 << 5,
92 FAT_TREE_CV = 6 << 5,
93 FAT_TREE_CODE_BINOP = 1 << 8,
94 FAT_TREE_CODE_ASSOP = 2 << 8,
95 FAT_FUNCPARAM = 1 << 10
98 struct unnumbered_arg
100 enum format_arg_type type;
103 struct spec
105 unsigned int directives;
106 unsigned int unnumbered_arg_count;
107 unsigned int allocated;
108 struct unnumbered_arg *unnumbered;
112 static void *
113 format_parse (const char *format, bool translated, char **invalid_reason)
115 struct spec spec;
116 struct spec *result;
118 spec.directives = 0;
119 spec.unnumbered_arg_count = 0;
120 spec.allocated = 0;
121 spec.unnumbered = NULL;
123 for (; *format != '\0';)
124 if (*format++ == '%')
126 /* A directive. */
127 enum format_arg_type size;
129 spec.directives++;
131 /* Parse size. */
132 size = 0;
133 if (*format == 'l')
135 format++;
136 size = FAT_SIZE_LONG;
139 if (*format != '%')
141 enum format_arg_type type;
143 if (*format == 'c')
144 type = FAT_CHAR;
145 else if (*format == 's')
146 type = FAT_STRING;
147 else if (*format == 'i' || *format == 'd')
148 type = FAT_INTEGER | size;
149 else if (*format == 'o' || *format == 'u' || *format == 'x')
150 type = FAT_INTEGER | FAT_UNSIGNED | size;
151 else if (*format == '.' && format[1] == '*' && format[2] == 's')
153 if (spec.allocated == spec.unnumbered_arg_count)
155 spec.allocated = 2 * spec.allocated + 1;
156 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
158 spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER;
159 spec.unnumbered_arg_count++;
160 type = FAT_STRING;
162 else if (*format == 'H')
163 type = FAT_LOCATION;
164 else
166 if (*format == '+')
167 format++;
168 if (*format == '#')
169 format++;
170 if (*format == 'D')
171 type = FAT_TREE | FAT_TREE_DECL;
172 else if (*format == 'F')
173 type = FAT_TREE | FAT_TREE_FUNCDECL;
174 else if (*format == 'T')
175 type = FAT_TREE | FAT_TREE_TYPE;
176 else if (*format == 'A')
177 type = FAT_TREE | FAT_TREE_ARGUMENT;
178 else if (*format == 'C')
179 type = FAT_TREE_CODE;
180 else if (*format == 'E')
181 type = FAT_TREE | FAT_TREE_EXPRESSION;
182 else if (*format == 'L')
183 type = FAT_LANGUAGES;
184 else if (*format == 'O')
185 type = FAT_TREE_CODE | FAT_TREE_CODE_BINOP;
186 else if (*format == 'P')
187 type = FAT_INTEGER | FAT_FUNCPARAM;
188 else if (*format == 'Q')
189 type = FAT_TREE_CODE | FAT_TREE_CODE_ASSOP;
190 else if (*format == 'V')
191 type = FAT_TREE | FAT_TREE_CV;
192 else
194 *invalid_reason =
195 (*format == '\0'
196 ? INVALID_UNTERMINATED_DIRECTIVE ()
197 : (*format == 'c'
198 || *format == 's'
199 || *format == 'i' || *format == 'd'
200 || *format == 'o' || *format == 'u' || *format == 'x'
201 || *format == 'H'
202 ? xasprintf (_("In the directive number %u, flags are not allowed before '%c'."), spec.directives, *format)
203 : INVALID_CONVERSION_SPECIFIER (spec.directives,
204 *format)));
205 goto bad_format;
209 if (spec.allocated == spec.unnumbered_arg_count)
211 spec.allocated = 2 * spec.allocated + 1;
212 spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
214 spec.unnumbered[spec.unnumbered_arg_count].type = type;
215 spec.unnumbered_arg_count++;
218 format++;
221 result = (struct spec *) xmalloc (sizeof (struct spec));
222 *result = spec;
223 return result;
225 bad_format:
226 if (spec.unnumbered != NULL)
227 free (spec.unnumbered);
228 return NULL;
231 static void
232 format_free (void *descr)
234 struct spec *spec = (struct spec *) descr;
236 if (spec->unnumbered != NULL)
237 free (spec->unnumbered);
238 free (spec);
241 static int
242 format_get_number_of_directives (void *descr)
244 struct spec *spec = (struct spec *) descr;
246 return spec->directives;
249 static bool
250 format_check (void *msgid_descr, void *msgstr_descr, bool equality,
251 formatstring_error_logger_t error_logger,
252 const char *pretty_msgstr)
254 struct spec *spec1 = (struct spec *) msgid_descr;
255 struct spec *spec2 = (struct spec *) msgstr_descr;
256 bool err = false;
257 unsigned int i;
259 /* Check the argument types are the same. */
260 if (equality
261 ? spec1->unnumbered_arg_count != spec2->unnumbered_arg_count
262 : spec1->unnumbered_arg_count < spec2->unnumbered_arg_count)
264 if (error_logger)
265 error_logger (_("number of format specifications in 'msgid' and '%s' does not match"),
266 pretty_msgstr);
267 err = true;
269 else
270 for (i = 0; i < spec2->unnumbered_arg_count; i++)
271 if (spec1->unnumbered[i].type != spec2->unnumbered[i].type)
273 if (error_logger)
274 error_logger (_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
275 pretty_msgstr, i + 1);
276 err = true;
279 return err;
283 struct formatstring_parser formatstring_gcc_internal =
285 format_parse,
286 format_free,
287 format_get_number_of_directives,
288 format_check
292 #ifdef TEST
294 /* Test program: Print the argument list specification returned by
295 format_parse for strings read from standard input. */
297 #include <stdio.h>
298 #include "getline.h"
300 static void
301 format_print (void *descr)
303 struct spec *spec = (struct spec *) descr;
304 unsigned int i;
306 if (spec == NULL)
308 printf ("INVALID");
309 return;
312 printf ("(");
313 for (i = 0; i < spec->unnumbered_arg_count; i++)
315 if (i > 0)
316 printf (" ");
317 if (spec->unnumbered[i].type & FAT_UNSIGNED)
318 printf ("[unsigned]");
319 if (spec->unnumbered[i].type & FAT_SIZE_LONG)
320 printf ("[long]");
321 switch (spec->unnumbered[i].type & ~(FAT_UNSIGNED | FAT_SIZE_LONG))
323 case FAT_INTEGER:
324 printf ("i");
325 break;
326 case FAT_INTEGER | FAT_FUNCPARAM:
327 printf ("P");
328 break;
329 case FAT_CHAR:
330 printf ("c");
331 break;
332 case FAT_STRING:
333 printf ("s");
334 break;
335 case FAT_LOCATION:
336 printf ("H");
337 break;
338 case FAT_TREE | FAT_TREE_DECL:
339 printf ("D");
340 break;
341 case FAT_TREE | FAT_TREE_FUNCDECL:
342 printf ("F");
343 break;
344 case FAT_TREE | FAT_TREE_TYPE:
345 printf ("T");
346 break;
347 case FAT_TREE | FAT_TREE_ARGUMENT:
348 printf ("A");
349 break;
350 case FAT_TREE | FAT_TREE_EXPRESSION:
351 printf ("E");
352 break;
353 case FAT_TREE | FAT_TREE_CV:
354 printf ("V");
355 break;
356 case FAT_TREE_CODE:
357 printf ("C");
358 break;
359 case FAT_TREE_CODE | FAT_TREE_CODE_BINOP:
360 printf ("O");
361 break;
362 case FAT_TREE_CODE | FAT_TREE_CODE_ASSOP:
363 printf ("Q");
364 break;
365 case FAT_LANGUAGES:
366 printf ("L");
367 break;
368 default:
369 abort ();
372 printf (")");
376 main ()
378 for (;;)
380 char *line = NULL;
381 size_t line_size = 0;
382 int line_len;
383 char *invalid_reason;
384 void *descr;
386 line_len = getline (&line, &line_size, stdin);
387 if (line_len < 0)
388 break;
389 if (line_len > 0 && line[line_len - 1] == '\n')
390 line[--line_len] = '\0';
392 invalid_reason = NULL;
393 descr = format_parse (line, false, &invalid_reason);
395 format_print (descr);
396 printf ("\n");
397 if (descr == NULL)
398 printf ("%s\n", invalid_reason);
400 free (invalid_reason);
401 free (line);
404 return 0;
408 * For Emacs M-x compile
409 * Local Variables:
410 * 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-gcc-internal.c ../lib/libgettextlib.la"
411 * End:
414 #endif /* TEST */