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)
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. */
30
#include "format-invalid.h"
32
#include "error-progname.h"
35
#define _(str) gettext (str)
37
/* GCC internal format strings consist of language frontend independent
38
format directives, implemented in gcc-3.3/gcc/diagnostic.c (function
39
output_format), plus some frontend dependent extensions:
40
- for the C/ObjC frontend in gcc-3.3/gcc/c-objc-common.c
41
- for the C++ frontend in gcc-3.3/gcc/cp/error.c
42
Taking these together, GCC internal format strings are specified as follows.
45
- is optionally followed by a size specifier 'l',
46
- is optionally followed by '+' (only the specifiers of gcc/cp/error.c),
47
- is optionally followed by '#' (only the specifiers of gcc/cp/error.c),
48
- is finished by a specifier
50
- '%', that needs no argument,
51
- 'c', that needs a character argument,
52
- 's', that needs a string argument,
53
- 'i', 'd', that need a signed integer argument,
54
- 'o', 'u', 'x', that need an unsigned integer argument,
55
- '.*s', that needs a signed integer argument and a string argument,
56
- 'H', that needs a 'location_t *' argument,
57
[see gcc/diagnostic.c]
59
- 'D', that needs a general declaration argument,
60
- 'F', that needs a function declaration argument,
61
- 'T', that needs a type argument,
62
[see gcc/c-objc-common.c and gcc/cp/error.c]
64
- 'A', that needs a function argument list argument,
65
- 'C', that needs a tree code argument,
66
- 'E', that needs an expression argument,
67
- 'L', that needs a language argument,
68
- 'O', that needs a binary operator argument,
69
- 'P', that needs a function parameter argument,
70
- 'Q', that needs an assignment operator argument,
71
- 'V', that needs a const/volatile qualifier argument.
87
FAT_UNSIGNED = 1 << 3,
88
FAT_SIZE_LONG = 1 << 4,
89
FAT_TREE_DECL = 1 << 5,
90
FAT_TREE_FUNCDECL = 2 << 5,
91
FAT_TREE_TYPE = 3 << 5,
92
FAT_TREE_ARGUMENT = 4 << 5,
93
FAT_TREE_EXPRESSION = 5 << 5,
95
FAT_TREE_CODE_BINOP = 1 << 8,
96
FAT_TREE_CODE_ASSOP = 2 << 8,
97
FAT_FUNCPARAM = 1 << 10
100
struct unnumbered_arg
102
enum format_arg_type type;
107
unsigned int directives;
108
unsigned int unnumbered_arg_count;
109
unsigned int allocated;
110
struct unnumbered_arg *unnumbered;
115
format_parse (const char *format, bool translated, char **invalid_reason)
121
spec.unnumbered_arg_count = 0;
123
spec.unnumbered = NULL;
125
for (; *format != '\0';)
126
if (*format++ == '%')
129
enum format_arg_type size;
138
size = FAT_SIZE_LONG;
143
enum format_arg_type type;
147
else if (*format == 's')
149
else if (*format == 'i' || *format == 'd')
150
type = FAT_INTEGER | size;
151
else if (*format == 'o' || *format == 'u' || *format == 'x')
152
type = FAT_INTEGER | FAT_UNSIGNED | size;
153
else if (*format == '.' && format[1] == '*' && format[2] == 's')
155
if (spec.allocated == spec.unnumbered_arg_count)
157
spec.allocated = 2 * spec.allocated + 1;
158
spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
160
spec.unnumbered[spec.unnumbered_arg_count].type = FAT_INTEGER;
161
spec.unnumbered_arg_count++;
164
else if (*format == 'H')
173
type = FAT_TREE | FAT_TREE_DECL;
174
else if (*format == 'F')
175
type = FAT_TREE | FAT_TREE_FUNCDECL;
176
else if (*format == 'T')
177
type = FAT_TREE | FAT_TREE_TYPE;
178
else if (*format == 'A')
179
type = FAT_TREE | FAT_TREE_ARGUMENT;
180
else if (*format == 'C')
181
type = FAT_TREE_CODE;
182
else if (*format == 'E')
183
type = FAT_TREE | FAT_TREE_EXPRESSION;
184
else if (*format == 'L')
185
type = FAT_LANGUAGES;
186
else if (*format == 'O')
187
type = FAT_TREE_CODE | FAT_TREE_CODE_BINOP;
188
else if (*format == 'P')
189
type = FAT_INTEGER | FAT_FUNCPARAM;
190
else if (*format == 'Q')
191
type = FAT_TREE_CODE | FAT_TREE_CODE_ASSOP;
192
else if (*format == 'V')
193
type = FAT_TREE | FAT_TREE_CV;
198
? INVALID_UNTERMINATED_DIRECTIVE ()
201
|| *format == 'i' || *format == 'd'
202
|| *format == 'o' || *format == 'u' || *format == 'x'
204
? xasprintf (_("In the directive number %u, flags are not allowed before '%c'."), spec.directives, *format)
205
: INVALID_CONVERSION_SPECIFIER (spec.directives,
211
if (spec.allocated == spec.unnumbered_arg_count)
213
spec.allocated = 2 * spec.allocated + 1;
214
spec.unnumbered = (struct unnumbered_arg *) xrealloc (spec.unnumbered, spec.allocated * sizeof (struct unnumbered_arg));
216
spec.unnumbered[spec.unnumbered_arg_count].type = type;
217
spec.unnumbered_arg_count++;
223
result = (struct spec *) xmalloc (sizeof (struct spec));
228
if (spec.unnumbered != NULL)
229
free (spec.unnumbered);
234
format_free (void *descr)
236
struct spec *spec = (struct spec *) descr;
238
if (spec->unnumbered != NULL)
239
free (spec->unnumbered);
244
format_get_number_of_directives (void *descr)
246
struct spec *spec = (struct spec *) descr;
248
return spec->directives;
252
format_check (const lex_pos_ty *pos, void *msgid_descr, void *msgstr_descr,
253
bool equality, bool noisy, const char *pretty_msgstr)
255
struct spec *spec1 = (struct spec *) msgid_descr;
256
struct spec *spec2 = (struct spec *) msgstr_descr;
260
/* Check the argument types are the same. */
262
? spec1->unnumbered_arg_count != spec2->unnumbered_arg_count
263
: spec1->unnumbered_arg_count < spec2->unnumbered_arg_count)
267
error_with_progname = false;
268
error_at_line (0, 0, pos->file_name, pos->line_number,
269
_("number of format specifications in 'msgid' and '%s' does not match"),
271
error_with_progname = true;
276
for (i = 0; i < spec2->unnumbered_arg_count; i++)
277
if (spec1->unnumbered[i].type != spec2->unnumbered[i].type)
281
error_with_progname = false;
282
error_at_line (0, 0, pos->file_name, pos->line_number,
283
_("format specifications in 'msgid' and '%s' for argument %u are not the same"),
284
pretty_msgstr, i + 1);
285
error_with_progname = true;
294
struct formatstring_parser formatstring_gcc_internal =
298
format_get_number_of_directives,
305
/* Test program: Print the argument list specification returned by
306
format_parse for strings read from standard input. */
312
format_print (void *descr)
314
struct spec *spec = (struct spec *) descr;
324
for (i = 0; i < spec->unnumbered_arg_count; i++)
328
if (spec->unnumbered[i].type & FAT_UNSIGNED)
329
printf ("[unsigned]");
330
if (spec->unnumbered[i].type & FAT_SIZE_LONG)
332
switch (spec->unnumbered[i].type & ~(FAT_UNSIGNED | FAT_SIZE_LONG))
337
case FAT_INTEGER | FAT_FUNCPARAM:
349
case FAT_TREE | FAT_TREE_DECL:
352
case FAT_TREE | FAT_TREE_FUNCDECL:
355
case FAT_TREE | FAT_TREE_TYPE:
358
case FAT_TREE | FAT_TREE_ARGUMENT:
361
case FAT_TREE | FAT_TREE_EXPRESSION:
364
case FAT_TREE | FAT_TREE_CV:
370
case FAT_TREE_CODE | FAT_TREE_CODE_BINOP:
373
case FAT_TREE_CODE | FAT_TREE_CODE_ASSOP:
392
size_t line_size = 0;
394
char *invalid_reason;
397
line_len = getline (&line, &line_size, stdin);
400
if (line_len > 0 && line[line_len - 1] == '\n')
401
line[--line_len] = '\0';
403
invalid_reason = NULL;
404
descr = format_parse (line, false, &invalid_reason);
406
format_print (descr);
409
printf ("%s\n", invalid_reason);
411
free (invalid_reason);
419
* For Emacs M-x compile
421
* 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"