bug-gettext
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug-gettext] [PATCH] format-kde: Recognize KUIT markup


From: Daiki Ueno
Subject: [bug-gettext] [PATCH] format-kde: Recognize KUIT markup
Date: Thu, 05 Mar 2015 18:09:00 +0900
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux)

Hello Chusslove,

Sorry for the delay.  I finally had a chance to go through the KI18n
document:
http://api.kde.org/frameworks-api/frameworks5-apidocs/ki18n/html/prg_guide.html
and got some points you told me earlier (sorry for pointless comments,
I'm really unfamiliar with KDE).

The attached patch is what I ended up with so far.  I chose the name
"kde-kuit-format" instead of "kde-xml-format", as it's not really a
valid XML fragment due to the stray &'s and %'s, and also defined it as
a superset of kde-format.

Processing the following file:

  // This is a KUIT string.
  xi18n ("The <command>&About</command> command shows the names of developers 
&amp; translators.");

  // This is a KUIT string.
  xi18n ("The configuration is read from <filename>%1</filename>");

  // This is a KUIT string.
  xi18n ("This does not contain a markup");

  // This is not a KUIT string.
  i18n ("<foo>b</foo>");

  // This is not a KUIT string.
  i18n ("<foo>%1</foo>");

with xgettext:

  xgettext --omit-header --add-comment --no-location \
           -L C++ --kde \
           -kxi18n:1 --flag xi18n:1:kde-kuit-format \
           -ki18n:1 --flag i18n:1:kde-format \
           -o - tstkuit.cpp

produces:

  #. This is a KUIT string.
  #, kde-kuit-format
  msgid ""
  "The <command>&About</command> command shows the names of developers &amp; "
  "translators."
  msgstr ""

  #. This is a KUIT string.
  #, kde-kuit-format
  msgid "The configuration is read from <filename>%1</filename>"
  msgstr ""

  #. This is a KUIT string.
  #, kde-kuit-format
  msgid "This does not contain a markup"
  msgstr ""

  #. This is not a KUIT string.
  #, kde-format
  msgid "<foo>b</foo>"
  msgstr ""

  #. This is not a KUIT string.
  #, kde-format
  msgid "<foo>%1</foo>"
  msgstr ""

If I omit -k and --flag options, all strings containing a markup tag are
now marked as kde-kuit-format (instead of kde-format), because the
initial flags list is empty.  That might be confusing and I tend to
agree with changing the --kde option to install all the necessary flags.

Also it might look a bit surprising that the 3rd and 4th string is
marked as kde-format, even if it doesn't contain a format directive.
However, this is the original behavior, and should be addressed
separately.

Anyway, comments would be appreciated.  Ideally, it would be nicer if
you could (re)write the patch and maintain it in gettext, since it is
you who invented the stuff in the KDE side :-)

Regards,
--
Daiki Ueno
>From ecaddd6a333b0054b566be253215ed42a095d3b6 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <address@hidden>
Date: Thu, 5 Mar 2015 12:00:09 +0900
Subject: [PATCH] format-kde: Recognize KUIT markup

Reported by Chusslove Illich in:
https://lists.gnu.org/archive/html/bug-gettext/2015-01/msg00017.html
* gettext-tools/src/format.h (formatstring_kde_kuit): New variable
declaration.
* gettext-tools/src/format.c (formatstring_parsers): Register
formatstring_kde_kuitas a format string parser.
* gettext-tools/src/format-kde.c: Include "unistr.h" and
"libexpat-compat.h".
(SIZEOF): New macro.
(start_element_handler) [HAVE_LIBEXPAT]: New function.
(end_element_handler) [HAVE_LIBEXPAT]: New function.
(struct char_range): New struct.
(name_chars1): New variable.
(name_chars2): New variable.
(is_reference): New function.
(format_kuit_parse): New function.
(format_kuit_free): New function.
(format_kuit_get_number_of_directives): New function.
(format_kuit_is_unlikely_intentional): New function.
(format_kuit_check): New function.
(formatstring_kde_kuit): New variable.
* gettext-tools/src/message.h (NFORMATS): Increment.
(enum format_type): New enum value format_kde_kuit.
* gettext-tools/src/xgettext.c (xgettext_record_flag): Handle
format_kde_kuit.
* gettext-tools/src/libexpat-compat.c (p_XML_SetUserData): New variable.
(XML_SetUserData): New function.
(load_libexpat): Initialize p_XML_SetUserData.
* gettext-tools/src/libexpat-compat.h (XML_SetUserData): New function
declaration.
* gettext-tools/src/Makefile.am (xgettext_SOURCES): Move
libexpat-compat.c to...
(libgettextsrc_la_SOURCES): ...here.
(xgettext_LDADD): Move @LTLIBEXPAT@ to...
(libgettextsrc_la_LDFLAGS): ...here.
* gettext-tools/libgettextpo/Makefile.am (libgettextpo_la_AUXSOURCES):
Add ../src/libexpat-compat.c.
(libgettextpo_la_LDFLAGS): Add @address@hidden
* gettext-tools/tests/format-kde-kuit-1: New file.
* gettext-tools/tests/format-kde-kuit-2: New file.
* gettext-tools/tests/Makefile.am (TESTS): Add new tests.
---
 gettext-tools/libgettextpo/ChangeLog   |   6 +
 gettext-tools/libgettextpo/Makefile.am |   5 +-
 gettext-tools/src/ChangeLog            |  35 ++++
 gettext-tools/src/Makefile.am          |   7 +-
 gettext-tools/src/format-kde.c         | 293 ++++++++++++++++++++++++++++++++-
 gettext-tools/src/format.c             |   1 +
 gettext-tools/src/format.h             |   1 +
 gettext-tools/src/libexpat-compat.c    |  13 ++
 gettext-tools/src/libexpat-compat.h    |   1 +
 gettext-tools/src/message.c            |   2 +
 gettext-tools/src/message.h            |   3 +-
 gettext-tools/src/xgettext.c           |  22 ++-
 gettext-tools/tests/ChangeLog          |   6 +
 gettext-tools/tests/Makefile.am        |   1 +
 gettext-tools/tests/format-kde-kuit-1  |  57 +++++++
 gettext-tools/tests/format-kde-kuit-2  |  64 +++++++
 16 files changed, 507 insertions(+), 10 deletions(-)
 create mode 100755 gettext-tools/tests/format-kde-kuit-1
 create mode 100755 gettext-tools/tests/format-kde-kuit-2

diff --git a/gettext-tools/libgettextpo/ChangeLog 
b/gettext-tools/libgettextpo/ChangeLog
index c439706..092b3f5 100644
--- a/gettext-tools/libgettextpo/ChangeLog
+++ b/gettext-tools/libgettextpo/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-05  Daiki Ueno  <address@hidden>
+
+       * Makefile.am (libgettextpo_la_AUXSOURCES): Add
+       ../src/libexpat-compat.c.
+       (libgettextpo_la_LDFLAGS): Add @address@hidden
+
 2014-12-24  Daiki Ueno  <address@hidden>
 
        * gettext 0.19.4 released.
diff --git a/gettext-tools/libgettextpo/Makefile.am 
b/gettext-tools/libgettextpo/Makefile.am
index 10f5de6..d1d0a03 100644
--- a/gettext-tools/libgettextpo/Makefile.am
+++ b/gettext-tools/libgettextpo/Makefile.am
@@ -91,7 +91,8 @@ libgettextpo_la_AUXSOURCES = \
   ../src/plural-exp.c \
   ../src/plural-eval.c \
   ../src/msgl-check.c \
-  ../src/sentence.c
+  ../src/sentence.c \
+  ../src/libexpat-compat.c
 
 # Libtool's library version information for libgettextpo.
 # See the libtool documentation, section "Library interface versions".
@@ -106,7 +107,7 @@ libgettextpo_la_LIBADD = libgnu.la $(WOE32_LIBADD) 
$(LTLIBUNISTRING)
 libgettextpo_la_LDFLAGS = \
   -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \
   -rpath $(libdir) \
-  @LTLIBINTL@ @LTLIBICONV@ -lc -no-undefined
+  @LTLIBINTL@ @LTLIBICONV@ @LTLIBEXPAT@ -lc -no-undefined
 
 # Tell the mingw or Cygwin linker which symbols to export.
 if WOE32DLL
diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog
index 754a9dc..195792a 100644
--- a/gettext-tools/src/ChangeLog
+++ b/gettext-tools/src/ChangeLog
@@ -1,3 +1,38 @@
+2015-03-05  Daiki Ueno  <address@hidden>
+
+       format-kde: Recognize KUIT markup
+       Reported by Chusslove Illich in:
+       https://lists.gnu.org/archive/html/bug-gettext/2015-01/msg00017.html
+       * format.h (formatstring_kde_kuit): New variable declaration.
+       * format.c (formatstring_parsers): Register formatstring_kde_kuit
+       as a format string parser.
+       * format-kde.c: Include "unistr.h" and "libexpat-compat.h".
+       (SIZEOF): New macro.
+       (struct kuit_spec): New struct.
+       (start_element_handler) [HAVE_LIBEXPAT]: New function.
+       (end_element_handler) [HAVE_LIBEXPAT]: New function.
+       (struct char_range): New struct.
+       (name_chars1): New variable.
+       (name_chars2): New variable.
+       (is_reference): New function.
+       (format_kuit_parse): New function.
+       (format_kuit_free): New function.
+       (format_kuit_get_number_of_directives): New function.
+       (format_kuit_is_unlikely_intentional): New function.
+       (format_kuit_check): New function.
+       (formatstring_kde_kuit): New variable.
+       * message.h (NFORMATS): Increment.
+       (enum format_type): New enum value format_kde_kuit.
+       * xgettext.c (xgettext_record_flag): Handle format_kde_kuit.
+       * Makefile.am (xgettext_SOURCES): Move libexpat-compat.c to...
+       (libgettextsrc_la_SOURCES): ...here.
+       (xgettext_LDADD): Move @LTLIBEXPAT@ to...
+       (libgettextsrc_la_LDFLAGS): ...here.
+       * libexpat-compat.c (p_XML_SetUserData): New variable.
+       (XML_SetUserData): New function.
+       (load_libexpat): Initialize p_XML_SetUserData.
+       * libexpat-compat.h (XML_SetUserData): New function declaration.
+
 2015-03-02  Daiki Ueno  <address@hidden>
 
        xgettext: Support message syntax checks
diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am
index edb376f..1e682bb 100644
--- a/gettext-tools/src/Makefile.am
+++ b/gettext-tools/src/Makefile.am
@@ -148,7 +148,7 @@ $(COMMON_SOURCE) read-catalog.c \
 color.c write-catalog.c write-properties.c write-stringtable.c write-po.c \
 msgl-ascii.c msgl-iconv.c msgl-equal.c msgl-cat.c msgl-header.c msgl-english.c 
\
 msgl-check.c file-list.c msgl-charset.c po-time.c plural-exp.c plural-eval.c \
-plural-table.c quote.h sentence.h sentence.c \
+plural-table.c quote.h sentence.h sentence.c libexpat-compat.c \
 $(FORMAT_SOURCE) \
 read-desktop.c
 
@@ -180,7 +180,6 @@ xgettext_SOURCES += \
   x-c.c x-po.c x-sh.c x-python.c x-lisp.c x-elisp.c x-librep.c x-scheme.c \
   x-smalltalk.c x-java.c x-csharp.c x-awk.c x-ycp.c x-tcl.c x-perl.c x-php.c \
   x-rst.c x-glade.c x-lua.c x-javascript.c x-vala.c x-gsettings.c \
-  libexpat-compat.c \
   x-desktop.c
 if !WOE32DLL
 msgattrib_SOURCES = msgattrib.c
@@ -247,7 +246,7 @@ urlget_SOURCES = urlget.c
 # use iconv().
 libgettextsrc_la_LDFLAGS = \
   -release @VERSION@ \
-  ../gnulib-lib/libgettextlib.la $(LTLIBUNISTRING) @LTLIBINTL@ @LTLIBICONV@ 
-lc -no-undefined
+  ../gnulib-lib/libgettextlib.la $(LTLIBUNISTRING) @LTLIBINTL@ @LTLIBICONV@ 
@LTLIBEXPAT@ -lc -no-undefined
 
 libgettextsrc_la_CPPFLAGS = $(AM_CPPFLAGS)
 
@@ -278,7 +277,7 @@ msgcmp_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ 
@MSGMERGE_LIBM@ $(WOE32_LDADD
 msgfmt_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ $(WOE32_LDADD)
 msgmerge_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ @MSGMERGE_LIBM@ 
$(WOE32_LDADD) $(OPENMP_CFLAGS)
 msgunfmt_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ $(WOE32_LDADD)
-xgettext_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ @LTLIBEXPAT@ @LTLIBICONV@ 
$(WOE32_LDADD)
+xgettext_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ @LTLIBICONV@ 
$(WOE32_LDADD)
 msgattrib_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ $(WOE32_LDADD)
 msgcat_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ $(WOE32_LDADD)
 msgcomm_LDADD = libgettextsrc.la @INTL_MACOSX_LIBS@ $(WOE32_LDADD)
diff --git a/gettext-tools/src/format-kde.c b/gettext-tools/src/format-kde.c
index 90e887d..ecfb596 100644
--- a/gettext-tools/src/format-kde.c
+++ b/gettext-tools/src/format-kde.c
@@ -1,5 +1,5 @@
 /* KDE format strings.
-   Copyright (C) 2003-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2003-2004, 2006-2007, 2009, 2015 Free Software Foundation, 
Inc.
    Written by Bruno Haible <address@hidden>, 2007.
 
    This program is free software: you can redistribute it and/or modify
@@ -23,12 +23,16 @@
 #include <stdlib.h>
 
 #include "format.h"
+#include "unistr.h"
 #include "xalloc.h"
 #include "xvasprintf.h"
+#include "libexpat-compat.h"
 #include "gettext.h"
 
 #define _(str) gettext (str)
 
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+
 /* KDE 4 format strings are processed by method
    KLocalizedStringPrivate::substituteSimple(string,'%',false) in
    kde4libs-3.93.0.orig/kdecore/localization/klocalizedstring.cpp .
@@ -270,6 +274,293 @@ struct formatstring_parser formatstring_kde =
 };
 
 
+/* KUIT (KDE User Interface Text) support.  KUIT is an XML-like markup
+   which augments the translatable text with semantic information:
+   
http://api.kde.org/frameworks-api/frameworks5-apidocs/ki18n/html/prg_guide.html#kuit_markup
+   KUIT can be seen as a fragment of well-formed XML, except that a
+   string may contain raw '&' as a Qt accelerator marker and '%'
+   as a format directive.  */
+
+struct kuit_spec
+{
+  struct spec *base;
+
+  /* Whether a markup tag found in the string.  */
+  bool has_markup;
+};
+
+#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
+
+/* Callback called when <element> is seen.  */
+static void
+start_element_handler (void *data, const char *name,
+                       const char **attributes)
+{
+  struct kuit_spec *spec = data;
+  spec->has_markup = true;
+}
+
+/* Callback called when </element> is seen.  */
+static void
+end_element_handler (void *data, const char *name)
+{
+  /* Nothing to do.  */
+}
+
+struct char_range
+{
+  ucs4_t start;
+  ucs4_t end;
+};
+
+/* Character ranges for NameStartChar defined in:
+   http://www.w3.org/TR/REC-xml/#NT-NameStartChar  */
+static const struct char_range name_chars1[] =
+  {
+    { ':', ':' },
+    { 'A', 'Z' },
+    { '_', '_' },
+    { 'a', 'z' },
+    { 0xC0, 0xD6 },
+    { 0xD8, 0xF6 },
+    { 0xF8, 0x2FF },
+    { 0x370, 0x37D },
+    { 0x37F, 0x1FFF },
+    { 0x200C, 0x200D },
+    { 0x2070, 0x218F },
+    { 0x2C00, 0x2FEF },
+    { 0x3001, 0xD7FF },
+    { 0xF900, 0xFDCF },
+    { 0xFDF0, 0xFFFD },
+    { 0x10000, 0xEFFFF }
+  };
+
+/* Character ranges for NameChar defined in:
+   http://www.w3.org/TR/REC-xml/#NT-NameChar  */
+static const struct char_range name_chars2[] =
+  {
+    { '-', '-' },
+    { '.', '.' },
+    { '0', '9' },
+    { 0xB7, 0xB7 },
+    { 0x0300, 0x036F },
+    { 0x203F, 0x2040 }
+  };
+
+/* Return true if INPUT is a reference.  */
+static bool
+is_reference (const char *input)
+{
+  const char *str = input;
+  const char *str_limit = str + strlen (input);
+  ucs4_t uc;
+  int i;
+
+  if (*str++ != '&')
+    return false;
+
+  str += u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
+
+  /* CharRef */
+  if (uc == '#')
+    {
+      str += u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
+      if (uc == 'x')
+        {
+          while (str < str_limit)
+            {
+              str += u8_mbtouc (&uc, (const unsigned char *) str,
+                                str_limit - str);
+              if (!(('0' <= uc && uc <= '9')
+                    || ('A' <= uc && uc <= 'F')
+                    || ('a' <= uc && uc <= 'f')))
+                break;
+            }
+          return uc == ';';
+        }
+      else if ('0' <= uc && uc <= '9')
+        {
+          while (str < str_limit)
+            {
+              str += u8_mbtouc (&uc, (const unsigned char *) str,
+                                str_limit - str);
+              if (!('0' <= uc && uc <= '9'))
+                break;
+            }
+          return uc == ';';
+        }
+    }
+  else
+    {
+      /* EntityRef */
+      for (i = 0; i < SIZEOF (name_chars1); i++)
+        if (name_chars1[i].start <= uc && uc <= name_chars1[i].end)
+          break;
+
+      if (i == SIZEOF (name_chars1))
+        return false;
+
+      while (str < str_limit)
+        {
+          str += u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
+          for (i = 0; i < SIZEOF (name_chars1); i++)
+            if (name_chars1[i].start <= uc && uc <= name_chars1[i].end)
+              break;
+          if (i == SIZEOF (name_chars1))
+            {
+              for (i = 0; i < SIZEOF (name_chars2); i++)
+                if (name_chars2[i].start <= uc && uc <= name_chars2[i].end)
+                  break;
+              if (i == SIZEOF (name_chars2))
+                return false;
+            }
+        }
+      return uc == ';';
+    }
+
+  return false;
+}
+
+#endif
+
+
+static void *
+format_kuit_parse (const char *format, bool translated, char *fdi,
+                   char **invalid_reason)
+{
+  struct kuit_spec *result;
+
+  result = XMALLOC (struct kuit_spec);
+
+#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
+  if (LIBEXPAT_AVAILABLE ())
+    {
+      XML_Parser parser;
+      const char *str = format;
+      const char *str_limit = str + strlen (format);
+      size_t amp_count;
+      char *buffer, *bp;
+
+      for (amp_count = 0; str < str_limit; amp_count++)
+        {
+          const char *amp = strchrnul (str, '&');
+          if (*amp != '&')
+            break;
+          str = amp + 1;
+        }
+
+      buffer = xmalloc (amp_count * 4 + strlen (format) + 16);
+      *buffer = '\0';
+
+      bp = buffer;
+      bp = stpcpy (bp, "<kuit>");
+      str = format;
+      while (str < str_limit)
+        {
+          const char *amp = strchrnul (str, '&');
+
+          bp = stpncpy (bp, str, amp - str);
+          if (*amp != '&')
+            break;
+
+          bp = stpcpy (bp, is_reference (amp) ? "&" : "&amp;");
+          str = amp + 1;
+        }
+      bp = stpcpy (bp, "</kuit>");
+
+      parser = XML_ParserCreate (NULL);
+      if (parser == NULL)
+        {
+          *invalid_reason = xasprintf (_("memory exhausted"));
+          free (buffer);
+          return NULL;
+        }
+
+      XML_SetUserData (parser, result);
+      XML_SetElementHandler (parser,
+                             start_element_handler,
+                             end_element_handler);
+
+      if (XML_Parse (parser, buffer, strlen (buffer), 0) == 0)
+        {
+          *invalid_reason =
+            xasprintf (_("error while parsing: %s"),
+                       XML_ErrorString (XML_GetErrorCode (parser)));
+          free (buffer);
+          XML_ParserFree (parser);
+          return NULL;
+        }
+
+      if (XML_Parse (parser, NULL, 0, 1) == 0)
+        {
+          *invalid_reason =
+            xasprintf (_("error while parsing: %s"),
+                       XML_ErrorString (XML_GetErrorCode (parser)));
+          free (buffer);
+          XML_ParserFree (parser);
+          return NULL;
+        }
+
+      free (buffer);
+      XML_ParserFree (parser);
+    }
+#endif
+
+  result->base = format_parse (format, translated, fdi, invalid_reason);
+  return result;
+}
+
+static void
+format_kuit_free (void *descr)
+{
+  struct kuit_spec *spec = descr;
+  if (spec->base != NULL)
+    format_free (spec->base);
+  free (spec);
+}
+
+static int
+format_kuit_get_number_of_directives (void *descr)
+{
+  struct kuit_spec *spec = descr;
+  if (spec->base)
+    return format_get_number_of_directives (spec->base);
+  return 0;
+}
+
+static bool
+format_kuit_is_unlikely_intentional (void *descr)
+{
+  struct kuit_spec *spec = descr;
+  return !spec->has_markup;
+}
+
+static bool
+format_kuit_check (void *msgid_descr, void *msgstr_descr, bool equality,
+                   formatstring_error_logger_t error_logger,
+                   const char *pretty_msgid, const char *pretty_msgstr)
+{
+  struct kuit_spec *msgid_spec = msgid_descr;
+  struct kuit_spec *msgstr_spec = msgstr_descr;
+
+  if (msgid_spec->base == NULL || msgstr_spec->base == NULL)
+    return false;
+
+  return format_check (msgid_spec, msgstr_spec, equality,
+                       error_logger,
+                       pretty_msgid, pretty_msgstr);
+}
+
+struct formatstring_parser formatstring_kde_kuit =
+{
+  format_kuit_parse,
+  format_kuit_free,
+  format_kuit_get_number_of_directives,
+  format_kuit_is_unlikely_intentional,
+  format_kuit_check
+};
+
+
 #ifdef TEST
 
 /* Test program: Print the argument list specification returned by
diff --git a/gettext-tools/src/format.c b/gettext-tools/src/format.c
index c73ad7d..cb5f49b 100644
--- a/gettext-tools/src/format.c
+++ b/gettext-tools/src/format.c
@@ -58,6 +58,7 @@ struct formatstring_parser *formatstring_parsers[NFORMATS] =
   /* format_qt */               &formatstring_qt,
   /* format_qt_plural */        &formatstring_qt_plural,
   /* format_kde */              &formatstring_kde,
+  /* format_kde_kuit */         &formatstring_kde_kuit,
   /* format_boost */            &formatstring_boost,
   /* format_lua */              &formatstring_lua,
   /* format_javascript */       &formatstring_javascript
diff --git a/gettext-tools/src/format.h b/gettext-tools/src/format.h
index d92532d..3214a9d 100644
--- a/gettext-tools/src/format.h
+++ b/gettext-tools/src/format.h
@@ -119,6 +119,7 @@ extern DLL_VARIABLE struct formatstring_parser 
formatstring_gfc_internal;
 extern DLL_VARIABLE struct formatstring_parser formatstring_qt;
 extern DLL_VARIABLE struct formatstring_parser formatstring_qt_plural;
 extern DLL_VARIABLE struct formatstring_parser formatstring_kde;
+extern DLL_VARIABLE struct formatstring_parser formatstring_kde_kuit;
 extern DLL_VARIABLE struct formatstring_parser formatstring_boost;
 extern DLL_VARIABLE struct formatstring_parser formatstring_lua;
 extern DLL_VARIABLE struct formatstring_parser formatstring_javascript;
diff --git a/gettext-tools/src/libexpat-compat.c 
b/gettext-tools/src/libexpat-compat.c
index ad680db..31005a4 100644
--- a/gettext-tools/src/libexpat-compat.c
+++ b/gettext-tools/src/libexpat-compat.c
@@ -195,6 +195,16 @@ XML_SetCommentHandler (XML_Parser parser, 
XML_CommentHandler handler)
 }
 
 
+static void (*p_XML_SetUserData) (XML_Parser parser,
+                                  void *userData);
+
+void
+XML_SetUserData (XML_Parser parser, void *userData)
+{
+  (*p_XML_SetUserData) (parser, userData);
+}
+
+
 static int (*p_XML_Parse) (XML_Parser parser, const char *s,
                            int len, int isFinal);
 
@@ -300,6 +310,9 @@ load_libexpat ()
           && (p_XML_SetCommentHandler =
                 (void (*) (XML_Parser, XML_CommentHandler))
                 dlsym (handle, "XML_SetCommentHandler")) != NULL
+          && (p_XML_SetUserData =
+              (void (*) (XML_Parser, void *))
+              dlsym (handle, "XML_SetUserData")) != NULL
           && (p_XML_Parse =
                 (int (*) (XML_Parser, const char *, int, int))
                 dlsym (handle, "XML_Parse")) != NULL
diff --git a/gettext-tools/src/libexpat-compat.h 
b/gettext-tools/src/libexpat-compat.h
index 2ff6465..004f692 100644
--- a/gettext-tools/src/libexpat-compat.h
+++ b/gettext-tools/src/libexpat-compat.h
@@ -76,6 +76,7 @@ void XML_SetElementHandler (XML_Parser parser,
 void XML_SetCharacterDataHandler (XML_Parser parser,
                                   XML_CharacterDataHandler handler);
 void XML_SetCommentHandler (XML_Parser parser, XML_CommentHandler handler);
+void XML_SetUserData (XML_Parser parser, void *userData);
 int XML_Parse (XML_Parser parser, const char *s, int len, int isFinal);
 enum XML_Error XML_GetErrorCode (XML_Parser parser);
 int64_t XML_GetCurrentLineNumber (XML_Parser parser);
diff --git a/gettext-tools/src/message.c b/gettext-tools/src/message.c
index 2596887..00372a2 100644
--- a/gettext-tools/src/message.c
+++ b/gettext-tools/src/message.c
@@ -58,6 +58,7 @@ const char *const format_language[NFORMATS] =
   /* format_qt */               "qt",
   /* format_qt_plursl */        "qt-plural",
   /* format_kde */              "kde",
+  /* format_kde_kuit */         "kde-kuit",
   /* format_boost */            "boost",
   /* format_lua */              "lua",
   /* format_javascript */       "javascript"
@@ -89,6 +90,7 @@ const char *const format_language_pretty[NFORMATS] =
   /* format_qt */               "Qt",
   /* format_qt_plural */        "Qt plural",
   /* format_kde */              "KDE",
+  /* format_kde_kuit */         "KDE KUIT",
   /* format_boost */            "Boost",
   /* format_lua */              "Lua",
   /* format_javascript */       "JavaScript"
diff --git a/gettext-tools/src/message.h b/gettext-tools/src/message.h
index 8b9bc3f..3649e1b 100644
--- a/gettext-tools/src/message.h
+++ b/gettext-tools/src/message.h
@@ -67,11 +67,12 @@ enum format_type
   format_qt,
   format_qt_plural,
   format_kde,
+  format_kde_kuit,
   format_boost,
   format_lua,
   format_javascript
 };
-#define NFORMATS 27     /* Number of format_type enum values.  */
+#define NFORMATS 28     /* Number of format_type enum values.  */
 extern DLL_VARIABLE const char *const format_language[NFORMATS];
 extern DLL_VARIABLE const char *const format_language_pretty[NFORMATS];
 
diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c
index 310b349..d79fa5d 100644
--- a/gettext-tools/src/xgettext.c
+++ b/gettext-tools/src/xgettext.c
@@ -1864,6 +1864,11 @@ xgettext_record_flag (const char *optionstring)
                                                     name_start, name_end,
                                                     argnum, value, pass);
                     break;
