From: Bruno Haible Date: Wed, 7 Jun 2023 16:57:37 +0000 (+0200) Subject: xgettext: Avoid side effects of the Vala extractor on the C extractor. X-Git-Tag: v0.22~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c1f24ed01d9f39b812c898603c7ab84b39a434fc;p=thirdparty%2Fgettext.git xgettext: Avoid side effects of the Vala extractor on the C extractor. * gettext-tools/src/xgettext.h (xgettext_record_flag): Add more comments. * gettext-tools/src/xgettext.c (xgettext_record_flag): Parse an optional '!BACKEND' suffix. When present, limit the effects of c-format related flags to the specified flag table(s). * gettext-tools/src/x-vala.c (init_flag_table_vala): Append '!Vala' to all xgettext_record_flag arguments. * gettext-tools/tests/xgettext-c-format-6: New file. * gettext-tools/tests/Makefile.am (TESTS): Add it. --- diff --git a/gettext-tools/src/x-vala.c b/gettext-tools/src/x-vala.c index 64cc4fd75..6f5485387 100644 --- a/gettext-tools/src/x-vala.c +++ b/gettext-tools/src/x-vala.c @@ -128,24 +128,25 @@ init_keywords () void init_flag_table_vala () { - xgettext_record_flag ("dgettext:2:pass-c-format"); - xgettext_record_flag ("dcgettext:2:pass-c-format"); - xgettext_record_flag ("ngettext:1:pass-c-format"); - xgettext_record_flag ("ngettext:2:pass-c-format"); - xgettext_record_flag ("dngettext:2:pass-c-format"); - xgettext_record_flag ("dngettext:3:pass-c-format"); - xgettext_record_flag ("dpgettext:2:pass-c-format"); - xgettext_record_flag ("dpgettext2:3:pass-c-format"); - xgettext_record_flag ("_:1:pass-c-format"); - xgettext_record_flag ("Q_:1:pass-c-format"); - xgettext_record_flag ("N_:1:pass-c-format"); - xgettext_record_flag ("NC_:2:pass-c-format"); - /* Vala leaves string formatting to Glib functions and thus the format string is exactly same as C. See also vapi/glib-2.0.vapi. */ - xgettext_record_flag ("printf:1:c-format"); - xgettext_record_flag ("vprintf:1:c-format"); + + xgettext_record_flag ("dgettext:2:pass-c-format!Vala"); + xgettext_record_flag ("dcgettext:2:pass-c-format!Vala"); + xgettext_record_flag ("ngettext:1:pass-c-format!Vala"); + xgettext_record_flag ("ngettext:2:pass-c-format!Vala"); + xgettext_record_flag ("dngettext:2:pass-c-format!Vala"); + xgettext_record_flag ("dngettext:3:pass-c-format!Vala"); + xgettext_record_flag ("dpgettext:2:pass-c-format!Vala"); + xgettext_record_flag ("dpgettext2:3:pass-c-format!Vala"); + xgettext_record_flag ("_:1:pass-c-format!Vala"); + xgettext_record_flag ("Q_:1:pass-c-format!Vala"); + xgettext_record_flag ("N_:1:pass-c-format!Vala"); + xgettext_record_flag ("NC_:2:pass-c-format!Vala"); + + xgettext_record_flag ("printf:1:c-format!Vala"); + xgettext_record_flag ("vprintf:1:c-format!Vala"); } diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index c3534ad14..27f703f59 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -1415,7 +1415,9 @@ xgettext_record_flag (const char *optionstring) const char *name_end = colon1; const char *argnum_start = colon1 + 1; const char *argnum_end = colon2; - const char *flag = colon2 + 1; + const char *flag_start = colon2 + 1; + const char *flag_end; + const char *backend; int argnum; /* Check the parts' syntax. */ @@ -1432,29 +1434,38 @@ xgettext_record_flag (const char *optionstring) if (argnum <= 0) goto err; + flag_end = strchr (flag_start, '!'); + if (flag_end != NULL) + backend = flag_end + 1; + else + { + flag_end = flag_start + strlen (flag_start); + backend = NULL; + } + /* Analyze the flag part. */ { bool pass; pass = false; - if (strlen (flag) >= 5 && memcmp (flag, "pass-", 5) == 0) + if (flag_end - flag_start >= 5 && memcmp (flag_start, "pass-", 5) == 0) { pass = true; - flag += 5; + flag_start += 5; } /* Unlike po_parse_comment_special(), we don't accept "fuzzy", "wrap", or "check" here - it has no sense. */ - if (strlen (flag) >= 7 - && memcmp (flag + strlen (flag) - 7, "-format", 7) == 0) + if (flag_end - flag_start >= 7 + && memcmp (flag_end - 7, "-format", 7) == 0) { const char *p; size_t n; enum is_format value; size_t type; - p = flag; - n = strlen (flag) - 7; + p = flag_start; + n = flag_end - flag_start - 7; if (n >= 3 && memcmp (p, "no-", 3) == 0) { @@ -1494,24 +1505,37 @@ xgettext_record_flag (const char *optionstring) switch (type) { case format_c: - flag_context_list_table_insert (&flag_table_c, 0, - name_start, name_end, - argnum, value, pass); - flag_context_list_table_insert (&flag_table_cxx_qt, 0, - name_start, name_end, - argnum, value, pass); - flag_context_list_table_insert (&flag_table_cxx_kde, 0, - name_start, name_end, - argnum, value, pass); - flag_context_list_table_insert (&flag_table_cxx_boost, 0, - name_start, name_end, - argnum, value, pass); - flag_context_list_table_insert (&flag_table_objc, 0, - name_start, name_end, - argnum, value, pass); - flag_context_list_table_insert (&flag_table_vala, 0, - name_start, name_end, - argnum, value, pass); + if (backend == NULL || strcmp (backend, "C") == 0 + || strcmp (backend, "C++") == 0) + { + flag_context_list_table_insert (&flag_table_c, 0, + name_start, name_end, + argnum, value, pass); + } + if (backend == NULL || strcmp (backend, "C++") == 0) + { + flag_context_list_table_insert (&flag_table_cxx_qt, 0, + name_start, name_end, + argnum, value, pass); + flag_context_list_table_insert (&flag_table_cxx_kde, 0, + name_start, name_end, + argnum, value, pass); + flag_context_list_table_insert (&flag_table_cxx_boost, 0, + name_start, name_end, + argnum, value, pass); + } + if (backend == NULL || strcmp (backend, "ObjectiveC") == 0) + { + flag_context_list_table_insert (&flag_table_objc, 0, + name_start, name_end, + argnum, value, pass); + } + if (backend == NULL || strcmp (backend, "Vala") == 0) + { + flag_context_list_table_insert (&flag_table_vala, 0, + name_start, name_end, + argnum, value, pass); + } break; case format_objc: flag_context_list_table_insert (&flag_table_objc, 1, diff --git a/gettext-tools/src/xgettext.h b/gettext-tools/src/xgettext.h index e696f8bed..c37f4a9ad 100644 --- a/gettext-tools/src/xgettext.h +++ b/gettext-tools/src/xgettext.h @@ -63,7 +63,11 @@ extern struct formatstring_parser *current_formatstring_parser3; extern struct formatstring_parser *current_formatstring_parser4; -/* Record a flag in the appropriate backend's table. */ +/* Record a flag in the appropriate backend's table. + OPTIONSTRING has the syntax WORD:ARG:FLAG (as documented) + or WORD:ARG:FLAG!BACKEND. + The latter syntax is undocumented and only needed for format string types + that are used by multiple backends. */ extern void xgettext_record_flag (const char *optionstring); diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 0cc606a28..857300f29 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -90,7 +90,7 @@ TESTS = gettext-1 gettext-2 \ xgettext-c-comment-4 xgettext-c-comment-5 xgettext-c-comment-6 \ xgettext-c-escape-1 xgettext-c-escape-2 xgettext-c-escape-3 \ xgettext-c-format-1 xgettext-c-format-2 xgettext-c-format-3 \ - xgettext-c-format-4 xgettext-c-format-5 \ + xgettext-c-format-4 xgettext-c-format-5 xgettext-c-format-6 \ xgettext-c-ctxt-1 xgettext-c-ctxt-2 xgettext-c-ctxt-3 \ xgettext-c-c++-1 xgettext-c-c++-2 \ xgettext-c-stackovfl-1 xgettext-c-stackovfl-2 \ diff --git a/gettext-tools/tests/xgettext-c-format-6 b/gettext-tools/tests/xgettext-c-format-6 new file mode 100755 index 000000000..f08b67f40 --- /dev/null +++ b/gettext-tools/tests/xgettext-c-format-6 @@ -0,0 +1,41 @@ +#! /bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test C support: verify that there are no side effects of the Vala extractor +# on the C extractor. + +cat <<\EOF > xg-c-format-6.c +/* For the C extractor, Q_ and X_ are unknown identifiers and should therefore + behave the same way. */ +printf (Q_("blablaQ %d and %s"), a, b); +printf (Q_("blablaQ {0} and {1}"), a, b); +printf (X_("blablaX %d and %s"), a, b); +printf (X_("blablaX {0} and {1}"), a, b); +EOF + +: ${XGETTEXT=xgettext} +${XGETTEXT} --omit-header --no-location -kQ_ -kX_ \ + -d xg-c-format-6.tmp xg-c-format-6.c || Exit 1 +LC_ALL=C tr -d '\r' < xg-c-format-6.tmp.po > xg-c-format-6.po || Exit 1 + +cat < xg-c-format-6.ok +#, c-format +msgid "blablaQ %d and %s" +msgstr "" + +msgid "blablaQ {0} and {1}" +msgstr "" + +#, c-format +msgid "blablaX %d and %s" +msgstr "" + +msgid "blablaX {0} and {1}" +msgstr "" +EOF + +: ${DIFF=diff} +${DIFF} xg-c-format-6.ok xg-c-format-6.po +result=$? + +exit $result