]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
xgettext: Avoid side effects of the Vala extractor on the C extractor.
authorBruno Haible <bruno@clisp.org>
Wed, 7 Jun 2023 16:57:37 +0000 (18:57 +0200)
committerBruno Haible <bruno@clisp.org>
Wed, 7 Jun 2023 16:58:32 +0000 (18:58 +0200)
* 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.

gettext-tools/src/x-vala.c
gettext-tools/src/xgettext.c
gettext-tools/src/xgettext.h
gettext-tools/tests/Makefile.am
gettext-tools/tests/xgettext-c-format-6 [new file with mode: 0755]

index 64cc4fd755604f053c431afb89f85b13daa6d13d..6f548538754f0cb64b63133e7c03ec2c41e81ba5 100644 (file)
@@ -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");
 }
 
 
index c3534ad145c6bd97bc640eb9882fa4583d6e7886..27f703f59e411d75f00fcd8fb0c0aa4f044d793f 100644 (file)
@@ -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,
index e696f8bed7c1f27c2b69e9d48bd9ec22d88b1dbf..c37f4a9adb4be64863592bc37c60fd73d8466385 100644 (file)
@@ -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);
 
 
index 0cc606a28c5c46181f5b1f555878ed1324cfad0d..857300f2953fc7d8373178637fd5bba231d2a1dd 100644 (file)
@@ -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 (executable)
index 0000000..f08b67f
--- /dev/null
@@ -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 <<EOF > 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