+                  case format_kde_kuit:
+                    flag_context_list_table_insert (&flag_table_cxx_kde, 2,
+                                                    name_start, name_end,
+                                                    argnum, value, pass);
+                    break;
                   case format_boost:
                     flag_context_list_table_insert (&flag_table_cxx_boost, 1,
                                                     name_start, name_end,
@@ -2543,7 +2548,13 @@ meta information, not the empty string.\n")));
                && (possible_format_p (is_format[format_qt])
                    || possible_format_p (is_format[format_qt_plural])
                    || possible_format_p (is_format[format_kde])
-                   || possible_format_p (is_format[format_boost]))))
+                   || possible_format_p (is_format[format_kde_kuit])
+                   || possible_format_p (is_format[format_boost])))
+          /* Avoid flagging a string as both kde-format and kde-kuit-format.  
*/
+          && !(i == format_kde_kuit
+               && possible_format_p (is_format[format_kde]))
+          && !(i == format_kde
+               && possible_format_p (is_format[format_kde_kuit])))
         {
           struct formatstring_parser *parser = formatstring_parsers[i];
           char *invalid_reason = NULL;
@@ -2678,7 +2689,13 @@ remember_a_message_plural (message_ty *mp, char *string,
                  && (possible_format_p (mp->is_format[format_qt])
                      || possible_format_p (mp->is_format[format_qt_plural])
                      || possible_format_p (mp->is_format[format_kde])
-                     || possible_format_p (mp->is_format[format_boost]))))
+                     || possible_format_p (mp->is_format[format_kde_kuit])
+                     || possible_format_p (mp->is_format[format_boost])))
+            /* Avoid flagging a string as both kde-format and kde-kuit-format. 
 */
