From: Bruno Haible Date: Sat, 27 Jul 2024 17:12:51 +0000 (+0200) Subject: xgettext: Vala: Improve the support of the method .printf(). X-Git-Tag: v0.23~221 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d17e3277992e112dc701272b83d4c8eacaabd568;p=thirdparty%2Fgettext.git xgettext: Vala: Improve the support of the method .printf(). * gettext-tools/src/x-vala.c (enum token_type_ty): New enum item token_type_compound_assign. (phase3_get): Recognize the compound assignment operators as token_type_compound_assign instead of token_type_assign. (extract_balanced): Invoke new_sub_region instead of inheriting_region. Invoke set_format_flag_on_region instead of iterating through the region. When encountering an operator, close the inner_region and open a new inner_region. After 'return', use the passthrough_context_list_iterator, not the null_context_list_iterator. * gettext-tools/tests/xgettext-vala-6: Add many more test cases. --- diff --git a/gettext-tools/src/x-vala.c b/gettext-tools/src/x-vala.c index cbcf6146b..74cfbeea4 100644 --- a/gettext-tools/src/x-vala.c +++ b/gettext-tools/src/x-vala.c @@ -54,8 +54,14 @@ #define SIZEOF(a) (sizeof(a) / sizeof(a[0])) /* The Vala syntax is defined in the Vala Reference Manual - https://www.vala-project.org/doc/vala/. - See also vala/valascanner.vala. */ + https://gnome.pages.gitlab.gnome.org/vala/manual/index.html. + See also vala/valascanner.vala. + + It supports string formatting through functions and methods, namely + through the string.printf and string.vprintf methods: + + + */ /* ====================== Keyword set customization. ====================== */ @@ -390,7 +396,8 @@ enum token_type_ty token_type_rparen, /* ) */ token_type_lbrace, /* { */ token_type_rbrace, /* } */ - token_type_assign, /* = += -= *= /= %= <<= >>= &= |= ^= */ + token_type_assign, /* = */ + token_type_compound_assign, /* += -= *= /= %= <<= >>= &= |= ^= */ token_type_return, /* return */ token_type_plus, /* + */ token_type_arithmetic_operator, /* - * / % << >> & | ^ ~ */ @@ -1018,6 +1025,7 @@ phase3_get (token_ty *tp) case token_type_lparen: case token_type_lbrace: case token_type_assign: + case token_type_compound_assign: case token_type_return: case token_type_plus: case token_type_arithmetic_operator: @@ -1033,7 +1041,7 @@ phase3_get (token_ty *tp) { int c2 = phase2_getc (); if (c2 == '=') - tp->type = last_token_type = token_type_assign; + tp->type = last_token_type = token_type_compound_assign; else { phase2_ungetc (c2); @@ -1069,7 +1077,7 @@ phase3_get (token_ty *tp) tp->type = last_token_type = token_type_other; break; case '=': - tp->type = last_token_type = token_type_assign; + tp->type = last_token_type = token_type_compound_assign; break; default: phase2_ungetc (c2); @@ -1088,7 +1096,7 @@ phase3_get (token_ty *tp) tp->type = last_token_type = token_type_other; break; case '=': - tp->type = last_token_type = token_type_assign; + tp->type = last_token_type = token_type_compound_assign; break; default: phase2_ungetc (c2); @@ -1102,7 +1110,7 @@ phase3_get (token_ty *tp) { int c2 = phase2_getc (); if (c2 == '=') - tp->type = last_token_type = token_type_assign; + tp->type = last_token_type = token_type_compound_assign; else { phase2_ungetc (c2); @@ -1116,7 +1124,7 @@ phase3_get (token_ty *tp) { int c2 = phase2_getc (); if (c2 == '=') - tp->type = last_token_type = token_type_assign; + tp->type = last_token_type = token_type_compound_assign; else { phase2_ungetc (c2); @@ -1171,7 +1179,7 @@ phase3_get (token_ty *tp) { int c3 = phase2_getc (); if (c3 == '=') - tp->type = last_token_type = token_type_assign; + tp->type = last_token_type = token_type_compound_assign; else { phase2_ungetc (c2); @@ -1202,7 +1210,7 @@ phase3_get (token_ty *tp) if (c2 == c) tp->type = last_token_type = token_type_logic_operator; else if (c2 == '=') - tp->type = last_token_type = token_type_assign; + tp->type = last_token_type = token_type_compound_assign; else { phase2_ungetc (c2); @@ -1370,10 +1378,11 @@ extract_balanced (message_list_ty *mlp, token_type_ty delim, /* Context iterator that will be used if the next token is a '('. */ flag_context_list_iterator_ty next_context_iter = passthrough_context_list_iterator; + /* Current context. */ + flag_context_ty curr_context = + flag_context_list_iterator_advance (&context_iter); /* Current region. */ - flag_region_ty *inner_region = - inheriting_region (outer_region, - flag_context_list_iterator_advance (&context_iter)); + flag_region_ty *inner_region = new_sub_region (outer_region, curr_context); /* Start state is 0. */ state = 0; @@ -1438,16 +1447,8 @@ extract_balanced (message_list_ty *mlp, token_type_ty delim, { /* Mark the messages found in the region as c-format a posteriori. */ - inner_region->for_formatstring[XFORMAT_PRIMARY].is_format = yes_according_to_context; - struct remembered_message_list_ty *rmlp = - inner_region->for_formatstring[XFORMAT_PRIMARY].remembered; - size_t i; - for (i = 0; i < rmlp->nitems; i++) - { - struct remembered_message_ty *rmp = &rmlp->item[i]; - set_format_flag_from_context (rmp->mp, rmp->plural, &rmp->pos, - XFORMAT_PRIMARY, inner_region); - } + set_format_flag_on_region (inner_region, + XFORMAT_PRIMARY, yes_according_to_context); } x_vala_unlex (&token3); } @@ -1472,10 +1473,59 @@ extract_balanced (message_list_ty *mlp, token_type_ty delim, case token_type_comma: arg++; unref_region (inner_region); - inner_region = - inheriting_region (outer_region, - flag_context_list_iterator_advance ( - &context_iter)); + curr_context = flag_context_list_iterator_advance (&context_iter); + inner_region = new_sub_region (outer_region, curr_context); + next_context_iter = passthrough_context_list_iterator; + state = 0; + continue; + + case token_type_question: + /* In an expression A ? B : C, each of A, B, C is a distinct + sub-region, and since the value of A is not the value of entire + expression, if later set_format_flag_on_region is called on this + region or an ancestor region, it shall not have an effect on the + remembered messages of A. */ + inner_region->inherit_from_parent_region = false; + unref_region (inner_region); + inner_region = new_sub_region (outer_region, curr_context); + next_context_iter = passthrough_context_list_iterator; + state = 0; + continue; + + case token_type_colon: + /* In an expression A ? B : C, each of A, B, C is a distinct + sub-region. */ + unref_region (inner_region); + inner_region = new_sub_region (outer_region, curr_context); + next_context_iter = passthrough_context_list_iterator; + state = 0; + continue; + + case token_type_assign: + /* In an expression A = B, A and B are distinct sub-regions. + The value of B is the value of the entire expression. */ + inner_region->inherit_from_parent_region = false; + unref_region (inner_region); + inner_region = new_sub_region (outer_region, curr_context); + next_context_iter = passthrough_context_list_iterator; + state = 0; + continue; + + case token_type_plus: + case token_type_arithmetic_operator: + case token_type_equality_test_operator: + case token_type_logic_operator: + case token_type_compound_assign: + /* When an expression contains one of these operators, neither the + value on the left of the operator nor the value on the right of the + operator is string-valued and the value of the entire expression. + Therefore, if later set_format_flag_on_region is called on this + region or an ancestor region, it shall not have an effect on the + remembered messages of this region. */ + inner_region->inherit_from_parent_region = false; + unref_region (inner_region); + inner_region = new_sub_region (outer_region, curr_context); + inner_region->inherit_from_parent_region = false; next_context_iter = passthrough_context_list_iterator; state = 0; continue; @@ -1531,17 +1581,14 @@ extract_balanced (message_list_ty *mlp, token_type_ty delim, state = 0; continue; + case token_type_return: + next_context_iter = passthrough_context_list_iterator; + state = 0; + continue; + case token_type_character_constant: case token_type_lbrace: case token_type_rbrace: - case token_type_assign: - case token_type_return: - case token_type_plus: - case token_type_arithmetic_operator: - case token_type_equality_test_operator: - case token_type_logic_operator: - case token_type_question: - case token_type_colon: case token_type_number: case token_type_string_template: case token_type_regex_literal: diff --git a/gettext-tools/tests/xgettext-vala-6 b/gettext-tools/tests/xgettext-vala-6 index f215f8218..986545d13 100755 --- a/gettext-tools/tests/xgettext-vala-6 +++ b/gettext-tools/tests/xgettext-vala-6 @@ -8,10 +8,56 @@ cat <<\EOF > xg-vala-6.vala "%s".printf(_("Hello 1")); _("Explanation: %s").printf(_("Hello 2")); -_("No error 1"); -_("No error 2").printf(); -(_("No error 3")).printf(); -foo(_("No error 4")).printf(); +_("test case 1"); +_("test case 2").printf(); +(_("test case 3")); +(_("test case 4")).printf(); +((_("test case 5"))); +((_("test case 6"))).printf(); +return _("test case 10"); +return _("test case 11").printf(); +return (_("test case 12").printf()); +return (_("test case 13")).printf(); +foo (_("test case 15")); +foo (_("test case 16")).printf(); +(foo (_("test case 17"))).printf(); +(foo (_("test case 18")).printf()); +foo (_("test case 19").printf()); +foo + _("test case 20"); +foo + _("test case 21").printf(); +(foo + _("test case 22")).printf(); +_("test case 23") + foo; +_("test case 24").printf() + foo; +(_("test case 25") + foo).printf(); +_("test case 26 a") + _("test case 26 b"); +_("test case 27 a").printf() + _("test case 27 b"); +_("test case 28 a") + _("test case 28 b").printf(); +_("test case 29 a").printf() + _("test case 29 b").printf(); +(_("test case 30 a") + _("test case 30 b")).printf(); +return _("test case 31 a") + _("test case 31 b"); +return _("test case 32 a").printf() + _("test case 32 b"); +return _("test case 33 a") + _("test case 33 b").printf(); +return _("test case 34 a").printf() + _("test case 34 b").printf(); +return (_("test case 35 a") + _("test case 35 b")).printf(); +return _("test case 36 a") + (_("test case 36 b")).printf() + _("test case 36 c").printf(); +return _("test case 37 a") + _("test case 37 b").printf() + (_("test case 37 c")).printf(); +return _("test case 38 a") + (_("test case 38 b")).printf() + (_("test case 38 c")).printf(); +foo ? _("test case 40 a") : _("test case 40 b"); +foo ? _("test case 41 a").printf() : _("test case 41 b"); +foo ? _("test case 42 a") : _("test case 42 b").printf(); +foo ? _("test case 43 a").printf() : _("test case 43 b").printf(); +(foo ? _("test case 44 a") : _("test case 44 b")); +(foo ? _("test case 45 a") : _("test case 45 b")).printf(); +s = (_("test case 46")).printf(); +(s = _("test case 47")).printf(); +s += (_("test case 48")).printf(); +(s += _("test case 49")).printf(); +return _("test case 50 a") + + _("test case 50 b").printf() + + (_("test case 50 c")).printf() + + foo(_("test case 50 d")).printf() + + (b ? _("test case 50 e") : _("test case 50 f")).printf() + + (b ? foo + _("test case 50 g") : _("test case 50 h") + bar).printf(); Posix.printf(_("Hello 3")); Posix.printf(_("Hello 4 %s!"), _("Sir")); EOF @@ -30,18 +76,262 @@ msgstr "" msgid "Hello 2" msgstr "" -msgid "No error 1" +msgid "test case 1" msgstr "" #, c-format -msgid "No error 2" +msgid "test case 2" +msgstr "" + +msgid "test case 3" +msgstr "" + +#, c-format +msgid "test case 4" +msgstr "" + +msgid "test case 5" +msgstr "" + +#, c-format +msgid "test case 6" +msgstr "" + +msgid "test case 10" +msgstr "" + +#, c-format +msgid "test case 11" +msgstr "" + +#, c-format +msgid "test case 12" +msgstr "" + +#, c-format +msgid "test case 13" +msgstr "" + +msgid "test case 15" +msgstr "" + +msgid "test case 16" +msgstr "" + +msgid "test case 17" +msgstr "" + +msgid "test case 18" +msgstr "" + +#, c-format +msgid "test case 19" +msgstr "" + +msgid "test case 20" +msgstr "" + +#, c-format +msgid "test case 21" +msgstr "" + +msgid "test case 22" +msgstr "" + +msgid "test case 23" +msgstr "" + +#, c-format +msgid "test case 24" +msgstr "" + +msgid "test case 25" +msgstr "" + +msgid "test case 26 a" +msgstr "" + +msgid "test case 26 b" +msgstr "" + +#, c-format +msgid "test case 27 a" +msgstr "" + +msgid "test case 27 b" +msgstr "" + +msgid "test case 28 a" +msgstr "" + +#, c-format +msgid "test case 28 b" +msgstr "" + +#, c-format +msgid "test case 29 a" +msgstr "" + +#, c-format +msgid "test case 29 b" +msgstr "" + +msgid "test case 30 a" +msgstr "" + +msgid "test case 30 b" +msgstr "" + +msgid "test case 31 a" +msgstr "" + +msgid "test case 31 b" +msgstr "" + +#, c-format +msgid "test case 32 a" +msgstr "" + +msgid "test case 32 b" +msgstr "" + +msgid "test case 33 a" +msgstr "" + +#, c-format +msgid "test case 33 b" +msgstr "" + +#, c-format +msgid "test case 34 a" msgstr "" #, c-format -msgid "No error 3" +msgid "test case 34 b" +msgstr "" + +msgid "test case 35 a" +msgstr "" + +msgid "test case 35 b" +msgstr "" + +msgid "test case 36 a" +msgstr "" + +#, c-format +msgid "test case 36 b" +msgstr "" + +#, c-format +msgid "test case 36 c" +msgstr "" + +msgid "test case 37 a" +msgstr "" + +#, c-format +msgid "test case 37 b" +msgstr "" + +#, c-format +msgid "test case 37 c" +msgstr "" + +msgid "test case 38 a" +msgstr "" + +#, c-format +msgid "test case 38 b" +msgstr "" + +#, c-format +msgid "test case 38 c" +msgstr "" + +msgid "test case 40 a" +msgstr "" + +msgid "test case 40 b" +msgstr "" + +#, c-format +msgid "test case 41 a" +msgstr "" + +msgid "test case 41 b" +msgstr "" + +msgid "test case 42 a" +msgstr "" + +#, c-format +msgid "test case 42 b" +msgstr "" + +#, c-format +msgid "test case 43 a" +msgstr "" + +#, c-format +msgid "test case 43 b" +msgstr "" + +msgid "test case 44 a" +msgstr "" + +msgid "test case 44 b" +msgstr "" + +#, c-format +msgid "test case 45 a" +msgstr "" + +#, c-format +msgid "test case 45 b" +msgstr "" + +#, c-format +msgid "test case 46" +msgstr "" + +#, c-format +msgid "test case 47" +msgstr "" + +#, c-format +msgid "test case 48" +msgstr "" + +msgid "test case 49" +msgstr "" + +msgid "test case 50 a" +msgstr "" + +#, c-format +msgid "test case 50 b" +msgstr "" + +#, c-format +msgid "test case 50 c" +msgstr "" + +msgid "test case 50 d" +msgstr "" + +#, c-format +msgid "test case 50 e" +msgstr "" + +#, c-format +msgid "test case 50 f" +msgstr "" + +msgid "test case 50 g" msgstr "" -msgid "No error 4" +msgid "test case 50 h" msgstr "" msgid "Hello 3" @@ -56,7 +346,7 @@ msgstr "" EOF : ${DIFF=diff} -${DIFF} xg-vala-6.ok xg-vala-6.po +${DIFF} -u xg-vala-6.ok xg-vala-6.po result=$? exit $result