From: Bruno Haible Date: Mon, 27 Nov 2006 12:46:22 +0000 (+0000) Subject: Add fdi argument to format_parse functions. X-Git-Tag: v0.17~632 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d1092cab08c3241cd227385c848e05362318120d;p=thirdparty%2Fgettext.git Add fdi argument to format_parse functions. --- diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog index 1c3c9f8c5..a050e913b 100644 --- a/gettext-tools/src/ChangeLog +++ b/gettext-tools/src/ChangeLog @@ -1,3 +1,41 @@ +2006-11-26 Bruno Haible + + * format.h (FMTDIR_START, FMTDIR_END, FMTDIR_ERROR): New enum values. + (FDI_SET): New macro. + (struct formatstring_parser): Add fdi argument to 'parse' method. + * format.c (check_msgid_msgstr_format): Update. + * format-awk.c (format_parse): Add fdi argument. Invoke FDI_SET. + * format-boost.c (format_parse): Likewise. + * format-c.c (format_parse): Add fdi argument. Invoke FDI_SET. + (format_c_parse, format_objc_parse): Add fdi argument. + (get_sysdep_c_format_directives): Update. + * format-csharp.c (format_parse): Add fdi argument. Invoke FDI_SET. + * format-elisp.c (format_parse): Likewise. + * format-gcc-internal.c (format_parse): Likewise. + * format-java.c (message_format_parse): Add fdi argument. Invoke + FDI_SET. + (choice_format_parse): Update. + (format_parse): Add fdi argument. + * format-librep.c (format_parse): Add fdi argument. Invoke FDI_SET. + * format-lisp.c (parse_upto): Add fdi argument. Invoke FDI_SET. + (format_parse): Add fdi argument. + * format-pascal.c (format_parse): Add fdi argument. Invoke FDI_SET. + * format-perl.c (format_parse): Likewise. + * format-perl-brace.c (format_parse): Likewise. + * format-php.c (format_parse): Likewise. + * format-python.c (format_parse): Add fdi argument. Invoke FDI_SET. + (get_python_format_unnamed_arg_count): Update. + * format-qt.c (format_parse): Add fdi argument. Invoke FDI_SET. + * format-scheme.c (parse_upto): Add fdi argument. Invoke FDI_SET. + (format_parse): Add fdi argument. + * format-sh.c (format_parse): Add fdi argument. Invoke FDI_SET. + * format-tcl.c (format_parse): Likewise. + * format-ycp.c (format_parse): Likewise. + * msgmerge.c (msgfmt_check_pair_fails): Update. + * read-mo.c (read_mo_file): Update. + * xgettext.c (set_format_flags_from_context, remember_a_message, + remember_a_message_plural): Update. + 2006-11-25 Bruno Haible * message.h (message_list_copy, msgdomain_list_copy): New declarations. diff --git a/gettext-tools/src/format-awk.c b/gettext-tools/src/format-awk.c index 8cdbc5ad4..db3f09e4c 100644 --- a/gettext-tools/src/format-awk.c +++ b/gettext-tools/src/format-awk.c @@ -94,8 +94,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; unsigned int unnumbered_arg_count; struct spec *result; @@ -113,6 +115,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) unsigned int number = 0; enum format_arg_type type; + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (isdigit (*format)) @@ -132,6 +135,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (m == 0) { *invalid_reason = INVALID_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } number = m; @@ -169,6 +173,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_WIDTH_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } width_number = m; @@ -184,6 +189,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -204,6 +210,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -251,6 +258,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_PRECISION_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } precision_number = m; @@ -266,6 +274,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -286,6 +295,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -326,10 +336,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_FLOAT; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -343,6 +360,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -363,6 +381,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -377,6 +396,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) } } + FDI_SET (format, FMTDIR_END); + format++; } @@ -618,7 +639,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-boost.c b/gettext-tools/src/format-boost.c index 8f1e3cbe1..318f4b6bd 100644 --- a/gettext-tools/src/format-boost.c +++ b/gettext-tools/src/format-boost.c @@ -114,8 +114,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; unsigned int unnumbered_arg_count; struct spec *result; @@ -130,6 +132,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format++ == '%') { /* A directive. */ + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (*format == '%') @@ -164,6 +167,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (m == 0) /* can happen if m overflows */ { *invalid_reason = INVALID_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } number = m; @@ -215,6 +219,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_WIDTH_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } width_number = m; @@ -232,6 +237,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -254,6 +260,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -301,6 +308,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_PRECISION_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } precision_number = m; @@ -318,6 +326,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -340,6 +349,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -392,6 +402,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format == '\0') { *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } format++; @@ -410,22 +421,36 @@ format_parse (const char *format, bool translated, char **invalid_reason) /*FALLTHROUGH*/ default: --format; - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec.directives, - *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec.directives, + *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } if (brackets) { if (*format != '|') { - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : xasprintf (_("The directive number %u starts with | but does not end with |."), - spec.directives)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + xasprintf (_("The directive number %u starts with | but does not end with |."), + spec.directives); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } format++; @@ -442,6 +467,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -462,6 +488,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -476,6 +503,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) } } } + + FDI_SET (format - 1, FMTDIR_END); } /* Convert the unnumbered argument array to numbered arguments. */ @@ -718,7 +747,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-c.c b/gettext-tools/src/format-c.c index b953f413a..7c65fe0d6 100644 --- a/gettext-tools/src/format-c.c +++ b/gettext-tools/src/format-c.c @@ -183,8 +183,9 @@ numbered_arg_compare (const void *p1, const void *p2) static void * format_parse (const char *format, bool translated, bool objc_extensions, - char **invalid_reason) + char *fdi, char **invalid_reason) { + const char *const format_start = format; struct spec spec; unsigned int numbered_arg_count; struct numbered_arg *numbered; @@ -208,6 +209,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, format_arg_type_t type; format_arg_type_t size; + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (isdigit (*format)) @@ -227,6 +229,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (m == 0) { *invalid_reason = INVALID_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } number = m; @@ -281,6 +284,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, { *invalid_reason = INVALID_WIDTH_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } width_number = m; @@ -296,6 +300,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (spec.unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -316,6 +321,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -362,6 +368,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, { *invalid_reason = INVALID_PRECISION_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } precision_number = m; @@ -377,6 +384,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (spec.unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -397,6 +405,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -432,18 +441,21 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (*format != 'P') { *invalid_reason = INVALID_C99_MACRO (spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); goto bad_format; } format++; if (*format != 'R') { *invalid_reason = INVALID_C99_MACRO (spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); goto bad_format; } format++; if (*format != 'I') { *invalid_reason = INVALID_C99_MACRO (spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); goto bad_format; } format++; @@ -458,6 +470,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, break; default: *invalid_reason = INVALID_C99_MACRO (spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); goto bad_format; } format++; @@ -501,6 +514,8 @@ format_parse (const char *format, bool translated, bool objc_extensions, else { *invalid_reason = INVALID_C99_MACRO (spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, + FMTDIR_ERROR); goto bad_format; } } @@ -531,6 +546,8 @@ format_parse (const char *format, bool translated, bool objc_extensions, else { *invalid_reason = INVALID_C99_MACRO (spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, + FMTDIR_ERROR); goto bad_format; } } @@ -559,6 +576,8 @@ format_parse (const char *format, bool translated, bool objc_extensions, else { *invalid_reason = INVALID_C99_MACRO (spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, + FMTDIR_ERROR); goto bad_format; } } @@ -568,6 +587,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, { *invalid_reason = xasprintf (_("In the directive number %u, the token after '<' is not followed by '>'."), spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); goto bad_format; } @@ -670,10 +690,17 @@ format_parse (const char *format, bool translated, bool objc_extensions, break; other: default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } } @@ -688,6 +715,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (spec.unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -708,6 +736,7 @@ format_parse (const char *format, bool translated, bool objc_extensions, if (numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -721,6 +750,8 @@ format_parse (const char *format, bool translated, bool objc_extensions, } } + FDI_SET (format, FMTDIR_END); + format++; } @@ -811,15 +842,17 @@ format_parse (const char *format, bool translated, bool objc_extensions, } static void * -format_c_parse (const char *format, bool translated, char **invalid_reason) +format_c_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { - return format_parse (format, translated, false, invalid_reason); + return format_parse (format, translated, false, fdi, invalid_reason); } static void * -format_objc_parse (const char *format, bool translated, char **invalid_reason) +format_objc_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { - return format_parse (format, translated, true, invalid_reason); + return format_parse (format, translated, true, fdi, invalid_reason); } static void @@ -913,7 +946,8 @@ get_sysdep_c_format_directives (const char *string, bool translated, particular language.) */ char *invalid_reason = NULL; struct spec *descr = - (struct spec *) format_parse (string, translated, true, &invalid_reason); + (struct spec *) + format_parse (string, translated, true, NULL, &invalid_reason); if (descr != NULL && descr->sysdep_directives_count > 0) { @@ -1084,7 +1118,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_c_parse (line, false, &invalid_reason); + descr = format_c_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-csharp.c b/gettext-tools/src/format-csharp.c index e72506e3f..0b57d8eda 100644 --- a/gettext-tools/src/format-csharp.c +++ b/gettext-tools/src/format-csharp.c @@ -57,8 +57,10 @@ struct spec }; static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; @@ -71,6 +73,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (c == '{') { + FDI_SET (format - 1, FMTDIR_START); if (*format == '{') format++; else @@ -84,6 +87,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = xasprintf (_("In the directive number %u, '{' is not followed by an argument number."), spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); return NULL; } number = 0; @@ -104,6 +108,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = xasprintf (_("In the directive number %u, ',' is not followed by a number."), spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, + FMTDIR_ERROR); return NULL; } do @@ -123,6 +129,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = xstrdup (_("The string ends in the middle of a directive: found '{' without matching '}'.")); + FDI_SET (format - 1, FMTDIR_ERROR); return NULL; } @@ -132,6 +139,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) (c_isprint (*format) ? xasprintf (_("The directive number %u ends with an invalid character '%c' instead of '}'."), spec.directives, *format) : xasprintf (_("The directive number %u ends with an invalid character instead of '}'."), spec.directives)); + FDI_SET (format, FMTDIR_ERROR); return NULL; } @@ -140,9 +148,11 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.numbered_arg_count <= number) spec.numbered_arg_count = number + 1; } + FDI_SET (format - 1, FMTDIR_END); } else if (c == '}') { + FDI_SET (format - 1, FMTDIR_START); if (*format == '}') format++; else @@ -151,8 +161,10 @@ format_parse (const char *format, bool translated, char **invalid_reason) (spec.directives == 0 ? xstrdup (_("The string starts in the middle of a directive: found '}' without matching '{'.")) : xasprintf (_("The string contains a lone '}' after directive number %u."), spec.directives)); + FDI_SET (*format == '\0' ? format - 1 : format, FMTDIR_ERROR); return NULL; } + FDI_SET (format - 1, FMTDIR_END); } } @@ -259,7 +271,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-elisp.c b/gettext-tools/src/format-elisp.c index b47a26277..34455d81b 100644 --- a/gettext-tools/src/format-elisp.c +++ b/gettext-tools/src/format-elisp.c @@ -95,8 +95,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; unsigned int number; @@ -113,6 +115,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) /* A directive. */ enum format_arg_type type; + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (isdigit (*format)) @@ -207,10 +210,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_OBJECT; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -228,6 +238,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) number++; } + FDI_SET (format, FMTDIR_END); + format++; } @@ -466,7 +478,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-gcc-internal.c b/gettext-tools/src/format-gcc-internal.c index ee15eff83..bbed625ef 100644 --- a/gettext-tools/src/format-gcc-internal.c +++ b/gettext-tools/src/format-gcc-internal.c @@ -157,8 +157,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; unsigned int unnumbered_arg_count; struct spec *result; @@ -174,6 +176,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format++ == '%') { /* A directive. */ + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (*format == '%' || *format == '<' || *format == '>' @@ -209,6 +212,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (m == 0) { *invalid_reason = INVALID_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } number = m; @@ -248,6 +252,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) continue; invalid_flags: *invalid_reason = xasprintf (_("In the directive number %u, the flags combination is invalid."), spec.directives); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; default: break; @@ -275,10 +280,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format != 's') { - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -307,16 +319,19 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (m == 0) { *invalid_reason = INVALID_WIDTH_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } if (unnumbered_arg_count > 0 || number == 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } if (m != number - 1) { *invalid_reason = xasprintf (_("In the directive number %u, the argument number for the precision must be equal to %u."), spec.directives, number - 1); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } precision_number = m; @@ -332,6 +347,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -352,6 +368,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -369,16 +386,25 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_STRING; else { - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + xasprintf (_("In the directive number %u, a precision is not allowed before '%c'."), spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } } else { *invalid_reason = xasprintf (_("In the directive number %u, the precision specification is invalid."), spec.directives); + FDI_SET (*format == '\0' ? format - 1 : format, + FMTDIR_ERROR); goto bad_format; } } @@ -418,17 +444,24 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_TREE | FAT_TREE_CV; else { - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : (*format == 'c' - || *format == 's' - || *format == 'i' || *format == 'd' - || *format == 'o' || *format == 'u' || *format == 'x' - || *format == 'H' - ? xasprintf (_("In the directive number %u, flags are not allowed before '%c'."), spec.directives, *format) - : INVALID_CONVERSION_SPECIFIER (spec.directives, - *format))); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + (*format == 'c' + || *format == 's' + || *format == 'i' || *format == 'd' + || *format == 'o' || *format == 'u' || *format == 'x' + || *format == 'H' + ? xasprintf (_("In the directive number %u, flags are not allowed before '%c'."), spec.directives, *format) + : INVALID_CONVERSION_SPECIFIER (spec.directives, + *format)); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } } @@ -441,6 +474,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (unnumbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -461,6 +495,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.numbered_arg_count > 0) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -475,6 +510,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) } } + FDI_SET (format, FMTDIR_END); + format++; } @@ -784,7 +821,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-java.c b/gettext-tools/src/format-java.c index 38aaaa399..5135e3adb 100644 --- a/gettext-tools/src/format-java.c +++ b/gettext-tools/src/format-java.c @@ -149,9 +149,10 @@ static bool choice_format_parse (const char *format, struct spec *spec, /* Return true if a format is a valid messageFormatPattern. Extracts argument type information into spec. */ static bool -message_format_parse (const char *format, struct spec *spec, +message_format_parse (const char *format, char *fdi, struct spec *spec, char **invalid_reason) { + const char *const format_start = format; bool quoting = false; for (;;) @@ -168,6 +169,7 @@ message_format_parse (const char *format, struct spec *spec, unsigned int number; enum format_arg_type type; + FDI_SET (format, FMTDIR_START); spec->directives++; element_start = ++format; @@ -188,6 +190,7 @@ message_format_parse (const char *format, struct spec *spec, { *invalid_reason = xstrdup (_("The string ends in the middle of a directive: found '{' without matching '}'.")); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } element_end = format++; @@ -201,6 +204,7 @@ message_format_parse (const char *format, struct spec *spec, { *invalid_reason = xasprintf (_("In the directive number %u, '{' is not followed by an argument number."), spec->directives); + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -235,6 +239,7 @@ message_format_parse (const char *format, struct spec *spec, { *invalid_reason = xasprintf (_("In the directive number %u, the substring \"%s\" is not a valid date/time style."), spec->directives, element); + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -245,6 +250,7 @@ message_format_parse (const char *format, struct spec *spec, element -= 4; *invalid_reason = xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element); + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -267,6 +273,7 @@ message_format_parse (const char *format, struct spec *spec, { *invalid_reason = xasprintf (_("In the directive number %u, the substring \"%s\" is not a valid number style."), spec->directives, element); + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -277,6 +284,7 @@ message_format_parse (const char *format, struct spec *spec, element -= 6; *invalid_reason = xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element); + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -294,6 +302,7 @@ message_format_parse (const char *format, struct spec *spec, ; else { + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -304,6 +313,7 @@ message_format_parse (const char *format, struct spec *spec, element -= 6; *invalid_reason = xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element); + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -312,6 +322,7 @@ message_format_parse (const char *format, struct spec *spec, { *invalid_reason = xasprintf (_("In the directive number %u, the argument number is not followed by a comma and one of \"%s\", \"%s\", \"%s\", \"%s\"."), spec->directives, "time", "date", "number", "choice"); + FDI_SET (format - 1, FMTDIR_ERROR); freesa (element_alloced); return false; } @@ -325,12 +336,16 @@ message_format_parse (const char *format, struct spec *spec, spec->numbered[spec->numbered_arg_count].number = number; spec->numbered[spec->numbered_arg_count].type = type; spec->numbered_arg_count++; + + FDI_SET (format - 1, FMTDIR_END); } /* The doc says "ab}de" is invalid. Even though JDK accepts it. */ else if (!quoting && *format == '}') { + FDI_SET (format, FMTDIR_START); *invalid_reason = xstrdup (_("The string starts in the middle of a directive: found '}' without matching '{'.")); + FDI_SET (format, FMTDIR_ERROR); return false; } else if (*format != '\0') @@ -581,7 +596,8 @@ choice_format_parse (const char *format, struct spec *spec, } *mp = '\0'; - msgformat_valid = message_format_parse (msgformat, spec, invalid_reason); + msgformat_valid = + message_format_parse (msgformat, NULL, spec, invalid_reason); freesa (msgformat); @@ -608,7 +624,8 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { struct spec spec; struct spec *result; @@ -618,7 +635,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) spec.allocated = 0; spec.numbered = NULL; - if (!message_format_parse (format, &spec, invalid_reason)) + if (!message_format_parse (format, fdi, &spec, invalid_reason)) goto bad_format; /* Sort the numbered argument array, and eliminate duplicates. */ @@ -852,7 +869,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-librep.c b/gettext-tools/src/format-librep.c index c44c9683e..bd460b7cb 100644 --- a/gettext-tools/src/format-librep.c +++ b/gettext-tools/src/format-librep.c @@ -92,8 +92,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; unsigned int number; @@ -110,6 +112,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) /* A directive. */ enum format_arg_type type; + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (isdigit (*format)) @@ -171,10 +174,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_OBJECT; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -192,6 +202,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) number++; } + FDI_SET (format, FMTDIR_END); + format++; } @@ -427,7 +439,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-lisp.c b/gettext-tools/src/format-lisp.c index 4dd6bbf0d..aa6f64245 100644 --- a/gettext-tools/src/format-lisp.c +++ b/gettext-tools/src/format-lisp.c @@ -2434,6 +2434,7 @@ nocheck_params (struct format_arg_list **listp, spec is the global struct spec. terminator is the directive that terminates this parse. separator specifies if ~; separators are allowed. + fdi is an array to be filled with format directive indicators, or NULL. If the format string is invalid, false is returned and *invalid_reason is set to an error message explaining why. */ static bool @@ -2441,9 +2442,10 @@ parse_upto (const char **formatp, int *positionp, struct format_arg_list **listp, struct format_arg_list **escapep, int *separatorp, struct spec *spec, char terminator, bool separator, - char **invalid_reason) + char *fdi, char **invalid_reason) { const char *format = *formatp; + const char *const format_start = format; int position = *positionp; struct format_arg_list *list = *listp; struct format_arg_list *escape = *escapep; @@ -2456,6 +2458,8 @@ parse_upto (const char **formatp, unsigned int paramcount = 0; struct param *params = NULL; + FDI_SET (format - 1, FMTDIR_START); + /* Count number of directives. */ spec->directives++; @@ -2482,10 +2486,17 @@ parse_upto (const char **formatp, format++; if (!c_isdigit (*format)) { - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1])); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1]); + FDI_SET (format, FMTDIR_ERROR); + } return false; } do @@ -2504,6 +2515,7 @@ parse_upto (const char **formatp, if (*format == '\0') { *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } format++; @@ -2560,7 +2572,10 @@ parse_upto (const char **formatp, case 'S': case 's': /* 22.3.4.2 FORMAT-S-EXPRESSION */ if (!check_params (&list, paramcount, params, 4, IIIC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_OBJECT); break; @@ -2568,7 +2583,10 @@ parse_upto (const char **formatp, case 'W': case 'w': /* 22.3.4.3 FORMAT-WRITE */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_OBJECT); break; @@ -2579,7 +2597,10 @@ parse_upto (const char **formatp, case 'X': case 'x': /* 22.3.2.5 FORMAT-HEXADECIMAL */ if (!check_params (&list, paramcount, params, 4, ICCI, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_INTEGER); break; @@ -2587,7 +2608,10 @@ parse_upto (const char **formatp, case 'R': case 'r': /* 22.3.2.1 FORMAT-RADIX */ if (!check_params (&list, paramcount, params, 5, IICCI, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_INTEGER); break; @@ -2595,7 +2619,10 @@ parse_upto (const char **formatp, case 'P': case 'p': /* 22.3.8.3 FORMAT-PLURAL */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (colon_p) { /* Go back by 1 argument. */ @@ -2609,7 +2636,10 @@ parse_upto (const char **formatp, case 'C': case 'c': /* 22.3.1.1 FORMAT-CHARACTER */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_CHARACTER); break; @@ -2617,7 +2647,10 @@ parse_upto (const char **formatp, case 'F': case 'f': /* 22.3.3.1 FORMAT-FIXED-FLOAT */ if (!check_params (&list, paramcount, params, 5, IIICC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_REAL); break; @@ -2626,7 +2659,10 @@ parse_upto (const char **formatp, case 'G': case 'g': /* 22.3.3.3 FORMAT-GENERAL-FLOAT */ if (!check_params (&list, paramcount, params, 7, IIIICCC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_REAL); break; @@ -2634,7 +2670,10 @@ parse_upto (const char **formatp, case '$': /* 22.3.3.4 FORMAT-DOLLARS-FLOAT */ if (!check_params (&list, paramcount, params, 4, IIIC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_REAL); break; @@ -2646,26 +2685,38 @@ parse_upto (const char **formatp, case 'I': case 'i': /* 22.3.5.3 */ if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } break; case '\n': /* 22.3.9.3 #\Newline */ case '_': /* 22.3.5.1 */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } break; case 'T': case 't': /* 22.3.6.1 FORMAT-TABULATE */ if (!check_params (&list, paramcount, params, 2, II, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } break; case '*': /* 22.3.7.1 FORMAT-GOTO */ if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } { int n; /* value of first parameter */ if (paramcount == 0 @@ -2684,6 +2735,7 @@ parse_upto (const char **formatp, /* invalid argument */ *invalid_reason = xasprintf (_("In the directive number %u, the argument %d is negative."), spec->directives, n); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (atsign_p) @@ -2719,7 +2771,10 @@ parse_upto (const char **formatp, case '?': /* 22.3.7.6 FORMAT-INDIRECTION */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_FORMATSTRING); if (atsign_p) @@ -2737,7 +2792,10 @@ parse_upto (const char **formatp, case '/': /* 22.3.5.4 FORMAT-CALL-USER-FUNCTION */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_OBJECT); while (*format != '\0' && *format != '/') @@ -2746,6 +2804,7 @@ parse_upto (const char **formatp, { *invalid_reason = xstrdup (_("The string ends in the middle of a ~/.../ directive.")); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } format++; @@ -2754,7 +2813,10 @@ parse_upto (const char **formatp, case '(': /* 22.3.8.1 FORMAT-CASE-CONVERSION */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -2762,8 +2824,12 @@ parse_upto (const char **formatp, { if (!parse_upto (formatp, positionp, listp, escapep, NULL, spec, ')', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } } format = *formatp; position = *positionp; @@ -2776,11 +2842,15 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("Found '~%c' without matching '~%c'."), ')', '('); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -2792,6 +2862,7 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("In the directive number %u, both the @ and the : modifiers are given."), spec->directives); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } else if (atsign_p) @@ -2801,7 +2872,10 @@ parse_upto (const char **formatp, if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *escapep = escape; @@ -2823,8 +2897,12 @@ parse_upto (const char **formatp, (list != NULL ? copy_list (list) : NULL); if (!parse_upto (formatp, &sub_position, &sub_list, escapep, NULL, spec, ']', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } if (sub_list != NULL) { if (position >= 0) @@ -2859,7 +2937,10 @@ parse_upto (const char **formatp, if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_OBJECT); @@ -2884,12 +2965,18 @@ parse_upto (const char **formatp, } if (!parse_upto (formatp, &sub_position, &sub_list, escapep, &sub_separator, spec, ']', true, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } if (!sub_separator) { *invalid_reason = xasprintf (_("In the directive number %u, '~:[' is not followed by two clauses, separated by '~;'."), spec->directives); + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); return false; } if (sub_list != NULL) @@ -2904,8 +2991,12 @@ parse_upto (const char **formatp, (list != NULL ? copy_list (list) : NULL); if (!parse_upto (formatp, &sub_position, &sub_list, escapep, NULL, spec, ']', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } if (sub_list != NULL) { if (union_position == -2) @@ -2935,7 +3026,10 @@ parse_upto (const char **formatp, if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } /* If there was no first parameter, an argument is consumed. */ arg_position = -1; @@ -2961,8 +3055,12 @@ parse_upto (const char **formatp, int sub_separator = 0; if (!parse_upto (formatp, &sub_position, &sub_list, escapep, &sub_separator, spec, ']', !last_alternative, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } /* If this alternative is chosen, the argument arg_position is an integer, namely the index of this alternative. */ if (!last_alternative && arg_position >= 0) @@ -3009,11 +3107,15 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("Found '~%c' without matching '~%c'."), ']', '['); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -3023,7 +3125,10 @@ parse_upto (const char **formatp, case '{': /* 22.3.7.4 FORMAT-ITERATION */ if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; { int sub_position = 0; @@ -3034,8 +3139,12 @@ parse_upto (const char **formatp, sub_spec.list = sub_list; if (!parse_upto (formatp, &sub_position, &sub_list, &sub_escape, NULL, &sub_spec, '}', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } spec->directives += sub_spec.directives; /* If the sub-formatstring is empty, except for the terminating @@ -3115,11 +3224,15 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("Found '~%c' without matching '~%c'."), '}', '{'); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -3129,7 +3242,10 @@ parse_upto (const char **formatp, case '<': /* 22.3.6.2, 22.3.5.2 FORMAT-JUSTIFICATION */ if (!check_params (&list, paramcount, params, 4, IIIC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } { struct format_arg_list *sub_escape = NULL; @@ -3142,8 +3258,12 @@ parse_upto (const char **formatp, int sub_separator = 0; if (!parse_upto (formatp, positionp, listp, &sub_escape, &sub_separator, spec, '>', true, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } if (!sub_separator) break; } @@ -3164,11 +3284,15 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("Found '~%c' without matching '~%c'."), '>', '<'); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -3178,7 +3302,10 @@ parse_upto (const char **formatp, case '^': /* 22.3.9.2 FORMAT-UP-AND-OUT */ if (!check_params (&list, paramcount, params, 3, THREE, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0 && list != NULL && is_required (list, position)) /* This ~^ can never be executed. Ignore it. */ break; @@ -3198,19 +3325,26 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("In the directive number %u, '~;' is used in an invalid position."), spec->directives); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (terminator == '>') { if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } } else { if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } } *formatp = format; *positionp = position; @@ -3222,7 +3356,10 @@ parse_upto (const char **formatp, case '!': /* FORMAT-CALL, a CLISP extension */ if (!nocheck_params (&list, paramcount, params, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) { add_req_type_constraint (&list, position++, FAT_FUNCTION); @@ -3232,13 +3369,22 @@ parse_upto (const char **formatp, default: --format; - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec->directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec->directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } return false; } + FDI_SET (format - 1, FMTDIR_END); + free (params); } @@ -3259,7 +3405,8 @@ parse_upto (const char **formatp, /* ============== Top level format string handling functions ============== */ static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { struct spec spec; struct spec *result; @@ -3272,7 +3419,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (!parse_upto (&format, &position, &spec.list, &escape, NULL, &spec, '\0', false, - invalid_reason)) + fdi, invalid_reason)) /* Invalid format string. */ return NULL; @@ -3487,7 +3634,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-pascal.c b/gettext-tools/src/format-pascal.c index 0857aa479..5ba0d0fe0 100644 --- a/gettext-tools/src/format-pascal.c +++ b/gettext-tools/src/format-pascal.c @@ -103,8 +103,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; unsigned int directives; unsigned int numbered_arg_count; unsigned int allocated; @@ -129,6 +131,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format++ == '%') { /* A directive. */ + FDI_SET (format - 1, FMTDIR_START); directives++; if (*format != '%') @@ -241,10 +244,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_INTEGER; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -275,6 +285,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) numbered_arg_count++; } + FDI_SET (format, FMTDIR_END); + format++; } @@ -519,7 +531,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-perl-brace.c b/gettext-tools/src/format-perl-brace.c index dfc45ae19..e72aff13a 100644 --- a/gettext-tools/src/format-perl-brace.c +++ b/gettext-tools/src/format-perl-brace.c @@ -60,8 +60,10 @@ named_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; @@ -91,6 +93,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) const char *name_end = f; size_t n = name_end - name_start; + FDI_SET (format - 1, FMTDIR_START); + name = XNMALLOC (n + 1, char); memcpy (name, name_start, n); name[n] = '\0'; @@ -105,6 +109,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) spec.named[spec.named_arg_count].name = name; spec.named_arg_count++; + FDI_SET (f, FMTDIR_END); + format = ++f; } } @@ -266,7 +272,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-perl.c b/gettext-tools/src/format-perl.c index 1c928099b..c87de485c 100644 --- a/gettext-tools/src/format-perl.c +++ b/gettext-tools/src/format-perl.c @@ -134,8 +134,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; unsigned int directives; unsigned int numbered_arg_count; unsigned int allocated; @@ -158,6 +160,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) format_arg_type_t type; format_arg_type_t size; + FDI_SET (format - 1, FMTDIR_START); directives++; if (isnonzerodigit (*format)) @@ -429,6 +432,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = xasprintf (_("In the directive number %u, the size specifier is incompatible with the conversion specifier '%c'."), directives, *format); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } type = FAT_DOUBLE | size; @@ -440,10 +444,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_COUNT_POINTER | size; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -460,6 +471,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) numbered_arg_count++; } + FDI_SET (format, FMTDIR_END); + format++; } @@ -731,7 +744,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-php.c b/gettext-tools/src/format-php.c index 601a033d5..1b0f4a4b9 100644 --- a/gettext-tools/src/format-php.c +++ b/gettext-tools/src/format-php.c @@ -94,8 +94,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; unsigned int directives; unsigned int numbered_arg_count; unsigned int allocated; @@ -113,6 +115,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format++ == '%') { /* A directive. */ + FDI_SET (format - 1, FMTDIR_START); directives++; if (*format != '%') @@ -139,6 +142,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (m == 0) { *invalid_reason = INVALID_ARGNO_0 (directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } number = m; @@ -158,6 +162,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format == '\0') { *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } format++; @@ -208,10 +213,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_STRING; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -225,6 +237,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) numbered_arg_count++; } + FDI_SET (format, FMTDIR_END); + format++; } @@ -463,7 +477,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-python.c b/gettext-tools/src/format-python.c index e8a973a5f..3c3148910 100644 --- a/gettext-tools/src/format-python.c +++ b/gettext-tools/src/format-python.c @@ -113,8 +113,10 @@ named_arg_compare (const void *p1, const void *p2) xstrdup (_("The string refers to arguments both through argument names and through unnamed argument specifications.")) static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; @@ -132,6 +134,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) char *name = NULL; enum format_arg_type type; + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (*format == '(') @@ -158,6 +161,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format == '\0') { *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } name_end = format++; @@ -180,6 +184,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.named_arg_count > 0) { *invalid_reason = INVALID_MIXES_NAMED_UNNAMED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -208,6 +213,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.named_arg_count > 0) { *invalid_reason = INVALID_MIXES_NAMED_UNNAMED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -246,10 +252,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_FLOAT; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -261,6 +274,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.unnamed_arg_count > 0) { *invalid_reason = INVALID_MIXES_NAMED_UNNAMED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -281,6 +295,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (spec.named_arg_count > 0) { *invalid_reason = INVALID_MIXES_NAMED_UNNAMED (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } @@ -293,6 +308,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) spec.unnamed_arg_count++; } + FDI_SET (format, FMTDIR_END); + format++; } @@ -518,7 +535,7 @@ get_python_format_unnamed_arg_count (const char *string) /* Parse the format string. */ char *invalid_reason = NULL; struct spec *descr = - (struct spec *) format_parse (string, false, &invalid_reason); + (struct spec *) format_parse (string, false, NULL, &invalid_reason); if (descr != NULL) { @@ -639,7 +656,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-qt.c b/gettext-tools/src/format-qt.c index 67aad7a59..90cc0f513 100644 --- a/gettext-tools/src/format-qt.c +++ b/gettext-tools/src/format-qt.c @@ -51,8 +51,10 @@ struct spec static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; @@ -66,6 +68,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) /* A directive. */ unsigned int number; + FDI_SET (format - 1, FMTDIR_START); spec.directives++; number = *format - '0'; @@ -76,10 +79,13 @@ format_parse (const char *format, bool translated, char **invalid_reason) { *invalid_reason = xasprintf (_("Multiple references to %%%c."), *format); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } spec.args_used[number] = true; + FDI_SET (format, FMTDIR_END); + format++; } @@ -201,7 +207,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-scheme.c b/gettext-tools/src/format-scheme.c index 78ee865b9..bc021b9d6 100644 --- a/gettext-tools/src/format-scheme.c +++ b/gettext-tools/src/format-scheme.c @@ -2437,6 +2437,7 @@ check_params (struct format_arg_list **listp, spec is the global struct spec. terminator is the directive that terminates this parse. separator specifies if ~; separators are allowed. + fdi is an array to be filled with format directive indicators, or NULL. If the format string is invalid, false is returned and *invalid_reason is set to an error message explaining why. */ static bool @@ -2444,9 +2445,10 @@ parse_upto (const char **formatp, int *positionp, struct format_arg_list **listp, struct format_arg_list **escapep, int *separatorp, struct spec *spec, char terminator, bool separator, - char **invalid_reason) + char *fdi, char **invalid_reason) { const char *format = *formatp; + const char *const format_start = format; int position = *positionp; struct format_arg_list *list = *listp; struct format_arg_list *escape = *escapep; @@ -2459,6 +2461,8 @@ parse_upto (const char **formatp, unsigned int paramcount = 0; struct param *params = NULL; + FDI_SET (format - 1, FMTDIR_START); + /* Count number of directives. */ spec->directives++; @@ -2485,10 +2489,17 @@ parse_upto (const char **formatp, format++; if (!c_isdigit (*format)) { - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1])); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + xasprintf (_("In the directive number %u, '%c' is not followed by a digit."), spec->directives, format[-1]); + FDI_SET (format, FMTDIR_ERROR); + } return false; } do @@ -2507,6 +2518,7 @@ parse_upto (const char **formatp, if (*format == '\0') { *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } format++; @@ -2563,7 +2575,10 @@ parse_upto (const char **formatp, case 'S': case 's': /* 22.3.4.2 FORMAT-S-EXPRESSION */ if (!check_params (&list, paramcount, params, 4, IIIC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_OBJECT); break; @@ -2571,7 +2586,10 @@ parse_upto (const char **formatp, case 'C': case 'c': /* FORMAT-CHARACTER */ if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (paramcount == 0 || (paramcount == 1 && params[0].type == PT_NIL)) if (position >= 0) @@ -2584,7 +2602,10 @@ parse_upto (const char **formatp, case 'X': case 'x': /* 22.3.2.5 FORMAT-HEXADECIMAL */ if (!check_params (&list, paramcount, params, 4, ICCI, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_INTEGER); break; @@ -2592,7 +2613,10 @@ parse_upto (const char **formatp, case 'R': case 'r': /* 22.3.2.1 FORMAT-RADIX */ if (!check_params (&list, paramcount, params, 5, IICCI, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_INTEGER); break; @@ -2600,7 +2624,10 @@ parse_upto (const char **formatp, case 'P': case 'p': /* 22.3.8.3 FORMAT-PLURAL */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (colon_p) { /* Go back by 1 argument. */ @@ -2614,7 +2641,10 @@ parse_upto (const char **formatp, case 'F': case 'f': /* 22.3.3.1 FORMAT-FIXED-FLOAT */ if (!check_params (&list, paramcount, params, 5, IIICC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_REAL); break; @@ -2623,7 +2653,10 @@ parse_upto (const char **formatp, case 'G': case 'g': /* 22.3.3.3 FORMAT-GENERAL-FLOAT */ if (!check_params (&list, paramcount, params, 7, IIIICCC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_REAL); break; @@ -2631,7 +2664,10 @@ parse_upto (const char **formatp, case '$': /* 22.3.3.4 FORMAT-DOLLARS-FLOAT */ if (!check_params (&list, paramcount, params, 4, IIIC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_REAL); break; @@ -2639,7 +2675,10 @@ parse_upto (const char **formatp, case 'I': case 'i': /* FORMAT-FIXED-FLOAT-COMPLEX */ if (!check_params (&list, paramcount, params, 5, IIICC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_COMPLEX); break; @@ -2647,7 +2686,10 @@ parse_upto (const char **formatp, case 'Y': case 'y': /* FORMAT-PRETTY */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_OBJECT); break; @@ -2660,7 +2702,10 @@ parse_upto (const char **formatp, case '~': /* 22.3.1.5 FORMAT-TILDE */ if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } break; case '!': /* FORMAT-FORCE-OUTPUT */ @@ -2668,19 +2713,28 @@ parse_upto (const char **formatp, case 'Q': case 'q': /* FORMAT-IMPLEMENTATION */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } break; case 'T': case 't': /* FORMAT-TABULATE */ if (!check_params (&list, paramcount, params, 3, IIC, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } break; case '*': /* 22.3.7.1 FORMAT-GOTO */ if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } { int n; /* value of first parameter */ if (paramcount == 0 @@ -2699,6 +2753,7 @@ parse_upto (const char **formatp, /* invalid argument */ *invalid_reason = xasprintf (_("In the directive number %u, the argument %d is negative."), spec->directives, n); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (atsign_p) @@ -2734,7 +2789,10 @@ parse_upto (const char **formatp, case '?': case 'K': case 'k': /* 22.3.7.6 FORMAT-INDIRECTION */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_FORMATSTRING); if (atsign_p) @@ -2752,7 +2810,10 @@ parse_upto (const char **formatp, case '(': /* 22.3.8.1 FORMAT-CASE-CONVERSION */ if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -2760,8 +2821,12 @@ parse_upto (const char **formatp, { if (!parse_upto (formatp, positionp, listp, escapep, NULL, spec, ')', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } } format = *formatp; position = *positionp; @@ -2774,11 +2839,15 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("Found '~%c' without matching '~%c'."), ')', '('); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -2790,6 +2859,7 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("In the directive number %u, both the @ and the : modifiers are given."), spec->directives); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } else if (atsign_p) @@ -2799,7 +2869,10 @@ parse_upto (const char **formatp, if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *escapep = escape; @@ -2821,8 +2894,12 @@ parse_upto (const char **formatp, (list != NULL ? copy_list (list) : NULL); if (!parse_upto (formatp, &sub_position, &sub_list, escapep, NULL, spec, ']', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } if (sub_list != NULL) { if (position >= 0) @@ -2857,7 +2934,10 @@ parse_upto (const char **formatp, if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0) add_req_type_constraint (&list, position++, FAT_OBJECT); @@ -2882,12 +2962,18 @@ parse_upto (const char **formatp, } if (!parse_upto (formatp, &sub_position, &sub_list, escapep, &sub_separator, spec, ']', true, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } if (!sub_separator) { *invalid_reason = xasprintf (_("In the directive number %u, '~:[' is not followed by two clauses, separated by '~;'."), spec->directives); + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); return false; } if (sub_list != NULL) @@ -2902,8 +2988,12 @@ parse_upto (const char **formatp, (list != NULL ? copy_list (list) : NULL); if (!parse_upto (formatp, &sub_position, &sub_list, escapep, NULL, spec, ']', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } if (sub_list != NULL) { if (union_position == -2) @@ -2933,7 +3023,10 @@ parse_upto (const char **formatp, if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } /* If there was no first parameter, an argument is consumed. */ arg_position = -1; @@ -2959,8 +3052,12 @@ parse_upto (const char **formatp, int sub_separator = 0; if (!parse_upto (formatp, &sub_position, &sub_list, escapep, &sub_separator, spec, ']', !last_alternative, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } /* If this alternative is chosen, the argument arg_position is an integer, namely the index of this alternative. */ if (!last_alternative && arg_position >= 0) @@ -3007,11 +3104,15 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("Found '~%c' without matching '~%c'."), ']', '['); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -3021,7 +3122,10 @@ parse_upto (const char **formatp, case '{': /* 22.3.7.4 FORMAT-ITERATION */ if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; { int sub_position = 0; @@ -3032,8 +3136,12 @@ parse_upto (const char **formatp, sub_spec.list = sub_list; if (!parse_upto (formatp, &sub_position, &sub_list, &sub_escape, NULL, &sub_spec, '}', false, - invalid_reason)) - return false; + NULL, invalid_reason)) + { + FDI_SET (**formatp == '\0' ? *formatp - 1 : *formatp, + FMTDIR_ERROR); + return false; + } spec->directives += sub_spec.directives; /* If the sub-formatstring is empty, except for the terminating @@ -3113,11 +3221,15 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("Found '~%c' without matching '~%c'."), '}', '{'); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } *formatp = format; *positionp = position; *listp = list; @@ -3127,7 +3239,10 @@ parse_upto (const char **formatp, case '^': /* 22.3.9.2 FORMAT-UP-AND-OUT */ if (!check_params (&list, paramcount, params, 3, THREE, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } if (position >= 0 && list != NULL && is_required (list, position)) /* This ~^ can never be executed. Ignore it. */ break; @@ -3147,19 +3262,26 @@ parse_upto (const char **formatp, { *invalid_reason = xasprintf (_("In the directive number %u, '~;' is used in an invalid position."), spec->directives); + FDI_SET (format - 1, FMTDIR_ERROR); return false; } if (terminator == '>') { if (!check_params (&list, paramcount, params, 1, I, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } } else { if (!check_params (&list, paramcount, params, 0, NULL, spec->directives, invalid_reason)) - return false; + { + FDI_SET (format - 1, FMTDIR_ERROR); + return false; + } } *formatp = format; *positionp = position; @@ -3170,13 +3292,22 @@ parse_upto (const char **formatp, default: --format; - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec->directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec->directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } return false; } + FDI_SET (format - 1, FMTDIR_END); + free (params); } @@ -3197,7 +3328,8 @@ parse_upto (const char **formatp, /* ============== Top level format string handling functions ============== */ static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { struct spec spec; struct spec *result; @@ -3210,7 +3342,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (!parse_upto (&format, &position, &spec.list, &escape, NULL, &spec, '\0', false, - invalid_reason)) + fdi, invalid_reason)) /* Invalid format string. */ return NULL; @@ -3425,7 +3557,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-sh.c b/gettext-tools/src/format-sh.c index 8390e7226..097be8c4b 100644 --- a/gettext-tools/src/format-sh.c +++ b/gettext-tools/src/format-sh.c @@ -86,8 +86,10 @@ named_arg_compare (const void *p1, const void *p2) xstrdup (_("The string refers to a shell variable with an empty name.")) static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; @@ -102,6 +104,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) /* A variable substitution. */ char *name; + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (*format == '{') @@ -118,6 +121,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (!c_isascii (*format)) { *invalid_reason = INVALID_NON_ASCII_VARIABLE (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } if (format > name_start @@ -125,18 +129,21 @@ format_parse (const char *format, bool translated, char **invalid_reason) || *format == '?' || *format == ':')) { *invalid_reason = INVALID_SHELL_SYNTAX (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } if (!(c_isalnum (*format) || *format == '_') || (format == name_start && c_isdigit (*format))) { *invalid_reason = INVALID_CONTEXT_DEPENDENT_VARIABLE (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } } if (*format == '\0') { *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } name_end = format++; @@ -145,6 +152,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (n == 0) { *invalid_reason = INVALID_EMPTY_VARIABLE (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } name = XNMALLOC (n + 1, char); @@ -173,17 +181,20 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (!c_isascii (*format)) { *invalid_reason = INVALID_NON_ASCII_VARIABLE (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } else { *invalid_reason = INVALID_CONTEXT_DEPENDENT_VARIABLE (); + FDI_SET (format, FMTDIR_ERROR); goto bad_format; } } else { *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } @@ -195,6 +206,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) } spec.named[spec.named_arg_count].name = name; spec.named_arg_count++; + + FDI_SET (format - 1, FMTDIR_END); } /* Sort the named argument array, and eliminate duplicates. */ @@ -367,7 +380,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-tcl.c b/gettext-tools/src/format-tcl.c index f98add8a9..35831f148 100644 --- a/gettext-tools/src/format-tcl.c +++ b/gettext-tools/src/format-tcl.c @@ -98,8 +98,10 @@ numbered_arg_compare (const void *p1, const void *p2) } static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; bool seen_numbered_arg; @@ -118,6 +120,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format++ == '%') { /* A directive. */ + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (*format != '%') @@ -144,6 +147,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (m == 0) { *invalid_reason = INVALID_ARGNO_0 (spec.directives); + FDI_SET (f, FMTDIR_ERROR); goto bad_format; } number = m; @@ -153,6 +157,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (seen_unnumbered_arg) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } is_numbered_arg = true; @@ -166,6 +171,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (seen_numbered_arg) { *invalid_reason = INVALID_MIXES_NUMBERED_UNNUMBERED (); + FDI_SET (format - 1, FMTDIR_ERROR); goto bad_format; } seen_unnumbered_arg = true; @@ -248,10 +254,17 @@ format_parse (const char *format, bool translated, char **invalid_reason) type = FAT_FLOAT; break; default: - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : INVALID_CONVERSION_SPECIFIER (spec.directives, *format)); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + INVALID_CONVERSION_SPECIFIER (spec.directives, *format); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } @@ -267,6 +280,8 @@ format_parse (const char *format, bool translated, char **invalid_reason) number++; } + FDI_SET (format, FMTDIR_END); + format++; } @@ -511,7 +526,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format-ycp.c b/gettext-tools/src/format-ycp.c index 8929cffaa..7f8f83d56 100644 --- a/gettext-tools/src/format-ycp.c +++ b/gettext-tools/src/format-ycp.c @@ -48,8 +48,10 @@ struct spec static void * -format_parse (const char *format, bool translated, char **invalid_reason) +format_parse (const char *format, bool translated, char *fdi, + char **invalid_reason) { + const char *const format_start = format; struct spec spec; struct spec *result; @@ -60,6 +62,7 @@ format_parse (const char *format, bool translated, char **invalid_reason) if (*format++ == '%') { /* A directive. */ + FDI_SET (format - 1, FMTDIR_START); spec.directives++; if (*format == '%') @@ -76,14 +79,23 @@ format_parse (const char *format, bool translated, char **invalid_reason) } else { - *invalid_reason = - (*format == '\0' - ? INVALID_UNTERMINATED_DIRECTIVE () - : (c_isprint (*format) - ? xasprintf (_("In the directive number %u, the character '%c' is not a digit between 1 and 9."), spec.directives, *format) - : xasprintf (_("The character that terminates the directive number %u is not a digit between 1 and 9."), spec.directives))); + if (*format == '\0') + { + *invalid_reason = INVALID_UNTERMINATED_DIRECTIVE (); + FDI_SET (format - 1, FMTDIR_ERROR); + } + else + { + *invalid_reason = + (c_isprint (*format) + ? xasprintf (_("In the directive number %u, the character '%c' is not a digit between 1 and 9."), spec.directives, *format) + : xasprintf (_("The character that terminates the directive number %u is not a digit between 1 and 9."), spec.directives)); + FDI_SET (format, FMTDIR_ERROR); + } goto bad_format; } + + FDI_SET (format - 1, FMTDIR_END); } result = XMALLOC (struct spec); @@ -212,7 +224,7 @@ main () line[--line_len] = '\0'; invalid_reason = NULL; - descr = format_parse (line, false, &invalid_reason); + descr = format_parse (line, false, NULL, &invalid_reason); format_print (descr); printf ("\n"); diff --git a/gettext-tools/src/format.c b/gettext-tools/src/format.c index 198707a3f..2e4fbac6f 100644 --- a/gettext-tools/src/format.c +++ b/gettext-tools/src/format.c @@ -99,7 +99,7 @@ check_msgid_msgstr_format (const char *msgid, const char *msgid_plural, char *invalid_reason = NULL; void *msgid_descr = parser->parse (msgid_plural != NULL ? msgid_plural : msgid, - false, &invalid_reason); + false, NULL, &invalid_reason); if (msgid_descr != NULL) { @@ -119,7 +119,7 @@ check_msgid_msgstr_format (const char *msgid, const char *msgid_plural, pretty_msgstr = buf; } - msgstr_descr = parser->parse (p, true, &invalid_reason); + msgstr_descr = parser->parse (p, true, NULL, &invalid_reason); if (msgstr_descr != NULL) { diff --git a/gettext-tools/src/format.h b/gettext-tools/src/format.h index 112f1ae20..6502325a4 100644 --- a/gettext-tools/src/format.h +++ b/gettext-tools/src/format.h @@ -31,6 +31,26 @@ extern "C" { #endif +/* These indicators are set by the parse function at the appropriate + positions. */ +enum +{ + /* Set on the first byte of a format directive. */ + FMTDIR_START = 1 << 0, + /* Set on the last byte of a format directive. */ + FMTDIR_END = 1 << 1, + /* Set on the last byte of an invalid format directive, where a parse error + was recognized. */ + FMTDIR_ERROR = 1 << 2 +}; + +/* Macro for use inside a parser: + Sets an indicator at the position corresponding to PTR. + Assumes local variables 'fdi' and 'format_start' are defined. */ +#define FDI_SET(ptr, flag) \ + if (fdi != NULL) \ + fdi[(ptr) - format_start] |= (flag)/*;*/ + /* This type of callback is responsible for showing an error. */ typedef void (*formatstring_error_logger_t) (const char *format, ...) #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) @@ -44,12 +64,14 @@ struct formatstring_parser /* Parse the given string as a format string. If translated is true, some extensions available only to msgstr but not to msgid strings are recognized. + If fdi is non-NULL, it must be a an array of strlen (string) zero bytes. Return a freshly allocated structure describing 1. the argument types/names needed for the format string, 2. the total number of format directives. Return NULL if the string is not a valid format string. In this case, - also set *invalid_reason to an error message explaining why. */ - void * (*parse) (const char *string, bool translated, char **invalid_reason); + also set *invalid_reason to an error message explaining why. + In both cases, set FMTDIR_* bits at the appropriate positions in fdi. */ + void * (*parse) (const char *string, bool translated, char *fdi, char **invalid_reason); /* Free a format string descriptor, returned by parse(). */ void (*free) (void *descr); diff --git a/gettext-tools/src/msgmerge.c b/gettext-tools/src/msgmerge.c index e51a62e7e..ad12d3774 100644 --- a/gettext-tools/src/msgmerge.c +++ b/gettext-tools/src/msgmerge.c @@ -738,7 +738,7 @@ msgfmt_check_pair_fails (const lex_pos_ty *pos, struct formatstring_parser *parser = formatstring_parsers[fmt]; char *invalid_reason = NULL; void *msgid_descr = - parser->parse (msgid_plural != NULL ? msgid_plural : msgid, false, + parser->parse (msgid_plural != NULL ? msgid_plural : msgid, false, NULL, &invalid_reason); failure = false; @@ -749,7 +749,8 @@ msgfmt_check_pair_fails (const lex_pos_ty *pos, for (p = msgstr; p < p_end; p += strlen (p) + 1) { - void *msgstr_descr = parser->parse (msgstr, true, &invalid_reason); + void *msgstr_descr = + parser->parse (msgstr, true, NULL, &invalid_reason); if (msgstr_descr != NULL) { diff --git a/gettext-tools/src/read-mo.c b/gettext-tools/src/read-mo.c index 6f2b392f8..7129e2692 100644 --- a/gettext-tools/src/read-mo.c +++ b/gettext-tools/src/read-mo.c @@ -404,7 +404,8 @@ read_mo_file (message_list_ty *mlp, const char *filename) for (str = msgid; str < str_end; str += strlen (str) + 1) { char *invalid_reason = NULL; - void *descr = parser->parse (str, false, &invalid_reason); + void *descr = + parser->parse (str, false, NULL, &invalid_reason); if (descr != NULL) parser->free (descr); @@ -422,7 +423,7 @@ read_mo_file (message_list_ty *mlp, const char *filename) { char *invalid_reason = NULL; void *descr = - parser->parse (str, true, &invalid_reason); + parser->parse (str, true, NULL, &invalid_reason); if (descr != NULL) parser->free (descr); diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index 49bede3cf..be4bec15f 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -1899,7 +1899,7 @@ set_format_flags_from_context (enum is_format is_format[NFORMATS], { struct formatstring_parser *parser = formatstring_parsers[i]; char *invalid_reason = NULL; - void *descr = parser->parse (string, false, &invalid_reason); + void *descr = parser->parse (string, false, NULL, &invalid_reason); if (descr != NULL) parser->free (descr); @@ -2156,7 +2156,7 @@ meta information, not the empty string.\n"))); { struct formatstring_parser *parser = formatstring_parsers[i]; char *invalid_reason = NULL; - void *descr = parser->parse (mp->msgid, false, &invalid_reason); + void *descr = parser->parse (mp->msgid, false, NULL, &invalid_reason); if (descr != NULL) { @@ -2269,7 +2269,7 @@ remember_a_message_plural (message_ty *mp, char *string, struct formatstring_parser *parser = formatstring_parsers[i]; char *invalid_reason = NULL; void *descr = - parser->parse (mp->msgid_plural, false, &invalid_reason); + parser->parse (mp->msgid_plural, false, NULL, &invalid_reason); if (descr != NULL) {