+            && !(i == format_kde_kuit
+                 && possible_format_p (mp->is_format[format_kde]))
+            && !(i == format_kde
+                 && possible_format_p (mp->is_format[format_kde_kuit])))
           {
             struct formatstring_parser *parser = formatstring_parsers[i];
             char *invalid_reason = NULL;
@@ -3706,6 +3723,7 @@ language_to_extractor (const char *name)
           {
             result.flag_table = &flag_table_cxx_kde;
             result.formatstring_parser2 = &formatstring_kde;
+            result.formatstring_parser3 = &formatstring_kde_kuit;
           }
         /* Likewise for --boost.  */
         if (recognize_format_boost && strcmp (tp->name, "C++") == 0)
diff --git a/gettext-tools/tests/ChangeLog b/gettext-tools/tests/ChangeLog
index 1ba2935..72a46d4 100644
--- a/gettext-tools/tests/ChangeLog
+++ b/gettext-tools/tests/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-05  Daiki Ueno  <address@hidden>
+
+       * format-kde-kuit-1: New file.
+       * format-kde-kuit-2: New file.
+       * Makefile.am (TESTS): Add new tests.
+
 2015-03-03  Daiki Ueno  <address@hidden>
 
        * xgettext-14: New file.
diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am
index ea8bfa9..a4decaf 100644
--- a/gettext-tools/tests/Makefile.am
+++ b/gettext-tools/tests/Makefile.am
@@ -119,6 +119,7 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 
gettext-6 gettext-7 \
        format-gfc-internal-1 format-gfc-internal-2 \
        format-java-1 format-java-2 \
        format-kde-1 format-kde-2 \
+       format-kde-kuit-1 format-kde-kuit-2 \
        format-librep-1 format-librep-2 \
        format-lisp-1 format-lisp-2 \
        format-php-1 format-php-2 \
diff --git a/gettext-tools/tests/format-kde-kuit-1 
b/gettext-tools/tests/format-kde-kuit-1
new file mode 100755
index 0000000..c6a5eab
--- /dev/null
+++ b/gettext-tools/tests/format-kde-kuit-1
@@ -0,0 +1,57 @@
+#! /bin/sh
+. "${srcdir=.}/init.sh"; path_prepend_ . ../src
+
+# Test recognition of KDE KUIT format strings.
+
+cat <<\EOF > f-kd-1.data
+# Unrecognized: unbalanced filename tag
+"<filename>a"
+# Unrecognized: unbalanced filename tag
+"<filename>%1"
+# Unrecognized: unbalanced filename tag
+"<filename>%1</xfilename>"
+# Valid: one argument
+"<filename>%1</filename>"
+# Valid: accelerator
+"<command>&About</command>"
+# Valid: entity reference
+"<command>&amp;About</command>"
+# Valid: character reference
+"<command>&#x61;&#141;</command>"
+EOF
+
+: ${XGETTEXT=xgettext}
+n=0
+while read comment; do
+  read string
+  n=`expr $n + 1`
+  cat <<EOF > f-kd-1-$n.in
+xi18n(${string});
+EOF
+  ${XGETTEXT} -L C++ --kde --flag=xi18n:1:kde-kuit-format 
--flag=i18n:1:kde-format -kxi18n -ki18n -o f-kd-1-$n.po f-kd-1-$n.in || exit 1
+  test -f f-kd-1-$n.po || exit 1
+  fail=
+  if echo "$comment" | grep 'Valid:' > /dev/null; then
+    if grep kde-kuit-format f-kd-1-$n.po > /dev/null; then
+      :
+    else
+      fail=yes
+    fi
+  else
+    if grep kde-kuit-format f-kd-1-$n.po > /dev/null; then
+      fail=yes
+    else
+      :
+    fi
+  fi
+  if test -n "$fail"; then
+    echo "Format string recognition error:" 1>&2
+    cat f-kd-1-$n.in 1>&2
+    echo "Got:" 1>&2
+    cat f-kd-1-$n.po 1>&2
+    exit 1
+  fi
+  rm -f f-kd-1-$n.in f-kd-1-$n.po
+done < f-kd-1.data
+
+exit 0
diff --git a/gettext-tools/tests/format-kde-kuit-2 
b/gettext-tools/tests/format-kde-kuit-2
new file mode 100755
index 0000000..5574a52
--- /dev/null
+++ b/gettext-tools/tests/format-kde-kuit-2
@@ -0,0 +1,64 @@
+#! /bin/sh
+. "${srcdir=.}/init.sh"; path_prepend_ . ../src
+
+# Test checking of KDE KUIT format strings.
+
+cat <<\EOF > f-kd-2.data
+# Valid: one argument
+msgid "<filename>%1</filename>"
+msgstr "<filename>%1</filename>"
+# Valid: change the text
+msgid "<filename>foo</filename>"
+msgstr "<filename>bar</filename>"
+# Invalid: unbalanced tag
+msgid "<filename>foo</filename>"
+msgstr "<filename>bar"
+# Invalid: unbalanced tag
+msgid "<filename>foo</filename>"
+msgstr "<filename>bar</xfilename>"
+# Valid: replaced tag
+msgid "<filename>foo</filename>"
+msgstr "<foo>foo</foo>"
+# Valid: accelerator
+msgid "<filename>&foo</filename>"
+msgstr "<foo>&foo</foo>"
+# Valid: entity reference
+msgid "<filename>foo</filename>"
+msgstr "<foo>&amp;</foo>"
+EOF
+
+: ${MSGFMT=msgfmt}
+n=0
+while read comment; do
+  read msgid_line
+  read msgstr_line
+  n=`expr $n + 1`
+  cat <<EOF > f-kd-2-$n.po
+#, kde-kuit-format
+${msgid_line}
+${msgstr_line}
+EOF
+  fail=
+  if echo "$comment" | grep 'Valid:' > /dev/null; then
+    if ${MSGFMT} --check-format -o f-kd-2-$n.mo f-kd-2-$n.po; then
+      :
+    else
+      fail=yes
+    fi
+  else
+    ${MSGFMT} --check-format -o f-kd-2-$n.mo f-kd-2-$n.po 2> /dev/null
+    if test $? = 1; then
+      :
+    else
+      fail=yes
+    fi
+  fi
+  if test -n "$fail"; then
+    echo "Format string checking error:" 1>&2
+    cat f-kd-2-$n.po 1>&2
+    exit 1
+  fi
+  rm -f f-kd-2-$n.po f-kd-2-$n.mo
+done < f-kd-2.data
+
+exit 0
-- 
2.1.0


reply via email to

[Prev in Thread] Current Thread [Next in Thread]