From 4fcef5686c4807721c5e8536db542293ee8d804e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?I=C3=B1igo=20Mart=C3=ADnez?=
Date: Tue, 6 Jun 2017 11:43:02 +0200
Subject: [PATCH 1/3] Added support for plugin file string extraction in
xgettext.
* gettext-tools/doc/xgettext.texi: Filled information regarding plugin
options.
* gettext-tools/src/Makefile.am: Added x-plugin.c and x-plugin.h files.
* gettext-tools/src/x-desktop.c: Removed static keyword for extract methods
not using static variables that can be shared.
* gettext-tools/src/x-desktop.h: Exposed extract methods and the reader
structure to be shared among Desktop Entry like files.
* gettext-tools/src/x-plugin.c: Support for plugin files.
* gettext-tools/src/x-plugin.h: Exposed extract method for plugin files.
* gettext-tools/src/xgettext.c: Added support for plugin backend.
* tests/Makefile.am: Added xgettext-plugin-1 file.
* tests/xgettext-plugin-1: A new test for plugin files based on Desktop
test.
---
gettext-tools/doc/xgettext.texi | 7 +-
gettext-tools/src/Makefile.am | 4 +-
gettext-tools/src/x-desktop.c | 14 +---
gettext-tools/src/x-desktop.h | 19 +++++
gettext-tools/src/x-plugin.c | 150 ++++++++++++++++++++++++++++++++++
gettext-tools/src/x-plugin.h | 47 +++++++++++
gettext-tools/src/xgettext.c | 8 +-
gettext-tools/tests/Makefile.am | 1 +
gettext-tools/tests/xgettext-plugin-1 | 95 +++++++++++++++++++++
9 files changed, 328 insertions(+), 17 deletions(-)
create mode 100644 gettext-tools/src/x-plugin.c
create mode 100644 gettext-tools/src/x-plugin.h
create mode 100755 gettext-tools/tests/xgettext-plugin-1
diff --git a/gettext-tools/doc/xgettext.texi b/gettext-tools/doc/xgettext.texi
index e2700d9f5..84bcb849d 100644
--- a/gettext-tools/doc/xgettext.texi
+++ b/gettext-tools/doc/xgettext.texi
@@ -74,7 +74,7 @@ are @code{C}, @code{C++}, @code{ObjectiveC}, @code{PO}, @code{Shell},
@code{Smalltalk}, @code{Java}, @code{JavaProperties}, @code{C#}, @code{awk},
@code{YCP}, @code{Tcl}, @code{Perl}, @code{PHP}, @code{GCC-source},
@code{NXStringTable}, @code{RST}, @code{Glade}, @code{Lua}, @code{JavaScript},
address@hidden, @code{GSettings}, @code{Desktop}.
address@hidden, @code{GSettings}, @code{Desktop}, @code{Plugin}.
@item -C
@itemx --c++
@@ -257,7 +257,7 @@ escaped.
This option has an effect with most languages, namely C, C++, ObjectiveC,
Shell, Python, Lisp, EmacsLisp, librep, Java, C#, awk, Tcl, Perl, PHP,
-GCC-source, Glade, Lua, JavaScript, Vala, GSettings, Desktop.
+GCC-source, Glade, Lua, JavaScript, Vala, GSettings, Desktop, Plugin.
The default keyword specifications, which are always looked for if not
explicitly disabled, are language dependent. They are:
@@ -341,6 +341,9 @@ For Vala: @code{_}, @code{Q_}, @code{N_}, @code{NC_}, @code{dgettext:2},
@item
For Desktop: @code{Name}, @code{GenericName}, @code{Comment},
@code{Icon}, @code{Keywords}.
+
address@hidden
+For Plugin: @code{Name}, @code{Description}.
@end itemize
To disable the default keyword specifications, the option @samp{-k} or
diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am
index 764afd13a..bf1c7a0df 100644
--- a/gettext-tools/src/Makefile.am
+++ b/gettext-tools/src/Makefile.am
@@ -55,7 +55,7 @@ po-time.h plural-table.h lang-table.h format.h filters.h \
xgettext.h x-c.h x-po.h x-sh.h x-python.h x-lisp.h x-elisp.h x-librep.h \
x-scheme.h x-smalltalk.h x-java.h x-properties.h x-csharp.h x-awk.h x-ycp.h \
x-tcl.h x-perl.h x-php.h x-stringtable.h x-rst.h x-glade.h x-lua.h \
-x-javascript.h x-vala.h x-gsettings.h x-desktop.h x-appdata.h
+x-javascript.h x-vala.h x-gsettings.h x-desktop.h x-appdata.h x-plugin.h
EXTRA_DIST += FILES project-id
@@ -180,7 +180,7 @@ 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-lua.c x-javascript.c x-vala.c \
- x-desktop.c
+ x-desktop.c x-plugin.c
if !WOE32DLL
msgattrib_SOURCES = msgattrib.c
else
diff --git a/gettext-tools/src/x-desktop.c b/gettext-tools/src/x-desktop.c
index 3f382ff50..862965f17 100644
--- a/gettext-tools/src/x-desktop.c
+++ b/gettext-tools/src/x-desktop.c
@@ -92,15 +92,7 @@ init_keywords (void)
}
}
-typedef struct extract_desktop_reader_ty extract_desktop_reader_ty;
-struct extract_desktop_reader_ty
-{
- DESKTOP_READER_TY
-
- message_list_ty *mlp;
-};
-
-static void
+void
extract_desktop_handle_group (struct desktop_reader_ty *reader,
const char *group)
{
@@ -131,7 +123,7 @@ extract_desktop_handle_pair (struct desktop_reader_ty *reader,
savable_comment_reset ();
}
-static void
+void
extract_desktop_handle_comment (struct desktop_reader_ty *reader,
const char *buffer)
{
@@ -153,7 +145,7 @@ extract_desktop_handle_comment (struct desktop_reader_ty *reader,
}
}
-static void
+void
extract_desktop_handle_blank (struct desktop_reader_ty *reader,
const char *s)
{
diff --git a/gettext-tools/src/x-desktop.h b/gettext-tools/src/x-desktop.h
index 4a820e5dd..194277855 100644
--- a/gettext-tools/src/x-desktop.h
+++ b/gettext-tools/src/x-desktop.h
@@ -20,6 +20,7 @@
#include "message.h"
#include "xgettext.h"
+#include "read-desktop.h"
#ifdef __cplusplus
@@ -33,6 +34,15 @@ extern "C" {
#define SCANNERS_DESKTOP \
{ "Desktop", extract_desktop, NULL, NULL, NULL, NULL }, \
+/* Desktop Entry like file reader. */
+typedef struct extract_desktop_reader_ty extract_desktop_reader_ty;
+struct extract_desktop_reader_ty
+{
+ DESKTOP_READER_TY
+
+ message_list_ty *mlp;
+};
+
/* Scan a Desktop Entry file and add its translatable strings to mdlp. */
extern void extract_desktop (FILE *fp, const char *real_filename,
const char *logical_filename,
@@ -41,6 +51,15 @@ extern void extract_desktop (FILE *fp, const char *real_filename,
extern void x_desktop_keyword (const char *keyword);
+/* Handle Group from a Desktop Entry like file. */
+extern void extract_desktop_handle_group (struct desktop_reader_ty *reader,
+ const char *group);
+/* Handle comments from a Desktop Entry like file. */
+extern void extract_desktop_handle_comment (struct desktop_reader_ty *reader,
+ const char *buffer);
+/* Handle blanks from a Desktop Entry like file. */
+extern void extract_desktop_handle_blank (struct desktop_reader_ty *reader,
+ const char *s);
#ifdef __cplusplus
}
diff --git a/gettext-tools/src/x-plugin.c b/gettext-tools/src/x-plugin.c
new file mode 100644
index 000000000..ca92adefb
--- /dev/null
+++ b/gettext-tools/src/x-plugin.c
@@ -0,0 +1,150 @@
+/* xgettext Desktop Entry backend.
+ Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+ This file was written by Iñigo Martínez , 2017.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* Specification. */
+#include "x-plugin.h"
+#include "x-desktop.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "message.h"
+#include "xgettext.h"
+#include "error.h"
+#include "error-progname.h"
+#include "xalloc.h"
+#include "xvasprintf.h"
+#include "hash.h"
+#include "gettext.h"
+#include "read-desktop.h"
+#include "po-charset.h"
+
+/* ====================== Keyword set customization. ====================== */
+
+/* The syntax of libpeas Plugin file is a Desktop Entry variant with a
+ custom set of keys. It is defined at
+ https://git.gnome.org/browse/libpeas/tree/libpeas/peas-plugin-info.c
+
+ The syntax of a Desktop Entry file is defined at
+ http://standards.freedesktop.org/desktop-entry-spec/latest/index.html
+
+ Basically, values with 'localestring' type can be translated.
+
+ The type of a value is determined by looking at the key associated
+ with it. The list of available keys are listed on:
+ http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s05.html */
+
+static hash_table keywords;
+static bool default_keywords = true;
+
+static void
+add_keyword (const char *name, hash_table *keywords, bool is_list)
+{
+ if (name == NULL)
+ default_keywords = false;
+ else
+ {
+ if (keywords->table == NULL)
+ hash_init (keywords, 100);
+
+ desktop_add_keyword (keywords, name, is_list);
+ }
+}
+
+void
+x_plugin_keyword (const char *name)
+{
+ add_keyword (name, &keywords, false);
+}
+
+static void
+init_keywords (void)
+{
+ if (default_keywords)
+ {
+ if (keywords.table == NULL)
+ hash_init (&keywords, 100);
+
+ desktop_add_keyword (&keywords, "Name", false);
+ desktop_add_keyword (&keywords, "Description", false);
+ default_keywords = false;
+ }
+}
+
+static void
+extract_plugin_handle_pair (struct desktop_reader_ty *reader,
+ lex_pos_ty *key_pos,
+ const char *key,
+ const char *locale,
+ const char *value)
+{
+ extract_desktop_reader_ty *extract_reader =
+ (extract_desktop_reader_ty *) reader;
+ void *keyword_value;
+
+ if (!locale /* Skip already translated entry. */
+ && hash_find_entry (&keywords, key, strlen (key), &keyword_value) == 0)
+ {
+ bool is_list = (bool) keyword_value;
+
+ remember_a_message (extract_reader->mlp, NULL,
+ desktop_unescape_string (value, is_list),
+ null_context, key_pos,
+ NULL, savable_comment);
+ }
+ savable_comment_reset ();
+}
+
+desktop_reader_class_ty extract_plugin_methods =
+ {
+ sizeof (extract_desktop_reader_ty),
+ NULL,
+ NULL,
+ extract_desktop_handle_group,
+ extract_plugin_handle_pair,
+ extract_desktop_handle_comment,
+ extract_desktop_handle_blank
+ };
+
+void
+extract_plugin (FILE *f,
+ const char *real_filename, const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp)
+{
+ desktop_reader_ty *reader = desktop_reader_alloc (&extract_plugin_methods);
+ extract_desktop_reader_ty *extract_reader =
+ (extract_desktop_reader_ty *) reader;
+
+ init_keywords ();
+ xgettext_current_source_encoding = po_charset_utf8;
+
+ extract_reader->mlp = mdlp->item[0]->messages;
+
+ desktop_parse (reader, f, real_filename, logical_filename);
+ desktop_reader_free (reader);
+
+ reader = NULL;
+}
diff --git a/gettext-tools/src/x-plugin.h b/gettext-tools/src/x-plugin.h
new file mode 100644
index 000000000..548ba3d30
--- /dev/null
+++ b/gettext-tools/src/x-plugin.h
@@ -0,0 +1,47 @@
+/* xgettext plugin backend.
+ Copyright (C) 2014-2017 Free Software Foundation, Inc.
+ Written by Iñigo Martínez , 2017.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see . */
+
+
+#include
+
+#include "message.h"
+#include "xgettext.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define EXTENSIONS_PLUGIN \
+ { "plugin", "Plugin" }, \
+
+#define SCANNERS_PLUGIN \
+ { "Plugin", extract_plugin, NULL, NULL, NULL, NULL }, \
+
+/* Scan a Plugin file and add its translatable strings to mdlp. */
+extern void extract_plugin (FILE *fp, const char *real_filename,
+ const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp);
+
+extern void x_plugin_keyword (const char *keyword);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c
index a80ee51ac..5f24dc8ad 100644
--- a/gettext-tools/src/xgettext.c
+++ b/gettext-tools/src/xgettext.c
@@ -106,6 +106,7 @@
#include "x-vala.h"
#include "x-gsettings.h"
#include "x-desktop.h"
+#include "x-plugin.h"
#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
@@ -487,6 +488,7 @@ main (int argc, char *argv[])
x_javascript_keyword (optarg);
x_vala_keyword (optarg);
x_desktop_keyword (optarg);
+ x_plugin_keyword (optarg);
if (optarg == NULL)
no_default_keywords = true;
else
@@ -1080,7 +1082,7 @@ Choice of input file language:\n"));
EmacsLisp, librep, Scheme, Smalltalk, Java,\n\
JavaProperties, C#, awk, YCP, Tcl, Perl, PHP,\n\
GCC-source, NXStringTable, RST, Glade, Lua,\n\
- JavaScript, Vala, Desktop)\n"));
+ JavaScript, Vala, Desktop, Plugin)\n"));
printf (_("\
-C, --c++ shorthand for --language=C++\n"));
printf (_("\
@@ -1130,7 +1132,7 @@ Language specific options:\n"));
(only languages C, C++, ObjectiveC, Shell,\n\
Python, Lisp, EmacsLisp, librep, Scheme, Java,\n\
C#, awk, Tcl, Perl, PHP, GCC-source, Glade,\n\
- Lua, JavaScript, Vala, Desktop)\n"));
+ Lua, JavaScript, Vala, Desktop, Plugin)\n"));
printf (_("\
--flag=WORD:ARG:FLAG additional flag for strings inside the argument\n\
number ARG of keyword WORD\n"));
@@ -3904,6 +3906,7 @@ language_to_extractor (const char *name)
SCANNERS_GSETTINGS
SCANNERS_DESKTOP
SCANNERS_APPDATA
+ SCANNERS_PLUGIN
/* Here may follow more languages and their scanners: pike, etc...
Make sure new scanners honor the --exclude-file option. */
};
@@ -3995,6 +3998,7 @@ extension_to_language (const char *extension)
EXTENSIONS_GSETTINGS
EXTENSIONS_DESKTOP
EXTENSIONS_APPDATA
+ EXTENSIONS_PLUGIN
/* Here may follow more file extensions... */
};
diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am
index 38b47b922..f50509a6a 100644
--- a/gettext-tools/tests/Makefile.am
+++ b/gettext-tools/tests/Makefile.am
@@ -114,6 +114,7 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 gettext-6 gettext-7 \
xgettext-gsettings-1 \
xgettext-desktop-1 \
xgettext-its-1 xgettext-its-2 \
+ xgettext-plugin-1 \
format-awk-1 format-awk-2 \
format-boost-1 format-boost-2 \
format-c-1 format-c-2 format-c-3 format-c-4 format-c-5 \
diff --git a/gettext-tools/tests/xgettext-plugin-1 b/gettext-tools/tests/xgettext-plugin-1
new file mode 100755
index 000000000..141488b1b
--- /dev/null
+++ b/gettext-tools/tests/xgettext-plugin-1
@@ -0,0 +1,95 @@
+#!/bin/sh
+. "${srcdir=.}/init.sh"; path_prepend_ . ../src
+
+# Test of Plugin support.
+
+: ${XGETTEXT=xgettext}
+
+cat <<\EOF >err1.plugin
+[Plugin]
+This is an invalid line
+Name =Foo
+EOF
+
+(LANGUAGE= LC_ALL=C ${XGETTEXT} --add-comments -o - err1.plugin 2>&1; exit) | grep "missing '=' after" || Exit 1
+
+cat <<\EOF >err2.plugin
+[Plugin
+EOF
+
+(LANGUAGE= LC_ALL=C ${XGETTEXT} --add-comments -o - err2.plugin 2>&1; exit) | grep "unterminated group name" || Exit 1
+
+cat <<\EOF >err3.plugin
+[Plugin]
+ Not a blank line!
+EOF
+
+(LANGUAGE= LC_ALL=C ${XGETTEXT} --add-comments -o - err3.plugin 2>&1; exit) | grep "invalid non-blank line" || Exit 1
+
+cat <<\EOF >err4.plugin
+[Plugin]a
+EOF
+
+(LANGUAGE= LC_ALL=C ${XGETTEXT} --add-comments -o - err4.plugin 2>&1; exit) | grep "invalid non-blank character" || Exit 1
+
+# gettext 0.19.4 issued an baseless warning of this.
+cat <<\EOF >ok4.plugin
+[Plugin]
+EOF
+
+(LANGUAGE= LC_ALL=C ${XGETTEXT} --add-comments -o - ok4.plugin 2>&1; exit) | grep "invalid non-blank character" && Exit 1
+
+cat <<\EOF > xg.plugin
+[Plugin]
+Module=helloworld
+Loader=C
+Name =Foo
+# This is a comment for description
+# This is a comment for description
+Description= \sThis is a \nmultiline\t description; for testing
+Description[foo]=Already translated description
+Copyright = Copyright (C) 1995-1998, 2000-2016 Free Software Foundation, Inc.
+# This is a comment before a blank line
+
+Website=https://wiki.gnome.org/Projects/Libpeas
+EOF
+
+${XGETTEXT} --add-comments -o - xg.plugin | grep -v 'POT-Creation-Date' > xg-plugin.pot || Exit 1
+
+cat <<\EOF > xg-plugin.ok
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: xg.plugin:5
+msgid "Foo"
+msgstr ""
+
+#. This is a comment for description
+#. This is a comment for description
+#: xg.desktop:8
+msgid ""
+" This is a \n"
+"multiline\t description; for testing"
+msgstr ""
+EOF
+
+: ${DIFF=diff}
+${DIFF} xg-plugin.ok xg-plugin.pot
+result=$?
+
+exit $result
--
2.11.0