summaryrefslogtreecommitdiff
path: root/gettext-tools/src
diff options
context:
space:
mode:
Diffstat (limited to 'gettext-tools/src')
-rw-r--r--gettext-tools/src/ChangeLog.1 (renamed from gettext-tools/src/ChangeLog)350
-rw-r--r--gettext-tools/src/FILES3
-rw-r--r--gettext-tools/src/Makefile.am38
-rw-r--r--gettext-tools/src/Makefile.in517
-rw-r--r--gettext-tools/src/cldr-plural-exp.c695
-rw-r--r--gettext-tools/src/cldr-plural-exp.h141
-rw-r--r--gettext-tools/src/cldr-plural.c2013
-rw-r--r--gettext-tools/src/cldr-plural.h102
-rw-r--r--gettext-tools/src/cldr-plural.y469
-rw-r--r--gettext-tools/src/cldr-plurals.c370
-rw-r--r--gettext-tools/src/color.c2
-rw-r--r--gettext-tools/src/color.h2
-rw-r--r--gettext-tools/src/dir-list.c3
-rw-r--r--gettext-tools/src/dir-list.h3
-rw-r--r--gettext-tools/src/file-list.c3
-rw-r--r--gettext-tools/src/file-list.h2
-rw-r--r--gettext-tools/src/filter-quote.c226
-rw-r--r--gettext-tools/src/filter-sr-latin.c2
-rw-r--r--gettext-tools/src/format-awk.c3
-rw-r--r--gettext-tools/src/format-boost.c3
-rw-r--r--gettext-tools/src/format-c-parse.h3
-rw-r--r--gettext-tools/src/format-c.c3
-rw-r--r--gettext-tools/src/format-csharp.c3
-rw-r--r--gettext-tools/src/format-elisp.c3
-rw-r--r--gettext-tools/src/format-gcc-internal.c2
-rw-r--r--gettext-tools/src/format-gfc-internal.c2
-rw-r--r--gettext-tools/src/format-invalid.h2
-rw-r--r--gettext-tools/src/format-java.c3
-rw-r--r--gettext-tools/src/format-javascript.c3
-rw-r--r--gettext-tools/src/format-kde-kuit.c411
-rw-r--r--gettext-tools/src/format-kde.c3
-rw-r--r--gettext-tools/src/format-librep.c3
-rw-r--r--gettext-tools/src/format-lisp.c3
-rw-r--r--gettext-tools/src/format-lua.c2
-rw-r--r--gettext-tools/src/format-pascal.c3
-rw-r--r--gettext-tools/src/format-perl-brace.c2
-rw-r--r--gettext-tools/src/format-perl.c3
-rw-r--r--gettext-tools/src/format-php.c3
-rw-r--r--gettext-tools/src/format-python-brace.c3
-rw-r--r--gettext-tools/src/format-python.c3
-rw-r--r--gettext-tools/src/format-qt-plural.c3
-rw-r--r--gettext-tools/src/format-qt.c3
-rw-r--r--gettext-tools/src/format-scheme.c2
-rw-r--r--gettext-tools/src/format-sh.c3
-rw-r--r--gettext-tools/src/format-tcl.c3
-rw-r--r--gettext-tools/src/format-ycp.c3
-rw-r--r--gettext-tools/src/format.c3
-rw-r--r--gettext-tools/src/format.h3
-rw-r--r--gettext-tools/src/gnu/gettext/DumpResource.java2
-rw-r--r--gettext-tools/src/gnu/gettext/GetURL.java2
-rw-r--r--gettext-tools/src/hostname.c3
-rw-r--r--gettext-tools/src/its.c1946
-rw-r--r--gettext-tools/src/its.h85
-rw-r--r--gettext-tools/src/lang-table.c2
-rw-r--r--gettext-tools/src/lang-table.h2
-rw-r--r--gettext-tools/src/libexpat-compat.c326
-rw-r--r--gettext-tools/src/libexpat-compat.h94
-rw-r--r--gettext-tools/src/locating-rule.c437
-rw-r--r--gettext-tools/src/locating-rule.h50
-rw-r--r--gettext-tools/src/message.c17
-rw-r--r--gettext-tools/src/message.h32
-rw-r--r--gettext-tools/src/msgattrib.c3
-rw-r--r--gettext-tools/src/msgcat.c3
-rw-r--r--gettext-tools/src/msgcmp.c3
-rw-r--r--gettext-tools/src/msgcomm.c3
-rw-r--r--gettext-tools/src/msgconv.c3
-rw-r--r--gettext-tools/src/msgen.c3
-rw-r--r--gettext-tools/src/msgexec.c29
-rw-r--r--gettext-tools/src/msgfilter.c51
-rw-r--r--gettext-tools/src/msgfmt.c382
-rw-r--r--gettext-tools/src/msgfmt.cs2
-rw-r--r--gettext-tools/src/msgfmt.h29
-rw-r--r--gettext-tools/src/msggrep.c3
-rw-r--r--gettext-tools/src/msginit.c86
-rw-r--r--gettext-tools/src/msgl-ascii.c3
-rw-r--r--gettext-tools/src/msgl-ascii.h2
-rw-r--r--gettext-tools/src/msgl-cat.c16
-rw-r--r--gettext-tools/src/msgl-cat.h2
-rw-r--r--gettext-tools/src/msgl-charset.c3
-rw-r--r--gettext-tools/src/msgl-charset.h2
-rw-r--r--gettext-tools/src/msgl-check.c208
-rw-r--r--gettext-tools/src/msgl-check.h5
-rw-r--r--gettext-tools/src/msgl-english.c2
-rw-r--r--gettext-tools/src/msgl-english.h2
-rw-r--r--gettext-tools/src/msgl-equal.c3
-rw-r--r--gettext-tools/src/msgl-equal.h2
-rw-r--r--gettext-tools/src/msgl-fsearch.c2
-rw-r--r--gettext-tools/src/msgl-fsearch.h2
-rw-r--r--gettext-tools/src/msgl-header.c2
-rw-r--r--gettext-tools/src/msgl-header.h2
-rw-r--r--gettext-tools/src/msgl-iconv.c3
-rw-r--r--gettext-tools/src/msgl-iconv.h3
-rw-r--r--gettext-tools/src/msgmerge.c11
-rw-r--r--gettext-tools/src/msgunfmt.c3
-rw-r--r--gettext-tools/src/msgunfmt.cs2
-rw-r--r--gettext-tools/src/msgunfmt.h3
-rw-r--r--gettext-tools/src/msgunfmt.tcl2
-rw-r--r--gettext-tools/src/msguniq.c3
-rw-r--r--gettext-tools/src/open-catalog.c3
-rw-r--r--gettext-tools/src/open-catalog.h3
-rw-r--r--gettext-tools/src/plural-count.c2
-rw-r--r--gettext-tools/src/plural-count.h2
-rw-r--r--gettext-tools/src/plural-distrib.h2
-rw-r--r--gettext-tools/src/plural-eval.c2
-rw-r--r--gettext-tools/src/plural-eval.h2
-rw-r--r--gettext-tools/src/plural-exp.c2
-rw-r--r--gettext-tools/src/plural-table.c3
-rw-r--r--gettext-tools/src/plural-table.h2
-rw-r--r--gettext-tools/src/po-charset.c2
-rw-r--r--gettext-tools/src/po-charset.h2
-rw-r--r--gettext-tools/src/po-error.c2
-rw-r--r--gettext-tools/src/po-error.h2
-rw-r--r--gettext-tools/src/po-gram-gen.c122
-rw-r--r--gettext-tools/src/po-gram-gen.h10
-rw-r--r--gettext-tools/src/po-gram-gen.y3
-rw-r--r--gettext-tools/src/po-gram-gen2.h10
-rw-r--r--gettext-tools/src/po-gram.h3
-rw-r--r--gettext-tools/src/po-lex.c2
-rw-r--r--gettext-tools/src/po-lex.h3
-rw-r--r--gettext-tools/src/po-time.c3
-rw-r--r--gettext-tools/src/po-time.h2
-rw-r--r--gettext-tools/src/po-xerror.c2
-rw-r--r--gettext-tools/src/po-xerror.h2
-rw-r--r--gettext-tools/src/pos.h3
-rwxr-xr-xgettext-tools/src/project-id2
-rw-r--r--gettext-tools/src/quote.h142
-rw-r--r--gettext-tools/src/read-catalog-abstract.c38
-rw-r--r--gettext-tools/src/read-catalog-abstract.h6
-rw-r--r--gettext-tools/src/read-catalog.c11
-rw-r--r--gettext-tools/src/read-catalog.h4
-rw-r--r--gettext-tools/src/read-csharp.c3
-rw-r--r--gettext-tools/src/read-csharp.h2
-rw-r--r--gettext-tools/src/read-desktop.c18
-rw-r--r--gettext-tools/src/read-desktop.h3
-rw-r--r--gettext-tools/src/read-java.c3
-rw-r--r--gettext-tools/src/read-java.h2
-rw-r--r--gettext-tools/src/read-mo.c14
-rw-r--r--gettext-tools/src/read-mo.h3
-rw-r--r--gettext-tools/src/read-po.c3
-rw-r--r--gettext-tools/src/read-po.h2
-rw-r--r--gettext-tools/src/read-properties.c3
-rw-r--r--gettext-tools/src/read-properties.h2
-rw-r--r--gettext-tools/src/read-resources.c3
-rw-r--r--gettext-tools/src/read-resources.h2
-rw-r--r--gettext-tools/src/read-stringtable.c3
-rw-r--r--gettext-tools/src/read-stringtable.h2
-rw-r--r--gettext-tools/src/read-tcl.c3
-rw-r--r--gettext-tools/src/read-tcl.h2
-rw-r--r--gettext-tools/src/recode-sr-latin.c3
-rw-r--r--gettext-tools/src/sentence.c194
-rw-r--r--gettext-tools/src/sentence.h42
-rw-r--r--gettext-tools/src/str-list.c3
-rw-r--r--gettext-tools/src/str-list.h3
-rw-r--r--gettext-tools/src/urlget.c3
-rw-r--r--gettext-tools/src/user-email.sh.in2
-rw-r--r--gettext-tools/src/write-catalog.c3
-rw-r--r--gettext-tools/src/write-catalog.h3
-rw-r--r--gettext-tools/src/write-csharp.c2
-rw-r--r--gettext-tools/src/write-csharp.h2
-rw-r--r--gettext-tools/src/write-desktop.c63
-rw-r--r--gettext-tools/src/write-desktop.h8
-rw-r--r--gettext-tools/src/write-java.c3
-rw-r--r--gettext-tools/src/write-java.h2
-rw-r--r--gettext-tools/src/write-mo.c3
-rw-r--r--gettext-tools/src/write-mo.h3
-rw-r--r--gettext-tools/src/write-po.c5
-rw-r--r--gettext-tools/src/write-po.h3
-rw-r--r--gettext-tools/src/write-properties.c2
-rw-r--r--gettext-tools/src/write-properties.h2
-rw-r--r--gettext-tools/src/write-qt.c3
-rw-r--r--gettext-tools/src/write-qt.h2
-rw-r--r--gettext-tools/src/write-resources.c3
-rw-r--r--gettext-tools/src/write-resources.h2
-rw-r--r--gettext-tools/src/write-stringtable.c2
-rw-r--r--gettext-tools/src/write-stringtable.h2
-rw-r--r--gettext-tools/src/write-tcl.c3
-rw-r--r--gettext-tools/src/write-tcl.h2
-rw-r--r--gettext-tools/src/write-xml.c107
-rw-r--r--gettext-tools/src/write-xml.h52
-rw-r--r--gettext-tools/src/x-appdata.h42
-rw-r--r--gettext-tools/src/x-awk.c3
-rw-r--r--gettext-tools/src/x-awk.h4
-rw-r--r--gettext-tools/src/x-c.c299
-rw-r--r--gettext-tools/src/x-c.h15
-rw-r--r--gettext-tools/src/x-csharp.c3
-rw-r--r--gettext-tools/src/x-csharp.h2
-rw-r--r--gettext-tools/src/x-desktop.c2
-rw-r--r--gettext-tools/src/x-desktop.h2
-rw-r--r--gettext-tools/src/x-elisp.c3
-rw-r--r--gettext-tools/src/x-elisp.h2
-rw-r--r--gettext-tools/src/x-glade.c612
-rw-r--r--gettext-tools/src/x-glade.h27
-rw-r--r--gettext-tools/src/x-gsettings.c386
-rw-r--r--gettext-tools/src/x-gsettings.h17
-rw-r--r--gettext-tools/src/x-java.c2
-rw-r--r--gettext-tools/src/x-java.h2
-rw-r--r--gettext-tools/src/x-javascript.c3
-rw-r--r--gettext-tools/src/x-javascript.h3
-rw-r--r--gettext-tools/src/x-librep.c3
-rw-r--r--gettext-tools/src/x-librep.h2
-rw-r--r--gettext-tools/src/x-lisp.c3
-rw-r--r--gettext-tools/src/x-lisp.h2
-rw-r--r--gettext-tools/src/x-lua.c2
-rw-r--r--gettext-tools/src/x-lua.h2
-rw-r--r--gettext-tools/src/x-perl.c2
-rw-r--r--gettext-tools/src/x-perl.h3
-rw-r--r--gettext-tools/src/x-php.c3
-rw-r--r--gettext-tools/src/x-php.h2
-rw-r--r--gettext-tools/src/x-po.c3
-rw-r--r--gettext-tools/src/x-po.h2
-rw-r--r--gettext-tools/src/x-properties.h2
-rw-r--r--gettext-tools/src/x-python.c3
-rw-r--r--gettext-tools/src/x-python.h2
-rw-r--r--gettext-tools/src/x-rst.c3
-rw-r--r--gettext-tools/src/x-rst.h2
-rw-r--r--gettext-tools/src/x-scheme.c2
-rw-r--r--gettext-tools/src/x-scheme.h2
-rw-r--r--gettext-tools/src/x-sh.c2
-rw-r--r--gettext-tools/src/x-sh.h2
-rw-r--r--gettext-tools/src/x-smalltalk.c3
-rw-r--r--gettext-tools/src/x-smalltalk.h2
-rw-r--r--gettext-tools/src/x-stringtable.h2
-rw-r--r--gettext-tools/src/x-tcl.c3
-rw-r--r--gettext-tools/src/x-tcl.h2
-rw-r--r--gettext-tools/src/x-vala.c2
-rw-r--r--gettext-tools/src/x-vala.h3
-rw-r--r--gettext-tools/src/x-ycp.c3
-rw-r--r--gettext-tools/src/x-ycp.h2
-rw-r--r--gettext-tools/src/xgettext.c391
-rw-r--r--gettext-tools/src/xgettext.h3
230 files changed, 10026 insertions, 2191 deletions
diff --git a/gettext-tools/src/ChangeLog b/gettext-tools/src/ChangeLog.1
index fbfa43f..5272c06 100644
--- a/gettext-tools/src/ChangeLog
+++ b/gettext-tools/src/ChangeLog.1
@@ -1,3 +1,353 @@
+2015-10-06 Daiki Ueno <ueno@gnu.org>
+
+ * msgfmt.c (msgfmt_desktop_bulk): Distinguish the number of errors
+ and the exit status.
+ * write-desktop.c (msgdomain_write_desktop_bulk): Don't
+ immediately exit when fwriteerror() returns error.
+
+2015-10-06 Daiki Ueno <ueno@gnu.org>
+
+ msgfmt: Refactor --desktop handling
+ * msgfmt.c (get_languages): Avoid redundant memory allocation.
+ (msgfmt_operand_list_init): New function.
+ (msgfmt_operand_list_destroy): New function.
+ (msgfmt_operand_list_append): New function.
+ (msgfmt_operand_list_add_directory): New function.
+ (msgfmt_desktop_bulk): Rewrite using msgfmt_operand_list_ty.
+
+ * msgfmt.h (msgfmt_operand_ty)
+ (msgfmt_operand_list_ty): New type.
+ * write-desktop.c (msgdomain_write_desktop_bulk):
+ Simplify using msgfmt_operand_list_ty.
+ (msgdomain_write_desktop): Simplify using msgfmt_operand_list_ty.
+ * write-desktop.h (msgdomain_write_desktop_bulk): Take OPERANDS as
+ the first argument, instead of LANGUAGES and MESSAGES.
+
+2015-10-06 Daiki Ueno <ueno@gnu.org>
+
+ * sentence.c (sentence_end): Assign initial values to local
+ variables to suppress compiler warnings with
+ -Wmaybe-uninitialized. This shouldn't address any real bug.
+
+2015-09-11 Daiki Ueno <ueno@gnu.org>
+
+ * gettext 0.19.6 released.
+
+2015-08-24 Daiki Ueno <ueno@gnu.org>
+
+ * xgettext.c (construct_header): Replace PACKAGE placeholder in
+ the header comment.
+
+2015-06-11 Philip Withnall <philip.withnall@collabora.co.uk>
+
+ xgettext: add support for AppData files
+ * x-appdata.h: New file.
+ * x-appdata.c: New file.
+ * xgettext.c: Include x-appdata.h.
+ (language_to_extractor): Add AppData rule.
+ (extension_to_language): Add AppData rule.
+ * Makefile.am (noinst_HEADERS): Add x-appdata.h.
+ (xgettext_SOURCES): Add x-appdata.c.
+ * FILES: Update.
+
+2015-08-21 Daiki Ueno <ueno@gnu.org>
+
+ xgettext: Allow multiple --copyright-holder
+ Feature requested by Francesco Poli in:
+ <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=682580>.
+ * xgettext.c (default_copyright_holder): New constant, renamed
+ from copyright_holder.
+ (copyright_holder): Define as a variable.
+ (main): Allow multiple --copyright-holder options.
+ (construct_header): Support multiple --copyright-holder options.
+
+2015-08-15 Daiki Ueno <ueno@gnu.org>
+
+ * cldr-plurals.c (main): Close FP after use.
+ Reported by Denis Denisov.
+
+2015-07-21 Václav Slavík <vaclav@slavik.io> (tiny change)
+
+ cldr-plurals: Fix --enable-relocatable compilation
+ Compilation of the cldr-plurals tool was broken in the relocatable
+ case because of missing CPPFLAGS/LDFLAGS. Add the same flags used
+ by other tools to the makefile.
+ * Makefile.am (cldr_plurals_CPPFLAGS)
+ (cldr_plurals_LDFLAGS): Adjust for --enable-relocatable
+ compilation.
+
+2015-07-10 Daiki Ueno <ueno@gnu.org>
+
+ * gettext 0.19.5 released.
+
+2015-06-29 Daiki Ueno <ueno@gnu.org>
+
+ * msginit.c (catalogname_for_locale): Remove sr_YU, which were
+ removed from ISO 3166-1:1997. Add comment saying that pap_AN,
+ which were removed from ISO 3166-1:2006, can be removed in the
+ future.
+ Reported by Jakub Wilk in:
+ <https://lists.gnu.org/archive/html/bug-gettext/2015-06/msg00057.html>.
+
+2015-06-25 Daiki Ueno <ueno@gnu.org>
+
+ * x-c.c (literalstring_parse): Bail out if C == NUL. Also adjust
+ the loop invariant in Unicode literal handling.
+ Reported by Hanno Boeck in:
+ <http://savannah.gnu.org/bugs/?45391>.
+
+2015-06-25 Daiki Ueno <ueno@gnu.org>
+
+ * x-c.c (literalstring_parse): Add more NUL checks. Change the
+ loop invariant so that C always points to the character previously
+ pointed by P.
+ Reported by Hanno Boeck in:
+ <http://savannah.gnu.org/bugs/?45391>.
+
+2015-06-24 Daiki Ueno <ueno@gnu.org>
+
+ * x-c.c (literalstring_parse): Check if the next character of a
+ backslash is NUL.
+ Reported by Hanno Boeck in:
+ <http://savannah.gnu.org/bugs/?45391>.
+
+2015-06-23 Daiki Ueno <ueno@gnu.org>
+
+ * cldr-plurals.c (main): Fix unmatched braces when
+ !(DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT).
+
+2015-06-23 Daiki Ueno <ueno@gnu.org>
+
+ * cldr-plurals.c: Include "basename.h".
+ (main): Place optind on the right hand side of the expression, to
+ work around build failure on Solaris.
+
+2015-06-23 Daiki Ueno <ueno@gnu.org>
+
+ * Makefile.am (uninstall-local): Remove cldr-plurals.
+
+2015-06-23 Daiki Ueno <ueno@gnu.org>
+
+ * Makefile.am (noinst_HEADERS): Add cldr-plural.h and
+ cldr-plural-exp.h.
+
+2015-06-22 Daiki Ueno <ueno@gnu.org>
+
+ msginit: Guess plural rules from Unicode CLDR
+ * Makefile.am (noinst_PROGRAMS): Add cldr-plurals.
+ (install-exec-local): Install cldr-plurals.
+ (BUILT_SOURCES): Add cldr-plural.c and cldr-plural.h.
+ (cldr_plural_SOURCES): New variable.
+ (cldr_plural_LDADD): New variable.
+ * cldr-plural-exp.h: New file.
+ * cldr-plural-exp.c: New file.
+ * cldr-plural.y: New file.
+ * cldr-plurals.c: New file.
+ * msginit.c (plural_forms): Call cldr-plurals program if the
+ plural rule is not defined in the code.
+
+2015-06-01 Daiki Ueno <ueno@gnu.org>
+
+ * x-awk.h (EXTENSIONS_AWK): Register file extensions ".gawk" and
+ ".twjr". Suggested by Karl Berry in:
+ <https://lists.gnu.org/archive/html/bug-gettext/2015-05/msg00032.html>.
+
+2015-05-08 Часлав Илић (Chusslove Illich) <caslav.ilic@gmx.net> (tiny change)
+
+ * x-c.c (init_flag_table_kde): New function.
+ (additional_keywords_kde): New variable.
+ (activate_additional_keywords_kde): New function.
+ (init_keywords): Optional addition of KDE-specific keywords.
+ * x-c.h (init_flag_table_kde): New function declaration.
+ (activate_additional_keywords_kde): New function declaration.
+ * xgettext.c (main): Invoke addition of KDE-specific keywords when
+ language is C++ with KDE.
+
+2015-03-20 Daiki Ueno <ueno@gnu.org>
+
+ kde-kuit: Use xmlns to avoid element name conflict
+ * format-kde-kuit.c (XML_NS): New macro.
+ (format_parse): Add namespace qualifier to the <kuit> tag.
+
+2015-03-12 Daiki Ueno <ueno@gnu.org>
+
+ * format-kde-kuit.c (format_parse): Remove dead assignment,
+ spotted by clang-analyzer.
+ * x-c.c (phase5_get): Likewise.
+
+2015-03-11 Daiki Ueno <ueno@gnu.org>
+
+ msgunfmt: Check allocated size for static segment
+ Reported by Max Lin in:
+ http://lists.gnu.org/archive/html/bug-gettext/2015-03/msg00005.html
+ * read-mo.c (get_sysdep_string): Check if the embedded segment
+ size is valid, before adding it to the string length.
+
+2015-03-06 Daiki Ueno <ueno@gnu.org>
+
+ 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-kuit.c: New file.
+ * 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.
+ (FORMAT_SOURCE): Add format-kde-kuit.c.
+
+2015-03-02 Daiki Ueno <ueno@gnu.org>
+
+ xgettext: Support message syntax checks
+ With this change, xgettext could report common syntactic problems
+ in extracted strings. The current built-in checks are
+ ellipsis-unicode, space-ellipsis, and quote-unicode. Those checks
+ can be enabled with --check option of xgettext and disabled with
+ special "xgettext:" comment in source files.
+ Feature suggested by Philip Withnall in:
+ https://savannah.gnu.org/bugs/?44098
+ * message.h (enum syntax_check_type): New enum.
+ (NSYNTAXCHECKS): New constant.
+ (enum is_syntax_check): New enum.
+ (struct message_ty): New field 'do_syntax_check'.
+ (syntax_check_name): New variable declaration.
+ * message.c (syntax_check_name): New variable.
+ * msgl-cat.c (catenate_msgdomain_list): Propagate
+ mp->do_syntax_check.
+ * msgmerge.c (message_merge): Propagate ref->do_syntax_check.
+ * msgl-check.h (syntax_check_message_list): New declaration.
+ * msgl-check.c (syntax_check_ellipsis_unicode): New function.
+ (syntax_check_space_ellipsis): New function.
+ (syntax_check_quote_unicode): New function.
+ (syntax_check_message): New function.
+ (syntax_check_message_list): New function.
+ * read-catalog-abstract.h (po_parse_comment_special): Adjust
+ function declaration.
+ * read-catalog-abstract.c (po_parse_comment_special): Add new
+ argument SCP for syntax checking; all callers changed.
+ * read-catalog.h (DEFAULT_CATALOG_READER_TY): New field
+ 'do_syntax_check'.
+ * read-catalog.c (default_constructor): Initialize
+ this->do_syntax_check.
+ (default_copy_comment_state): Propagate this->do_syntax_check.
+ * sentence.h: New file.
+ * sentence.c: New file.
+ * xgettext.c (long_options): Add options --check and --sentence-end.
+ (main): Handle options --check and --sentence-end.
+ (usage): Document options --check and --sentence-end.
+ (remember_a_message): Propagate do_syntax_check value.
+
+2015-02-05 Alex Henrie <alexhenrie24@gmail.com> (tiny change)
+
+ xgettext: Wrap location comments to 79 characters
+ Previously, messages were wrapped to 79 characters, but location
+ comments were wrapped to 78 characters.
+ * write-po.c (message_print_comment_filepos): Fix off-by-one in
+ calculating line-wrapping width of location comment.
+
+2015-02-03 Daiki Ueno <ueno@gnu.org>
+
+ msgfilter: Factor out quoted string handling
+ For later use in xgettext, separate out the scanner part in
+ filter-quote.c into a separate file. See:
+ <https://savannah.gnu.org/bugs/?44098>.
+ * quote.h: New file split from filter-quote.c.
+ * filter-quote.c: Include "quote.h".
+ (convert_quote_callback): New function.
+ (convert_ascii_quote_to_unicode): Use scan_quoted from quote.h.
+ * Makefile.am (libgettextsrc_la_SOURCES): Add quote.h.
+
+2015-01-29 Daiki Ueno <ueno@gnu.org>
+
+ msgexec: Add --newline option
+ See the commit 96dde0b for the rationale.
+ * msgexec.c (newline): New variable.
+ (long_options): Add --newline option.
+ (main): Handle --newline option.
+ (usage): Document --newline option.
+ (process_string): Handle --newline option.
+
+2015-01-28 Daiki Ueno <ueno@gnu.org>
+
+ msgfilter: Add --newline option
+ The filter program was supposed to handle translation without a
+ newline character at the end of line. This was causing
+ portability problems with standard text processing programs on
+ some platforms (BSD sed, for instance) and not friendly towards
+ POSIX, where a "text file" is required to have an ending newline.
+ The new --newline option controls the behavior. If it is given,
+ both filter input and output are assumed to end with a newline
+ character.
+ * msgfilter.c (newline): New variable.
+ (long_options): Add --newline option.
+ (main): Handle --newline option.
+ (usage): Document --newline option.
+ (process_string_with_newline): New function which wraps
+ process_string.
+ (process_message): Use process_string_with_newline instead of
+ process_string if --newline is specified.
+
+2015-01-24 Daiki Ueno <ueno@gnu.org>
+
+ xgettext, msgmerge: Avoid undefined non-null argument behavior
+ * xgettext.c (remember_a_message): Building with gcc's
+ -fsanitize=undefined and running tests triggered:
+ xgettext.c:2425:17: runtime error: null pointer passed as argument \
+ 2, which is declared to never be null
+ Adjust the argument of strncmp to never be null.
+ * msgmerge.c (message_merge): Likewise for memcpy.
+
+2015-01-23 Daiki Ueno <ueno@gnu.org>
+
+ build: Fix parallel build from git checkout
+ Since po-gram-gen2.h depends on po-gram-gen.h, an explicit
+ dependency on the YACC rule is needed for parallel compilation.
+ * Makefile.am (po-gram-gen.h): Depend on po-gram-gen.c.
+
+2015-01-16 Daiki Ueno <ueno@gnu.org>
+
+ desktop: Avoid useless warning for group header
+ Reported by Marek Černocký at:
+ <https://savannah.gnu.org/bugs/?44005>
+ * read-desktop.c (desktop_lex): Fix "invalid non-blank
+ character" check after reading a group header.
+
+2015-01-13 Daiki Ueno <ueno@gnu.org>
+
+ * x-c.c (phase5_get): Reset raw_expected at the beginning of the
+ function.
+
+2015-01-13 Daiki Ueno <ueno@gnu.org>
+
+ c++: Make C++11 raw string recognition stricter
+ Reported by Vaclav Slavik at:
+ <http://savannah.gnu.org/bugs/?43970>.
+ * x-c.c (struct token_ty): New field 'escape'.
+ (struct xgettext_token_ty): New field 'escape'.
+ (phase5_get): Recognize raw strings more strictly. Set 'escape'
+ field of token appropriately for string literals.
+ (extract_parenthesized): Respect 'escape' field of token.
+
+2015-01-13 Daiki Ueno <ueno@gnu.org>
+
+ c++: Differentiate scanning logic from C
+ To enable raw string literals only in C++, add a flag indicating
+ the current source language is C++.
+ Suggested by Vaclav Slavik at:
+ <https://savannah.gnu.org/bugs/?43970>.
+ * x-c.h (extract_cxx): New declaration.
+ (SCANNERS_C): Use extract_cxx for "C++".
+ * x-c.c (cxx_extensions): New variable.
+ (phase5_get): Respect cxx_extensions and recognize raw string
+ literals only when it is set.
+ (extract_cxx): New function.
+ (extract_c, extract_objc): Reset cxx_extensions.
+
2014-12-24 Daiki Ueno <ueno@gnu.org>
* gettext 0.19.4 released.
diff --git a/gettext-tools/src/FILES b/gettext-tools/src/FILES
index 5fb474f..b647a84 100644
--- a/gettext-tools/src/FILES
+++ b/gettext-tools/src/FILES
@@ -357,6 +357,9 @@ msgl-check.c
| x-desktop.h
| x-desktop.c
| String extractor from Desktop Entry file.
+| x-appdata.h
+| x-appdata.c
+| String extractor for AppData files.
| xgettext.c
| Main source for the 'xgettext' program.
|
diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am
index 9f2325f..7109072 100644
--- a/gettext-tools/src/Makefile.am
+++ b/gettext-tools/src/Makefile.am
@@ -1,5 +1,6 @@
## Makefile for the gettext-tools/src subdirectory of GNU gettext
-## Copyright (C) 1995-1998, 2000-2011 Free Software Foundation, Inc.
+## Copyright (C) 1995-1998, 2000-2011, 2015 Free Software Foundation,
+## Inc.
##
## 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
@@ -29,7 +30,7 @@ msgcmp msgfmt msgmerge msgunfmt xgettext \
msgattrib msgcat msgcomm msgconv msgen msgexec msgfilter msggrep msginit msguniq \
recode-sr-latin
-noinst_PROGRAMS = hostname urlget
+noinst_PROGRAMS = hostname urlget cldr-plurals
lib_LTLIBRARIES = libgettextsrc.la
@@ -38,7 +39,8 @@ po-lex.h open-catalog.h read-catalog-abstract.h read-catalog.h \
read-po.h read-properties.h read-stringtable.h \
str-list.h \
color.h write-catalog.h write-po.h write-properties.h write-stringtable.h \
-dir-list.h file-list.h po-gram-gen.h po-gram-gen2.h \
+dir-list.h file-list.h po-gram-gen.h po-gram-gen2.h cldr-plural.h \
+cldr-plural-exp.h locating-rule.h its.h \
msgl-charset.h msgl-equal.h msgl-iconv.h msgl-ascii.h msgl-cat.h msgl-header.h \
msgl-english.h msgl-check.h msgl-fsearch.h msgfmt.h msgunfmt.h \
plural-count.h plural-eval.h plural-distrib.h \
@@ -49,13 +51,14 @@ read-resources.h write-resources.h \
read-tcl.h write-tcl.h \
write-qt.h \
read-desktop.h write-desktop.h \
+write-xml.h \
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 libexpat-compat.h
+x-javascript.h x-vala.h x-gsettings.h x-desktop.h x-appdata.h
-EXTRA_DIST += FILES project-id ChangeLog.0
+EXTRA_DIST += FILES project-id
aliaspath = $(localedir)
jardir = $(datadir)/gettext
@@ -138,6 +141,7 @@ FORMAT_SOURCE += \
format-qt.c \
format-qt-plural.c \
format-kde.c \
+ format-kde-kuit.c \
format-boost.c \
format-lua.c \
format-javascript.c
@@ -148,9 +152,9 @@ $(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 \
+plural-table.c quote.h sentence.h sentence.c \
$(FORMAT_SOURCE) \
-read-desktop.c
+read-desktop.c locating-rule.c its.c
# msggrep needs pattern matching.
LIBGREP = ../libgrep/libgrep.a
@@ -161,7 +165,8 @@ msgcmp_SOURCES += msgl-fsearch.c
msgfmt_SOURCES = msgfmt.c
msgfmt_SOURCES += \
write-mo.c write-java.c write-csharp.c write-resources.c write-tcl.c \
- write-qt.c write-desktop.c ../../gettext-runtime/intl/hash-string.c
+ write-qt.c write-desktop.c write-xml.c \
+ ../../gettext-runtime/intl/hash-string.c
if !WOE32DLL
msgmerge_SOURCES = msgmerge.c
else
@@ -179,8 +184,7 @@ endif
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-rst.c x-lua.c x-javascript.c x-vala.c \
x-desktop.c
if !WOE32DLL
msgattrib_SOURCES = msgattrib.c
@@ -236,6 +240,9 @@ endif
recode_sr_latin_SOURCES = recode-sr-latin.c filter-sr-latin.c
hostname_SOURCES = hostname.c
urlget_SOURCES = urlget.c
+cldr_plurals_SOURCES = cldr-plural.y cldr-plural-exp.c cldr-plurals.c
+cldr_plurals_CFLAGS = $(AM_CFLAGS) $(INCXML)
+cldr_plurals_LDADD = libgettextsrc.la $(LDADD)
# How to build libgettextsrc.la.
# Need ../gnulib-lib/libgettextlib.la.
@@ -249,7 +256,7 @@ libgettextsrc_la_LDFLAGS = \
-release @VERSION@ \
../gnulib-lib/libgettextlib.la $(LTLIBUNISTRING) @LTLIBINTL@ @LTLIBICONV@ -lc -no-undefined
-libgettextsrc_la_CPPFLAGS = $(AM_CPPFLAGS)
+libgettextsrc_la_CPPFLAGS = $(AM_CPPFLAGS) $(INCXML)
# Tell the mingw or Cygwin linker which symbols to export.
if WOE32DLL
@@ -278,7 +285,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)
@@ -329,6 +336,7 @@ msguniq_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(bindir)\"
recode_sr_latin_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(bindir)\"
hostname_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
urlget_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
+cldr_plurals_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
if RELOCATABLE_VIA_LD
msgcmp_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
msgfmt_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
@@ -348,6 +356,7 @@ msguniq_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
recode_sr_latin_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
hostname_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(pkglibdir)`
urlget_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(pkglibdir)`
+cldr_plurals_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(pkglibdir)`
endif
# Linking with C++ libraries is needed _only_ on mingw and Cygwin.
@@ -446,7 +455,7 @@ endif
# Special rules for bison and flex generated files.
BUILT_SOURCES = \
- po-gram-gen.c po-gram-gen.h po-gram-gen2.h
+ po-gram-gen.c po-gram-gen.h po-gram-gen2.h cldr-plural.c cldr-plural.h
po-lex.o po-lex.lo: po-gram-gen2.h
po-gram-gen2.h: po-gram-gen.h
@@ -455,6 +464,7 @@ po-gram-gen2.h: po-gram-gen.h
$(SED) -e 's/yy/po_gram_/g' -e 's/extern /extern DLL_VARIABLE /' \
$${srcdir}po-gram-gen.h > $@-tmp && \
mv $@-tmp $@
+po-gram-gen.h: po-gram-gen.c
# Special rules for installation of auxiliary programs.
@@ -463,6 +473,7 @@ install-exec-local:
$(MKDIR_P) $(DESTDIR)$(pkglibdir)
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) hostname$(EXEEXT) $(DESTDIR)$(pkglibdir)/hostname$(EXEEXT)
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) urlget$(EXEEXT) $(DESTDIR)$(pkglibdir)/urlget$(EXEEXT)
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) cldr-plurals$(EXEEXT) $(DESTDIR)$(pkglibdir)/cldr-plurals$(EXEEXT)
$(INSTALL_SCRIPT) user-email $(DESTDIR)$(pkglibdir)/user-email
$(INSTALL_SCRIPT) $(srcdir)/project-id $(DESTDIR)$(pkglibdir)/project-id
@@ -472,6 +483,7 @@ installdirs-local:
uninstall-local:
$(RM) $(DESTDIR)$(pkglibdir)/hostname$(EXEEXT)
$(RM) $(DESTDIR)$(pkglibdir)/urlget$(EXEEXT)
+ $(RM) $(DESTDIR)$(pkglibdir)/cldr-plurals$(EXEEXT)
$(RM) $(DESTDIR)$(pkglibdir)/user-email
$(RM) $(DESTDIR)$(pkglibdir)/project-id
diff --git a/gettext-tools/src/Makefile.in b/gettext-tools/src/Makefile.in
index 4e29138..00da903 100644
--- a/gettext-tools/src/Makefile.in
+++ b/gettext-tools/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -17,7 +17,17 @@
VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@@ -83,7 +93,8 @@ bin_PROGRAMS = msgcmp$(EXEEXT) msgfmt$(EXEEXT) msgmerge$(EXEEXT) \
msgen$(EXEEXT) msgexec$(EXEEXT) msgfilter$(EXEEXT) \
msggrep$(EXEEXT) msginit$(EXEEXT) msguniq$(EXEEXT) \
recode-sr-latin$(EXEEXT)
-noinst_PROGRAMS = hostname$(EXEEXT) urlget$(EXEEXT)
+noinst_PROGRAMS = hostname$(EXEEXT) urlget$(EXEEXT) \
+ cldr-plurals$(EXEEXT)
# Tell the mingw or Cygwin linker which symbols to export.
@WOE32DLL_TRUE@am__append_1 = ../woe32dll/gettextsrc-exports.c
@@ -91,15 +102,10 @@ noinst_PROGRAMS = hostname$(EXEEXT) urlget$(EXEEXT)
@WOE32DLL_TRUE@am__append_3 = $(GETTEXTLIB_EXPORTS_FLAGS)
@WOE32_TRUE@am__append_4 = gettext.res
subdir = src
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(top_srcdir)/../build-aux/mkinstalldirs \
- $(srcdir)/user-email.sh.in po-gram-gen.c \
- $(top_srcdir)/../build-aux/ylwrap $(noinst_HEADERS) ChangeLog
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = \
$(top_srcdir)/libgettextpo/gnulib-m4/gnulib-comp.m4 \
$(top_srcdir)/libgrep/gnulib-m4/gnulib-comp.m4 \
- $(top_srcdir)/libgrep/gnulib-m4/langinfo_h.m4 \
$(top_srcdir)/libgrep/gnulib-m4/localeconv.m4 \
$(top_srcdir)/libgrep/gnulib-m4/mbrlen.m4 \
$(top_srcdir)/libgrep/gnulib-m4/nl_langinfo.m4 \
@@ -116,6 +122,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/btowc.m4 \
$(top_srcdir)/gnulib-m4/byteswap.m4 \
$(top_srcdir)/gnulib-m4/canonicalize.m4 \
+ $(top_srcdir)/gnulib-m4/check-math-lib.m4 \
$(top_srcdir)/gnulib-m4/close.m4 \
$(top_srcdir)/gnulib-m4/closedir.m4 \
$(top_srcdir)/gnulib-m4/configmake.m4 \
@@ -123,6 +130,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/csharp.m4 \
$(top_srcdir)/gnulib-m4/csharpcomp.m4 \
$(top_srcdir)/gnulib-m4/csharpexec.m4 \
+ $(top_srcdir)/gnulib-m4/ctype.m4 \
$(top_srcdir)/gnulib-m4/curses.m4 \
$(top_srcdir)/gnulib-m4/dirent_h.m4 \
$(top_srcdir)/gnulib-m4/double-slash-root.m4 \
@@ -134,7 +142,10 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/error.m4 \
$(top_srcdir)/gnulib-m4/execute.m4 \
$(top_srcdir)/gnulib-m4/exponentd.m4 \
+ $(top_srcdir)/gnulib-m4/exponentf.m4 \
+ $(top_srcdir)/gnulib-m4/exponentl.m4 \
$(top_srcdir)/gnulib-m4/extensions.m4 \
+ $(top_srcdir)/gnulib-m4/fabs.m4 \
$(top_srcdir)/gnulib-m4/fatal-signal.m4 \
$(top_srcdir)/gnulib-m4/fcntl.m4 \
$(top_srcdir)/gnulib-m4/fcntl_h.m4 \
@@ -164,10 +175,16 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/inline.m4 \
$(top_srcdir)/gnulib-m4/intmax_t.m4 \
$(top_srcdir)/gnulib-m4/inttypes.m4 \
+ $(top_srcdir)/gnulib-m4/isinf.m4 \
+ $(top_srcdir)/gnulib-m4/isnan.m4 \
+ $(top_srcdir)/gnulib-m4/isnand.m4 \
+ $(top_srcdir)/gnulib-m4/isnanf.m4 \
+ $(top_srcdir)/gnulib-m4/isnanl.m4 \
$(top_srcdir)/gnulib-m4/iswblank.m4 \
$(top_srcdir)/gnulib-m4/java.m4 \
$(top_srcdir)/gnulib-m4/javacomp.m4 \
$(top_srcdir)/gnulib-m4/javaexec.m4 \
+ $(top_srcdir)/gnulib-m4/langinfo_h.m4 \
$(top_srcdir)/gnulib-m4/largefile.m4 \
$(top_srcdir)/gnulib-m4/lib-ld.m4 \
$(top_srcdir)/gnulib-m4/lib-link.m4 \
@@ -185,10 +202,13 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/locale-zh.m4 \
$(top_srcdir)/gnulib-m4/locale_h.m4 \
$(top_srcdir)/gnulib-m4/localename.m4 \
+ $(top_srcdir)/gnulib-m4/log10.m4 \
$(top_srcdir)/gnulib-m4/lseek.m4 \
$(top_srcdir)/gnulib-m4/lstat.m4 \
$(top_srcdir)/gnulib-m4/malloc.m4 \
$(top_srcdir)/gnulib-m4/malloca.m4 \
+ $(top_srcdir)/gnulib-m4/math_h.m4 \
+ $(top_srcdir)/gnulib-m4/mathfunc.m4 \
$(top_srcdir)/gnulib-m4/mbchar.m4 \
$(top_srcdir)/gnulib-m4/mbiter.m4 \
$(top_srcdir)/gnulib-m4/mbrtowc.m4 \
@@ -218,6 +238,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/pathmax.m4 \
$(top_srcdir)/gnulib-m4/pipe2.m4 \
$(top_srcdir)/gnulib-m4/posix_spawn.m4 \
+ $(top_srcdir)/gnulib-m4/pow.m4 \
$(top_srcdir)/gnulib-m4/printf.m4 \
$(top_srcdir)/gnulib-m4/putenv.m4 \
$(top_srcdir)/gnulib-m4/quote.m4 \
@@ -242,6 +263,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/sigaction.m4 \
$(top_srcdir)/gnulib-m4/signal_h.m4 \
$(top_srcdir)/gnulib-m4/signalblocking.m4 \
+ $(top_srcdir)/gnulib-m4/signbit.m4 \
$(top_srcdir)/gnulib-m4/sigpipe.m4 \
$(top_srcdir)/gnulib-m4/sleep.m4 \
$(top_srcdir)/gnulib-m4/snprintf.m4 \
@@ -249,6 +271,7 @@ am__aclocal_m4_deps = \
$(top_srcdir)/gnulib-m4/spawn_h.m4 \
$(top_srcdir)/gnulib-m4/ssize_t.m4 \
$(top_srcdir)/gnulib-m4/stat.m4 \
+ $(top_srcdir)/gnulib-m4/stdalign.m4 \
$(top_srcdir)/gnulib-m4/stdarg.m4 \
$(top_srcdir)/gnulib-m4/stdbool.m4 \
$(top_srcdir)/gnulib-m4/stddef_h.m4 \
@@ -340,6 +363,8 @@ am__aclocal_m4_deps = \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+ $(am__DIST_COMMON)
mkinstalldirs = $(SHELL) $(top_srcdir)/../build-aux/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = user-email
@@ -381,15 +406,17 @@ am__libgettextsrc_la_SOURCES_DIST = message.c po-error.c po-xerror.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 format.c \
- format-invalid.h format-c.c format-c-parse.h format-sh.c \
- format-python.c format-python-brace.c format-lisp.c \
- format-elisp.c format-librep.c format-scheme.c format-java.c \
- format-csharp.c format-awk.c format-pascal.c format-ycp.c \
- format-tcl.c format-perl.c format-perl-brace.c format-php.c \
+ po-time.c plural-exp.c plural-eval.c plural-table.c quote.h \
+ sentence.h sentence.c format.c format-invalid.h format-c.c \
+ format-c-parse.h format-sh.c format-python.c \
+ format-python-brace.c format-lisp.c format-elisp.c \
+ format-librep.c format-scheme.c format-java.c format-csharp.c \
+ format-awk.c format-pascal.c format-ycp.c format-tcl.c \
+ format-perl.c format-perl-brace.c format-php.c \
format-gcc-internal.c format-gfc-internal.c format-qt.c \
- format-qt-plural.c format-kde.c format-boost.c format-lua.c \
- format-javascript.c ../woe32dll/c++format.cc read-desktop.c \
+ format-qt-plural.c format-kde.c format-kde-kuit.c \
+ format-boost.c format-lua.c format-javascript.c \
+ ../woe32dll/c++format.cc read-desktop.c locating-rule.c its.c \
../woe32dll/gettextsrc-exports.c
am__objects_1 = libgettextsrc_la-message.lo \
libgettextsrc_la-po-error.lo libgettextsrc_la-po-xerror.lo \
@@ -424,6 +451,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@WOE32DLL_FALSE@ libgettextsrc_la-format-qt.lo \
@WOE32DLL_FALSE@ libgettextsrc_la-format-qt-plural.lo \
@WOE32DLL_FALSE@ libgettextsrc_la-format-kde.lo \
+@WOE32DLL_FALSE@ libgettextsrc_la-format-kde-kuit.lo \
@WOE32DLL_FALSE@ libgettextsrc_la-format-boost.lo \
@WOE32DLL_FALSE@ libgettextsrc_la-format-lua.lo \
@WOE32DLL_FALSE@ libgettextsrc_la-format-javascript.lo
@@ -451,6 +479,7 @@ am__dirstamp = $(am__leading_dot)dirstamp
@WOE32DLL_TRUE@ libgettextsrc_la-format-qt.lo \
@WOE32DLL_TRUE@ libgettextsrc_la-format-qt-plural.lo \
@WOE32DLL_TRUE@ libgettextsrc_la-format-kde.lo \
+@WOE32DLL_TRUE@ libgettextsrc_la-format-kde-kuit.lo \
@WOE32DLL_TRUE@ libgettextsrc_la-format-boost.lo \
@WOE32DLL_TRUE@ libgettextsrc_la-format-lua.lo \
@WOE32DLL_TRUE@ libgettextsrc_la-format-javascript.lo
@@ -467,19 +496,31 @@ am_libgettextsrc_la_OBJECTS = $(am__objects_1) \
libgettextsrc_la-msgl-check.lo libgettextsrc_la-file-list.lo \
libgettextsrc_la-msgl-charset.lo libgettextsrc_la-po-time.lo \
libgettextsrc_la-plural-exp.lo libgettextsrc_la-plural-eval.lo \
- libgettextsrc_la-plural-table.lo $(am__objects_2) \
- libgettextsrc_la-read-desktop.lo $(am__objects_3)
+ libgettextsrc_la-plural-table.lo libgettextsrc_la-sentence.lo \
+ $(am__objects_2) libgettextsrc_la-read-desktop.lo \
+ libgettextsrc_la-locating-rule.lo libgettextsrc_la-its.lo \
+ $(am__objects_3)
libgettextsrc_la_OBJECTS = $(am_libgettextsrc_la_OBJECTS)
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
-am_hostname_OBJECTS = hostname-hostname.$(OBJEXT)
-hostname_OBJECTS = $(am_hostname_OBJECTS)
-hostname_LDADD = $(LDADD)
+am_cldr_plurals_OBJECTS = cldr_plurals-cldr-plural.$(OBJEXT) \
+ cldr_plurals-cldr-plural-exp.$(OBJEXT) \
+ cldr_plurals-cldr-plurals.$(OBJEXT)
+cldr_plurals_OBJECTS = $(am_cldr_plurals_OBJECTS)
am__DEPENDENCIES_1 =
@WOE32_TRUE@am__DEPENDENCIES_2 = gettext.res
+am__DEPENDENCIES_3 = ../gnulib-lib/libgettextlib.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+cldr_plurals_DEPENDENCIES = libgettextsrc.la $(am__DEPENDENCIES_3)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
+cldr_plurals_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(cldr_plurals_CFLAGS) \
+ $(CFLAGS) $(cldr_plurals_LDFLAGS) $(LDFLAGS) -o $@
+am_hostname_OBJECTS = hostname-hostname.$(OBJEXT)
+hostname_OBJECTS = $(am_hostname_OBJECTS)
+hostname_LDADD = $(LDADD)
hostname_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(hostname_LDFLAGS) $(LDFLAGS) -o $@
@@ -533,6 +574,7 @@ am_msgfmt_OBJECTS = msgfmt-msgfmt.$(OBJEXT) msgfmt-write-mo.$(OBJEXT) \
msgfmt-write-java.$(OBJEXT) msgfmt-write-csharp.$(OBJEXT) \
msgfmt-write-resources.$(OBJEXT) msgfmt-write-tcl.$(OBJEXT) \
msgfmt-write-qt.$(OBJEXT) msgfmt-write-desktop.$(OBJEXT) \
+ msgfmt-write-xml.$(OBJEXT) \
../../gettext-runtime/intl/msgfmt-hash-string.$(OBJEXT)
msgfmt_OBJECTS = $(am_msgfmt_OBJECTS)
msgfmt_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -594,8 +636,7 @@ urlget_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
am__xgettext_SOURCES_DIST = xgettext.c 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 \
+ x-rst.c x-lua.c x-javascript.c x-vala.c x-desktop.c \
../woe32dll/c++xgettext.cc
@WOE32DLL_FALSE@am_xgettext_OBJECTS = xgettext-xgettext.$(OBJEXT) \
@WOE32DLL_FALSE@ xgettext-x-c.$(OBJEXT) xgettext-x-po.$(OBJEXT) \
@@ -614,12 +655,9 @@ am__xgettext_SOURCES_DIST = xgettext.c x-c.c x-po.c x-sh.c x-python.c \
@WOE32DLL_FALSE@ xgettext-x-perl.$(OBJEXT) \
@WOE32DLL_FALSE@ xgettext-x-php.$(OBJEXT) \
@WOE32DLL_FALSE@ xgettext-x-rst.$(OBJEXT) \
-@WOE32DLL_FALSE@ xgettext-x-glade.$(OBJEXT) \
@WOE32DLL_FALSE@ xgettext-x-lua.$(OBJEXT) \
@WOE32DLL_FALSE@ xgettext-x-javascript.$(OBJEXT) \
@WOE32DLL_FALSE@ xgettext-x-vala.$(OBJEXT) \
-@WOE32DLL_FALSE@ xgettext-x-gsettings.$(OBJEXT) \
-@WOE32DLL_FALSE@ xgettext-libexpat-compat.$(OBJEXT) \
@WOE32DLL_FALSE@ xgettext-x-desktop.$(OBJEXT)
@WOE32DLL_TRUE@am_xgettext_OBJECTS = \
@WOE32DLL_TRUE@ ../woe32dll/xgettext-c++xgettext.$(OBJEXT) \
@@ -639,12 +677,9 @@ am__xgettext_SOURCES_DIST = xgettext.c x-c.c x-po.c x-sh.c x-python.c \
@WOE32DLL_TRUE@ xgettext-x-perl.$(OBJEXT) \
@WOE32DLL_TRUE@ xgettext-x-php.$(OBJEXT) \
@WOE32DLL_TRUE@ xgettext-x-rst.$(OBJEXT) \
-@WOE32DLL_TRUE@ xgettext-x-glade.$(OBJEXT) \
@WOE32DLL_TRUE@ xgettext-x-lua.$(OBJEXT) \
@WOE32DLL_TRUE@ xgettext-x-javascript.$(OBJEXT) \
@WOE32DLL_TRUE@ xgettext-x-vala.$(OBJEXT) \
-@WOE32DLL_TRUE@ xgettext-x-gsettings.$(OBJEXT) \
-@WOE32DLL_TRUE@ xgettext-libexpat-compat.$(OBJEXT) \
@WOE32DLL_TRUE@ xgettext-x-desktop.$(OBJEXT)
xgettext_OBJECTS = $(am_xgettext_OBJECTS)
AM_V_P = $(am__v_P_@AM_V@)
@@ -708,24 +743,25 @@ am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
am__v_YACC_0 = @echo " YACC " $@;
am__v_YACC_1 =
YLWRAP = $(top_srcdir)/../build-aux/ylwrap
-SOURCES = $(libgettextsrc_la_SOURCES) $(hostname_SOURCES) \
- $(msgattrib_SOURCES) $(msgcat_SOURCES) $(msgcmp_SOURCES) \
- $(msgcomm_SOURCES) $(msgconv_SOURCES) $(msgen_SOURCES) \
- $(msgexec_SOURCES) $(msgfilter_SOURCES) $(msgfmt_SOURCES) \
- $(msggrep_SOURCES) $(msginit_SOURCES) $(msgmerge_SOURCES) \
- $(msgunfmt_SOURCES) $(msguniq_SOURCES) \
+SOURCES = $(libgettextsrc_la_SOURCES) $(cldr_plurals_SOURCES) \
+ $(hostname_SOURCES) $(msgattrib_SOURCES) $(msgcat_SOURCES) \
+ $(msgcmp_SOURCES) $(msgcomm_SOURCES) $(msgconv_SOURCES) \
+ $(msgen_SOURCES) $(msgexec_SOURCES) $(msgfilter_SOURCES) \
+ $(msgfmt_SOURCES) $(msggrep_SOURCES) $(msginit_SOURCES) \
+ $(msgmerge_SOURCES) $(msgunfmt_SOURCES) $(msguniq_SOURCES) \
$(recode_sr_latin_SOURCES) $(urlget_SOURCES) \
$(xgettext_SOURCES)
DIST_SOURCES = $(am__libgettextsrc_la_SOURCES_DIST) \
- $(hostname_SOURCES) $(am__msgattrib_SOURCES_DIST) \
- $(am__msgcat_SOURCES_DIST) $(msgcmp_SOURCES) \
- $(am__msgcomm_SOURCES_DIST) $(am__msgconv_SOURCES_DIST) \
- $(am__msgen_SOURCES_DIST) $(msgexec_SOURCES) \
- $(am__msgfilter_SOURCES_DIST) $(msgfmt_SOURCES) \
- $(am__msggrep_SOURCES_DIST) $(msginit_SOURCES) \
- $(am__msgmerge_SOURCES_DIST) $(msgunfmt_SOURCES) \
- $(am__msguniq_SOURCES_DIST) $(recode_sr_latin_SOURCES) \
- $(urlget_SOURCES) $(am__xgettext_SOURCES_DIST)
+ $(cldr_plurals_SOURCES) $(hostname_SOURCES) \
+ $(am__msgattrib_SOURCES_DIST) $(am__msgcat_SOURCES_DIST) \
+ $(msgcmp_SOURCES) $(am__msgcomm_SOURCES_DIST) \
+ $(am__msgconv_SOURCES_DIST) $(am__msgen_SOURCES_DIST) \
+ $(msgexec_SOURCES) $(am__msgfilter_SOURCES_DIST) \
+ $(msgfmt_SOURCES) $(am__msggrep_SOURCES_DIST) \
+ $(msginit_SOURCES) $(am__msgmerge_SOURCES_DIST) \
+ $(msgunfmt_SOURCES) $(am__msguniq_SOURCES_DIST) \
+ $(recode_sr_latin_SOURCES) $(urlget_SOURCES) \
+ $(am__xgettext_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -751,6 +787,9 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/user-email.sh.in \
+ $(top_srcdir)/../build-aux/mkinstalldirs \
+ $(top_srcdir)/../build-aux/ylwrap cldr-plural.c po-gram-gen.c
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
pkgdatadir = $(datadir)/gettext
pkglibdir = $(libdir)/gettext
@@ -763,6 +802,7 @@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
AR = @AR@
ARCHIVE_FORMAT = @ARCHIVE_FORMAT@
+ARCHIVE_VERSION = @ARCHIVE_VERSION@
ARFLAGS = @ARFLAGS@
AS = @AS@
ASM_SYMBOL_PREFIX = @ASM_SYMBOL_PREFIX@
@@ -834,6 +874,7 @@ EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@
EOVERFLOW_VALUE = @EOVERFLOW_VALUE@
ERRNO_H = @ERRNO_H@
EXEEXT = @EXEEXT@
+FABS_LIBM = @FABS_LIBM@
FGREP = @FGREP@
FLOAT_H = @FLOAT_H@
FNMATCH_H = @FNMATCH_H@
@@ -848,15 +889,34 @@ GLIBC21 = @GLIBC21@
GLOBAL_SYMBOL_PIPE = @GLOBAL_SYMBOL_PIPE@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
+GNULIB_ACOSF = @GNULIB_ACOSF@
+GNULIB_ACOSL = @GNULIB_ACOSL@
GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
+GNULIB_ASINF = @GNULIB_ASINF@
+GNULIB_ASINL = @GNULIB_ASINL@
+GNULIB_ATAN2F = @GNULIB_ATAN2F@
+GNULIB_ATANF = @GNULIB_ATANF@
+GNULIB_ATANL = @GNULIB_ATANL@
GNULIB_ATOLL = @GNULIB_ATOLL@
GNULIB_BTOWC = @GNULIB_BTOWC@
GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
GNULIB_CANONICALIZE_FILE_NAME = @GNULIB_CANONICALIZE_FILE_NAME@
+GNULIB_CBRT = @GNULIB_CBRT@
+GNULIB_CBRTF = @GNULIB_CBRTF@
+GNULIB_CBRTL = @GNULIB_CBRTL@
+GNULIB_CEIL = @GNULIB_CEIL@
+GNULIB_CEILF = @GNULIB_CEILF@
+GNULIB_CEILL = @GNULIB_CEILL@
GNULIB_CHDIR = @GNULIB_CHDIR@
GNULIB_CHOWN = @GNULIB_CHOWN@
GNULIB_CLOSE = @GNULIB_CLOSE@
GNULIB_CLOSEDIR = @GNULIB_CLOSEDIR@
+GNULIB_COPYSIGN = @GNULIB_COPYSIGN@
+GNULIB_COPYSIGNF = @GNULIB_COPYSIGNF@
+GNULIB_COPYSIGNL = @GNULIB_COPYSIGNL@
+GNULIB_COSF = @GNULIB_COSF@
+GNULIB_COSHF = @GNULIB_COSHF@
+GNULIB_COSL = @GNULIB_COSL@
GNULIB_DIRFD = @GNULIB_DIRFD@
GNULIB_DPRINTF = @GNULIB_DPRINTF@
GNULIB_DUP = @GNULIB_DUP@
@@ -865,6 +925,16 @@ GNULIB_DUP3 = @GNULIB_DUP3@
GNULIB_DUPLOCALE = @GNULIB_DUPLOCALE@
GNULIB_ENVIRON = @GNULIB_ENVIRON@
GNULIB_EUIDACCESS = @GNULIB_EUIDACCESS@
+GNULIB_EXP2 = @GNULIB_EXP2@
+GNULIB_EXP2F = @GNULIB_EXP2F@
+GNULIB_EXP2L = @GNULIB_EXP2L@
+GNULIB_EXPF = @GNULIB_EXPF@
+GNULIB_EXPL = @GNULIB_EXPL@
+GNULIB_EXPM1 = @GNULIB_EXPM1@
+GNULIB_EXPM1F = @GNULIB_EXPM1F@
+GNULIB_EXPM1L = @GNULIB_EXPM1L@
+GNULIB_FABSF = @GNULIB_FABSF@
+GNULIB_FABSL = @GNULIB_FABSL@
GNULIB_FACCESSAT = @GNULIB_FACCESSAT@
GNULIB_FCHDIR = @GNULIB_FCHDIR@
GNULIB_FCHMODAT = @GNULIB_FCHMODAT@
@@ -879,6 +949,15 @@ GNULIB_FFSL = @GNULIB_FFSL@
GNULIB_FFSLL = @GNULIB_FFSLL@
GNULIB_FGETC = @GNULIB_FGETC@
GNULIB_FGETS = @GNULIB_FGETS@
+GNULIB_FLOOR = @GNULIB_FLOOR@
+GNULIB_FLOORF = @GNULIB_FLOORF@
+GNULIB_FLOORL = @GNULIB_FLOORL@
+GNULIB_FMA = @GNULIB_FMA@
+GNULIB_FMAF = @GNULIB_FMAF@
+GNULIB_FMAL = @GNULIB_FMAL@
+GNULIB_FMOD = @GNULIB_FMOD@
+GNULIB_FMODF = @GNULIB_FMODF@
+GNULIB_FMODL = @GNULIB_FMODL@
GNULIB_FOPEN = @GNULIB_FOPEN@
GNULIB_FPRINTF = @GNULIB_FPRINTF@
GNULIB_FPRINTF_POSIX = @GNULIB_FPRINTF_POSIX@
@@ -887,6 +966,9 @@ GNULIB_FPUTC = @GNULIB_FPUTC@
GNULIB_FPUTS = @GNULIB_FPUTS@
GNULIB_FREAD = @GNULIB_FREAD@
GNULIB_FREOPEN = @GNULIB_FREOPEN@
+GNULIB_FREXP = @GNULIB_FREXP@
+GNULIB_FREXPF = @GNULIB_FREXPF@
+GNULIB_FREXPL = @GNULIB_FREXPL@
GNULIB_FSCANF = @GNULIB_FSCANF@
GNULIB_FSEEK = @GNULIB_FSEEK@
GNULIB_FSEEKO = @GNULIB_FSEEKO@
@@ -917,17 +999,47 @@ GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@
GNULIB_GRANTPT = @GNULIB_GRANTPT@
GNULIB_GROUP_MEMBER = @GNULIB_GROUP_MEMBER@
+GNULIB_HYPOT = @GNULIB_HYPOT@
+GNULIB_HYPOTF = @GNULIB_HYPOTF@
+GNULIB_HYPOTL = @GNULIB_HYPOTL@
GNULIB_ICONV = @GNULIB_ICONV@
+GNULIB_ILOGB = @GNULIB_ILOGB@
+GNULIB_ILOGBF = @GNULIB_ILOGBF@
+GNULIB_ILOGBL = @GNULIB_ILOGBL@
GNULIB_IMAXABS = @GNULIB_IMAXABS@
GNULIB_IMAXDIV = @GNULIB_IMAXDIV@
GNULIB_ISATTY = @GNULIB_ISATTY@
+GNULIB_ISBLANK = @GNULIB_ISBLANK@
+GNULIB_ISFINITE = @GNULIB_ISFINITE@
+GNULIB_ISINF = @GNULIB_ISINF@
+GNULIB_ISNAN = @GNULIB_ISNAN@
+GNULIB_ISNAND = @GNULIB_ISNAND@
+GNULIB_ISNANF = @GNULIB_ISNANF@
+GNULIB_ISNANL = @GNULIB_ISNANL@
GNULIB_ISWBLANK = @GNULIB_ISWBLANK@
GNULIB_ISWCTYPE = @GNULIB_ISWCTYPE@
GNULIB_LCHMOD = @GNULIB_LCHMOD@
GNULIB_LCHOWN = @GNULIB_LCHOWN@
+GNULIB_LDEXPF = @GNULIB_LDEXPF@
+GNULIB_LDEXPL = @GNULIB_LDEXPL@
GNULIB_LINK = @GNULIB_LINK@
GNULIB_LINKAT = @GNULIB_LINKAT@
GNULIB_LOCALECONV = @GNULIB_LOCALECONV@
+GNULIB_LOG = @GNULIB_LOG@
+GNULIB_LOG10 = @GNULIB_LOG10@
+GNULIB_LOG10F = @GNULIB_LOG10F@
+GNULIB_LOG10L = @GNULIB_LOG10L@
+GNULIB_LOG1P = @GNULIB_LOG1P@
+GNULIB_LOG1PF = @GNULIB_LOG1PF@
+GNULIB_LOG1PL = @GNULIB_LOG1PL@
+GNULIB_LOG2 = @GNULIB_LOG2@
+GNULIB_LOG2F = @GNULIB_LOG2F@
+GNULIB_LOG2L = @GNULIB_LOG2L@
+GNULIB_LOGB = @GNULIB_LOGB@
+GNULIB_LOGBF = @GNULIB_LOGBF@
+GNULIB_LOGBL = @GNULIB_LOGBL@
+GNULIB_LOGF = @GNULIB_LOGF@
+GNULIB_LOGL = @GNULIB_LOGL@
GNULIB_LSEEK = @GNULIB_LSEEK@
GNULIB_LSTAT = @GNULIB_LSTAT@
GNULIB_MALLOC_POSIX = @GNULIB_MALLOC_POSIX@
@@ -966,6 +1078,9 @@ GNULIB_MKOSTEMPS = @GNULIB_MKOSTEMPS@
GNULIB_MKSTEMP = @GNULIB_MKSTEMP@
GNULIB_MKSTEMPS = @GNULIB_MKSTEMPS@
GNULIB_MKTIME = @GNULIB_MKTIME@
+GNULIB_MODF = @GNULIB_MODF@
+GNULIB_MODFF = @GNULIB_MODFF@
+GNULIB_MODFL = @GNULIB_MODFL@
GNULIB_NANOSLEEP = @GNULIB_NANOSLEEP@
GNULIB_NL_LANGINFO = @GNULIB_NL_LANGINFO@
GNULIB_NONBLOCKING = @GNULIB_NONBLOCKING@
@@ -1001,6 +1116,7 @@ GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDU
GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN@
GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_DESTROY@
GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT = @GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT@
+GNULIB_POWF = @GNULIB_POWF@
GNULIB_PREAD = @GNULIB_PREAD@
GNULIB_PRINTF = @GNULIB_PRINTF@
GNULIB_PRINTF_POSIX = @GNULIB_PRINTF_POSIX@
@@ -1024,11 +1140,20 @@ GNULIB_READLINK = @GNULIB_READLINK@
GNULIB_READLINKAT = @GNULIB_READLINKAT@
GNULIB_REALLOC_POSIX = @GNULIB_REALLOC_POSIX@
GNULIB_REALPATH = @GNULIB_REALPATH@
+GNULIB_REMAINDER = @GNULIB_REMAINDER@
+GNULIB_REMAINDERF = @GNULIB_REMAINDERF@
+GNULIB_REMAINDERL = @GNULIB_REMAINDERL@
GNULIB_REMOVE = @GNULIB_REMOVE@
GNULIB_RENAME = @GNULIB_RENAME@
GNULIB_RENAMEAT = @GNULIB_RENAMEAT@
GNULIB_REWINDDIR = @GNULIB_REWINDDIR@
+GNULIB_RINT = @GNULIB_RINT@
+GNULIB_RINTF = @GNULIB_RINTF@
+GNULIB_RINTL = @GNULIB_RINTL@
GNULIB_RMDIR = @GNULIB_RMDIR@
+GNULIB_ROUND = @GNULIB_ROUND@
+GNULIB_ROUNDF = @GNULIB_ROUNDF@
+GNULIB_ROUNDL = @GNULIB_ROUNDL@
GNULIB_RPMATCH = @GNULIB_RPMATCH@
GNULIB_SCANDIR = @GNULIB_SCANDIR@
GNULIB_SCANF = @GNULIB_SCANF@
@@ -1039,10 +1164,16 @@ GNULIB_SETHOSTNAME = @GNULIB_SETHOSTNAME@
GNULIB_SETLOCALE = @GNULIB_SETLOCALE@
GNULIB_SIGACTION = @GNULIB_SIGACTION@
GNULIB_SIGNAL_H_SIGPIPE = @GNULIB_SIGNAL_H_SIGPIPE@
+GNULIB_SIGNBIT = @GNULIB_SIGNBIT@
GNULIB_SIGPROCMASK = @GNULIB_SIGPROCMASK@
+GNULIB_SINF = @GNULIB_SINF@
+GNULIB_SINHF = @GNULIB_SINHF@
+GNULIB_SINL = @GNULIB_SINL@
GNULIB_SLEEP = @GNULIB_SLEEP@
GNULIB_SNPRINTF = @GNULIB_SNPRINTF@
GNULIB_SPRINTF_POSIX = @GNULIB_SPRINTF_POSIX@
+GNULIB_SQRTF = @GNULIB_SQRTF@
+GNULIB_SQRTL = @GNULIB_SQRTL@
GNULIB_STAT = @GNULIB_STAT@
GNULIB_STDIO_H_NONBLOCKING = @GNULIB_STDIO_H_NONBLOCKING@
GNULIB_STDIO_H_SIGPIPE = @GNULIB_STDIO_H_SIGPIPE@
@@ -1071,10 +1202,17 @@ GNULIB_STRVERSCMP = @GNULIB_STRVERSCMP@
GNULIB_SYMLINK = @GNULIB_SYMLINK@
GNULIB_SYMLINKAT = @GNULIB_SYMLINKAT@
GNULIB_SYSTEM_POSIX = @GNULIB_SYSTEM_POSIX@
+GNULIB_TANF = @GNULIB_TANF@
+GNULIB_TANHF = @GNULIB_TANHF@
+GNULIB_TANL = @GNULIB_TANL@
GNULIB_TIMEGM = @GNULIB_TIMEGM@
GNULIB_TIME_R = @GNULIB_TIME_R@
+GNULIB_TIME_RZ = @GNULIB_TIME_RZ@
GNULIB_TMPFILE = @GNULIB_TMPFILE@
GNULIB_TOWCTRANS = @GNULIB_TOWCTRANS@
+GNULIB_TRUNC = @GNULIB_TRUNC@
+GNULIB_TRUNCF = @GNULIB_TRUNCF@
+GNULIB_TRUNCL = @GNULIB_TRUNCL@
GNULIB_TTYNAME_R = @GNULIB_TTYNAME_R@
GNULIB_UNISTD_H_NONBLOCKING = @GNULIB_UNISTD_H_NONBLOCKING@
GNULIB_UNISTD_H_SIGPIPE = @GNULIB_UNISTD_H_SIGPIPE@
@@ -1134,25 +1272,57 @@ GNULIB_WMEMSET = @GNULIB_WMEMSET@
GNULIB_WRITE = @GNULIB_WRITE@
GNULIB__EXIT = @GNULIB__EXIT@
GREP = @GREP@
+HAVE_ACOSF = @HAVE_ACOSF@
+HAVE_ACOSL = @HAVE_ACOSL@
HAVE_ALPHASORT = @HAVE_ALPHASORT@
+HAVE_ASINF = @HAVE_ASINF@
+HAVE_ASINL = @HAVE_ASINL@
HAVE_ASPRINTF = @HAVE_ASPRINTF@
+HAVE_ATAN2F = @HAVE_ATAN2F@
+HAVE_ATANF = @HAVE_ATANF@
+HAVE_ATANL = @HAVE_ATANL@
HAVE_ATOLL = @HAVE_ATOLL@
HAVE_BTOWC = @HAVE_BTOWC@
HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@
+HAVE_CBRT = @HAVE_CBRT@
+HAVE_CBRTF = @HAVE_CBRTF@
+HAVE_CBRTL = @HAVE_CBRTL@
HAVE_CHOWN = @HAVE_CHOWN@
HAVE_CLIX = @HAVE_CLIX@
HAVE_CLIX_IN_PATH = @HAVE_CLIX_IN_PATH@
HAVE_CLOSEDIR = @HAVE_CLOSEDIR@
+HAVE_COPYSIGN = @HAVE_COPYSIGN@
+HAVE_COPYSIGNL = @HAVE_COPYSIGNL@
+HAVE_COSF = @HAVE_COSF@
+HAVE_COSHF = @HAVE_COSHF@
+HAVE_COSL = @HAVE_COSL@
HAVE_CSC = @HAVE_CSC@
HAVE_CSCC = @HAVE_CSCC@
HAVE_CSCC_IN_PATH = @HAVE_CSCC_IN_PATH@
HAVE_CSC_IN_PATH = @HAVE_CSC_IN_PATH@
+HAVE_DECL_ACOSL = @HAVE_DECL_ACOSL@
+HAVE_DECL_ASINL = @HAVE_DECL_ASINL@
+HAVE_DECL_ATANL = @HAVE_DECL_ATANL@
+HAVE_DECL_CBRTF = @HAVE_DECL_CBRTF@
+HAVE_DECL_CBRTL = @HAVE_DECL_CBRTL@
+HAVE_DECL_CEILF = @HAVE_DECL_CEILF@
+HAVE_DECL_CEILL = @HAVE_DECL_CEILL@
+HAVE_DECL_COPYSIGNF = @HAVE_DECL_COPYSIGNF@
+HAVE_DECL_COSL = @HAVE_DECL_COSL@
HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
+HAVE_DECL_EXP2 = @HAVE_DECL_EXP2@
+HAVE_DECL_EXP2F = @HAVE_DECL_EXP2F@
+HAVE_DECL_EXP2L = @HAVE_DECL_EXP2L@
+HAVE_DECL_EXPL = @HAVE_DECL_EXPL@
+HAVE_DECL_EXPM1L = @HAVE_DECL_EXPM1L@
HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@
HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@
HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@
+HAVE_DECL_FLOORF = @HAVE_DECL_FLOORF@
+HAVE_DECL_FLOORL = @HAVE_DECL_FLOORL@
HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@
+HAVE_DECL_FREXPL = @HAVE_DECL_FREXPL@
HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@
HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@
HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
@@ -1164,13 +1334,28 @@ HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@
HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@
HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@
HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@
+HAVE_DECL_LDEXPL = @HAVE_DECL_LDEXPL@
HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@
+HAVE_DECL_LOG10L = @HAVE_DECL_LOG10L@
+HAVE_DECL_LOG2 = @HAVE_DECL_LOG2@
+HAVE_DECL_LOG2F = @HAVE_DECL_LOG2F@
+HAVE_DECL_LOG2L = @HAVE_DECL_LOG2L@
+HAVE_DECL_LOGB = @HAVE_DECL_LOGB@
+HAVE_DECL_LOGL = @HAVE_DECL_LOGL@
HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@
HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@
HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@
+HAVE_DECL_REMAINDER = @HAVE_DECL_REMAINDER@
+HAVE_DECL_REMAINDERL = @HAVE_DECL_REMAINDERL@
+HAVE_DECL_RINTF = @HAVE_DECL_RINTF@
+HAVE_DECL_ROUND = @HAVE_DECL_ROUND@
+HAVE_DECL_ROUNDF = @HAVE_DECL_ROUNDF@
+HAVE_DECL_ROUNDL = @HAVE_DECL_ROUNDL@
HAVE_DECL_SETENV = @HAVE_DECL_SETENV@
HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@
+HAVE_DECL_SINL = @HAVE_DECL_SINL@
HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@
+HAVE_DECL_SQRTL = @HAVE_DECL_SQRTL@
HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@
HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@
HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@
@@ -1179,6 +1364,10 @@ HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@
HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@
HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@
HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@
+HAVE_DECL_TANL = @HAVE_DECL_TANL@
+HAVE_DECL_TRUNC = @HAVE_DECL_TRUNC@
+HAVE_DECL_TRUNCF = @HAVE_DECL_TRUNCF@
+HAVE_DECL_TRUNCL = @HAVE_DECL_TRUNCL@
HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@
HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@
HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
@@ -1190,6 +1379,12 @@ HAVE_DUP2 = @HAVE_DUP2@
HAVE_DUP3 = @HAVE_DUP3@
HAVE_DUPLOCALE = @HAVE_DUPLOCALE@
HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
+HAVE_EXPF = @HAVE_EXPF@
+HAVE_EXPL = @HAVE_EXPL@
+HAVE_EXPM1 = @HAVE_EXPM1@
+HAVE_EXPM1F = @HAVE_EXPM1F@
+HAVE_FABSF = @HAVE_FABSF@
+HAVE_FABSL = @HAVE_FABSL@
HAVE_FACCESSAT = @HAVE_FACCESSAT@
HAVE_FCHDIR = @HAVE_FCHDIR@
HAVE_FCHMODAT = @HAVE_FCHMODAT@
@@ -1200,6 +1395,12 @@ HAVE_FDOPENDIR = @HAVE_FDOPENDIR@
HAVE_FEATURES_H = @HAVE_FEATURES_H@
HAVE_FFSL = @HAVE_FFSL@
HAVE_FFSLL = @HAVE_FFSLL@
+HAVE_FMA = @HAVE_FMA@
+HAVE_FMAF = @HAVE_FMAF@
+HAVE_FMAL = @HAVE_FMAL@
+HAVE_FMODF = @HAVE_FMODF@
+HAVE_FMODL = @HAVE_FMODL@
+HAVE_FREXPF = @HAVE_FREXPF@
HAVE_FSEEKO = @HAVE_FSEEKO@
HAVE_FSTATAT = @HAVE_FSTATAT@
HAVE_FSYNC = @HAVE_FSYNC@
@@ -1222,9 +1423,18 @@ HAVE_GIJ_IN_PATH = @HAVE_GIJ_IN_PATH@
HAVE_GLOBAL_SYMBOL_PIPE = @HAVE_GLOBAL_SYMBOL_PIPE@
HAVE_GRANTPT = @HAVE_GRANTPT@
HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@
+HAVE_HYPOTF = @HAVE_HYPOTF@
+HAVE_HYPOTL = @HAVE_HYPOTL@
+HAVE_ILOGB = @HAVE_ILOGB@
+HAVE_ILOGBF = @HAVE_ILOGBF@
+HAVE_ILOGBL = @HAVE_ILOGBL@
HAVE_ILRUN = @HAVE_ILRUN@
HAVE_ILRUN_IN_PATH = @HAVE_ILRUN_IN_PATH@
HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
+HAVE_ISBLANK = @HAVE_ISBLANK@
+HAVE_ISNAND = @HAVE_ISNAND@
+HAVE_ISNANF = @HAVE_ISNANF@
+HAVE_ISNANL = @HAVE_ISNANL@
HAVE_ISWBLANK = @HAVE_ISWBLANK@
HAVE_ISWCNTRL = @HAVE_ISWCNTRL@
HAVE_JAVA = @HAVE_JAVA@
@@ -1246,12 +1456,22 @@ HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@
HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@
HAVE_LCHMOD = @HAVE_LCHMOD@
HAVE_LCHOWN = @HAVE_LCHOWN@
-HAVE_LIBEXPAT = @HAVE_LIBEXPAT@
+HAVE_LDEXPF = @HAVE_LDEXPF@
HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@
HAVE_LINK = @HAVE_LINK@
HAVE_LINKAT = @HAVE_LINKAT@
+HAVE_LOG10F = @HAVE_LOG10F@
+HAVE_LOG10L = @HAVE_LOG10L@
+HAVE_LOG1P = @HAVE_LOG1P@
+HAVE_LOG1PF = @HAVE_LOG1PF@
+HAVE_LOG1PL = @HAVE_LOG1PL@
+HAVE_LOGBF = @HAVE_LOGBF@
+HAVE_LOGBL = @HAVE_LOGBL@
+HAVE_LOGF = @HAVE_LOGF@
+HAVE_LOGL = @HAVE_LOGL@
HAVE_LONG_LONG_INT = @HAVE_LONG_LONG_INT@
HAVE_LSTAT = @HAVE_LSTAT@
+HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@
HAVE_MBRLEN = @HAVE_MBRLEN@
HAVE_MBRTOWC = @HAVE_MBRTOWC@
HAVE_MBSINIT = @HAVE_MBSINIT@
@@ -1272,6 +1492,8 @@ HAVE_MKOSTEMP = @HAVE_MKOSTEMP@
HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@
HAVE_MKSTEMP = @HAVE_MKSTEMP@
HAVE_MKSTEMPS = @HAVE_MKSTEMPS@
+HAVE_MODFF = @HAVE_MODFF@
+HAVE_MODFL = @HAVE_MODFL@
HAVE_MONO = @HAVE_MONO@
HAVE_MONO_IN_PATH = @HAVE_MONO_IN_PATH@
HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@
@@ -1291,6 +1513,7 @@ HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@
HAVE_POSIX_SPAWN = @HAVE_POSIX_SPAWN@
HAVE_POSIX_SPAWNATTR_T = @HAVE_POSIX_SPAWNATTR_T@
HAVE_POSIX_SPAWN_FILE_ACTIONS_T = @HAVE_POSIX_SPAWN_FILE_ACTIONS_T@
+HAVE_POWF = @HAVE_POWF@
HAVE_PREAD = @HAVE_PREAD@
HAVE_PSELECT = @HAVE_PSELECT@
HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@
@@ -1306,9 +1529,14 @@ HAVE_READDIR = @HAVE_READDIR@
HAVE_READLINK = @HAVE_READLINK@
HAVE_READLINKAT = @HAVE_READLINKAT@
HAVE_REALPATH = @HAVE_REALPATH@
+HAVE_REMAINDER = @HAVE_REMAINDER@
+HAVE_REMAINDERF = @HAVE_REMAINDERF@
HAVE_RENAMEAT = @HAVE_RENAMEAT@
HAVE_REWINDDIR = @HAVE_REWINDDIR@
+HAVE_RINT = @HAVE_RINT@
+HAVE_RINTL = @HAVE_RINTL@
HAVE_RPMATCH = @HAVE_RPMATCH@
+HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = @HAVE_SAME_LONG_DOUBLE_AS_DOUBLE@
HAVE_SCANDIR = @HAVE_SCANDIR@
HAVE_SCHED_H = @HAVE_SCHED_H@
HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@
@@ -1321,9 +1549,14 @@ HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@
HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@
HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@
HAVE_SIGSET_T = @HAVE_SIGSET_T@
+HAVE_SINF = @HAVE_SINF@
+HAVE_SINHF = @HAVE_SINHF@
+HAVE_SINL = @HAVE_SINL@
HAVE_SLEEP = @HAVE_SLEEP@
HAVE_SNPRINTF = @HAVE_SNPRINTF@
HAVE_SPAWN_H = @HAVE_SPAWN_H@
+HAVE_SQRTF = @HAVE_SQRTF@
+HAVE_SQRTL = @HAVE_SQRTL@
HAVE_STDINT_H = @HAVE_STDINT_H@
HAVE_STPCPY = @HAVE_STPCPY@
HAVE_STPNCPY = @HAVE_STPNCPY@
@@ -1349,7 +1582,11 @@ HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@
HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@
HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@
HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@
+HAVE_TANF = @HAVE_TANF@
+HAVE_TANHF = @HAVE_TANHF@
+HAVE_TANL = @HAVE_TANL@
HAVE_TIMEGM = @HAVE_TIMEGM@
+HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@
HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@
HAVE_UNISTD_H = @HAVE_UNISTD_H@
HAVE_UNLINKAT = @HAVE_UNLINKAT@
@@ -1425,13 +1662,16 @@ INTLOBJS = @INTLOBJS@
INTL_DEFAULT_VERBOSITY = @INTL_DEFAULT_VERBOSITY@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+ISINF_LIBM = @ISINF_LIBM@
+ISNAND_LIBM = @ISNAND_LIBM@
+ISNANF_LIBM = @ISNANF_LIBM@
+ISNANL_LIBM = @ISNANL_LIBM@
+ISNAN_LIBM = @ISNAN_LIBM@
JAR = @JAR@
JAVA_CHOICE = @JAVA_CHOICE@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBCROCO = @LIBCROCO@
-LIBEXPAT = @LIBEXPAT@
-LIBEXPAT_PREFIX = @LIBEXPAT_PREFIX@
LIBGLIB = @LIBGLIB@
LIBGLIB_H = @LIBGLIB_H@
LIBGREP_LIBDEPS = @LIBGREP_LIBDEPS@
@@ -1450,6 +1690,7 @@ LIBTOOL = @LIBTOOL@
LIBUNISTRING = @LIBUNISTRING@
LIBUNISTRING_PREFIX = @LIBUNISTRING_PREFIX@
LIBUNISTRING_UNICONV_H = @LIBUNISTRING_UNICONV_H@
+LIBUNISTRING_UNICTYPE_H = @LIBUNISTRING_UNICTYPE_H@
LIBUNISTRING_UNILBRK_H = @LIBUNISTRING_UNILBRK_H@
LIBUNISTRING_UNINAME_H = @LIBUNISTRING_UNINAME_H@
LIBUNISTRING_UNISTR_H = @LIBUNISTRING_UNISTR_H@
@@ -1458,6 +1699,7 @@ LIBUNISTRING_UNIWIDTH_H = @LIBUNISTRING_UNIWIDTH_H@
LIBXML = @LIBXML@
LIBXML_H = @LIBXML_H@
LIB_ACL = @LIB_ACL@
+LIB_HAS_ACL = @LIB_HAS_ACL@
LIB_POSIX_SPAWN = @LIB_POSIX_SPAWN@
LIPO = @LIPO@
LN_S = @LN_S@
@@ -1467,9 +1709,9 @@ LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@
LOCALE_JA = @LOCALE_JA@
LOCALE_TR_UTF8 = @LOCALE_TR_UTF8@
LOCALE_ZH_CN = @LOCALE_ZH_CN@
+LOG10_LIBM = @LOG10_LIBM@
LTLIBC = @LTLIBC@
LTLIBCROCO = @LTLIBCROCO@
-LTLIBEXPAT = @LTLIBEXPAT@
LTLIBGLIB = @LTLIBGLIB@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
@@ -1480,6 +1722,7 @@ LTLIBTERMINFO = @LTLIBTERMINFO@
LTLIBTHREAD = @LTLIBTHREAD@
LTLIBUNISTRING = @LTLIBUNISTRING@
LTLIBXML = @LTLIBXML@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
@@ -1489,6 +1732,7 @@ MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
MSGMERGE_LIBM = @MSGMERGE_LIBM@
+NEXT_AS_FIRST_DIRECTIVE_CTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_CTYPE_H@
NEXT_AS_FIRST_DIRECTIVE_DIRENT_H = @NEXT_AS_FIRST_DIRECTIVE_DIRENT_H@
NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@
NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@
@@ -1498,6 +1742,7 @@ NEXT_AS_FIRST_DIRECTIVE_ICONV_H = @NEXT_AS_FIRST_DIRECTIVE_ICONV_H@
NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@
NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@
NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@
+NEXT_AS_FIRST_DIRECTIVE_MATH_H = @NEXT_AS_FIRST_DIRECTIVE_MATH_H@
NEXT_AS_FIRST_DIRECTIVE_SCHED_H = @NEXT_AS_FIRST_DIRECTIVE_SCHED_H@
NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@
NEXT_AS_FIRST_DIRECTIVE_SPAWN_H = @NEXT_AS_FIRST_DIRECTIVE_SPAWN_H@
@@ -1516,6 +1761,7 @@ NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@
NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@
NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@
NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_WCTYPE_H@
+NEXT_CTYPE_H = @NEXT_CTYPE_H@
NEXT_DIRENT_H = @NEXT_DIRENT_H@
NEXT_ERRNO_H = @NEXT_ERRNO_H@
NEXT_FCNTL_H = @NEXT_FCNTL_H@
@@ -1525,6 +1771,7 @@ NEXT_ICONV_H = @NEXT_ICONV_H@
NEXT_INTTYPES_H = @NEXT_INTTYPES_H@
NEXT_LANGINFO_H = @NEXT_LANGINFO_H@
NEXT_LOCALE_H = @NEXT_LOCALE_H@
+NEXT_MATH_H = @NEXT_MATH_H@
NEXT_SCHED_H = @NEXT_SCHED_H@
NEXT_SIGNAL_H = @NEXT_SIGNAL_H@
NEXT_SPAWN_H = @NEXT_SPAWN_H@
@@ -1555,12 +1802,14 @@ PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_SUFFIX = @PACKAGE_SUFFIX@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
POSUB = @POSUB@
+POW_LIBM = @POW_LIBM@
PRAGMA_COLUMNS = @PRAGMA_COLUMNS@
PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@
PRIPTR_PREFIX = @PRIPTR_PREFIX@
@@ -1581,6 +1830,11 @@ RELOCATABLE_STRIP = :
REPLACE_BTOWC = @REPLACE_BTOWC@
REPLACE_CALLOC = @REPLACE_CALLOC@
REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@
+REPLACE_CBRTF = @REPLACE_CBRTF@
+REPLACE_CBRTL = @REPLACE_CBRTL@
+REPLACE_CEIL = @REPLACE_CEIL@
+REPLACE_CEILF = @REPLACE_CEILF@
+REPLACE_CEILL = @REPLACE_CEILL@
REPLACE_CHOWN = @REPLACE_CHOWN@
REPLACE_CLOSE = @REPLACE_CLOSE@
REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@
@@ -1589,16 +1843,33 @@ REPLACE_DPRINTF = @REPLACE_DPRINTF@
REPLACE_DUP = @REPLACE_DUP@
REPLACE_DUP2 = @REPLACE_DUP2@
REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@
+REPLACE_EXP2 = @REPLACE_EXP2@
+REPLACE_EXP2L = @REPLACE_EXP2L@
+REPLACE_EXPM1 = @REPLACE_EXPM1@
+REPLACE_EXPM1F = @REPLACE_EXPM1F@
+REPLACE_FABSL = @REPLACE_FABSL@
REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@
REPLACE_FCLOSE = @REPLACE_FCLOSE@
REPLACE_FCNTL = @REPLACE_FCNTL@
REPLACE_FDOPEN = @REPLACE_FDOPEN@
REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@
REPLACE_FFLUSH = @REPLACE_FFLUSH@
+REPLACE_FLOOR = @REPLACE_FLOOR@
+REPLACE_FLOORF = @REPLACE_FLOORF@
+REPLACE_FLOORL = @REPLACE_FLOORL@
+REPLACE_FMA = @REPLACE_FMA@
+REPLACE_FMAF = @REPLACE_FMAF@
+REPLACE_FMAL = @REPLACE_FMAL@
+REPLACE_FMOD = @REPLACE_FMOD@
+REPLACE_FMODF = @REPLACE_FMODF@
+REPLACE_FMODL = @REPLACE_FMODL@
REPLACE_FOPEN = @REPLACE_FOPEN@
REPLACE_FPRINTF = @REPLACE_FPRINTF@
REPLACE_FPURGE = @REPLACE_FPURGE@
REPLACE_FREOPEN = @REPLACE_FREOPEN@
+REPLACE_FREXP = @REPLACE_FREXP@
+REPLACE_FREXPF = @REPLACE_FREXPF@
+REPLACE_FREXPL = @REPLACE_FREXPL@
REPLACE_FSEEK = @REPLACE_FSEEK@
REPLACE_FSEEKO = @REPLACE_FSEEKO@
REPLACE_FSTAT = @REPLACE_FSTAT@
@@ -1617,19 +1888,44 @@ REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@
REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@
REPLACE_GMTIME = @REPLACE_GMTIME@
+REPLACE_HUGE_VAL = @REPLACE_HUGE_VAL@
+REPLACE_HYPOT = @REPLACE_HYPOT@
+REPLACE_HYPOTF = @REPLACE_HYPOTF@
+REPLACE_HYPOTL = @REPLACE_HYPOTL@
REPLACE_ICONV = @REPLACE_ICONV@
REPLACE_ICONV_OPEN = @REPLACE_ICONV_OPEN@
REPLACE_ICONV_UTF = @REPLACE_ICONV_UTF@
+REPLACE_ILOGB = @REPLACE_ILOGB@
+REPLACE_ILOGBF = @REPLACE_ILOGBF@
REPLACE_ISATTY = @REPLACE_ISATTY@
+REPLACE_ISFINITE = @REPLACE_ISFINITE@
+REPLACE_ISINF = @REPLACE_ISINF@
+REPLACE_ISNAN = @REPLACE_ISNAN@
REPLACE_ISWBLANK = @REPLACE_ISWBLANK@
REPLACE_ISWCNTRL = @REPLACE_ISWCNTRL@
REPLACE_ITOLD = @REPLACE_ITOLD@
REPLACE_LCHOWN = @REPLACE_LCHOWN@
+REPLACE_LDEXPL = @REPLACE_LDEXPL@
REPLACE_LINK = @REPLACE_LINK@
REPLACE_LINKAT = @REPLACE_LINKAT@
REPLACE_LOCALECONV = @REPLACE_LOCALECONV@
REPLACE_LOCALTIME = @REPLACE_LOCALTIME@
REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@
+REPLACE_LOG = @REPLACE_LOG@
+REPLACE_LOG10 = @REPLACE_LOG10@
+REPLACE_LOG10F = @REPLACE_LOG10F@
+REPLACE_LOG10L = @REPLACE_LOG10L@
+REPLACE_LOG1P = @REPLACE_LOG1P@
+REPLACE_LOG1PF = @REPLACE_LOG1PF@
+REPLACE_LOG1PL = @REPLACE_LOG1PL@
+REPLACE_LOG2 = @REPLACE_LOG2@
+REPLACE_LOG2F = @REPLACE_LOG2F@
+REPLACE_LOG2L = @REPLACE_LOG2L@
+REPLACE_LOGB = @REPLACE_LOGB@
+REPLACE_LOGBF = @REPLACE_LOGBF@
+REPLACE_LOGBL = @REPLACE_LOGBL@
+REPLACE_LOGF = @REPLACE_LOGF@
+REPLACE_LOGL = @REPLACE_LOGL@
REPLACE_LSEEK = @REPLACE_LSEEK@
REPLACE_LSTAT = @REPLACE_LSTAT@
REPLACE_MALLOC = @REPLACE_MALLOC@
@@ -1647,6 +1943,10 @@ REPLACE_MKFIFO = @REPLACE_MKFIFO@
REPLACE_MKNOD = @REPLACE_MKNOD@
REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
REPLACE_MKTIME = @REPLACE_MKTIME@
+REPLACE_MODF = @REPLACE_MODF@
+REPLACE_MODFF = @REPLACE_MODFF@
+REPLACE_MODFL = @REPLACE_MODFL@
+REPLACE_NAN = @REPLACE_NAN@
REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@
REPLACE_NULL = @REPLACE_NULL@
@@ -1676,16 +1976,25 @@ REPLACE_READLINK = @REPLACE_READLINK@
REPLACE_READLINKAT = @REPLACE_READLINKAT@
REPLACE_REALLOC = @REPLACE_REALLOC@
REPLACE_REALPATH = @REPLACE_REALPATH@
+REPLACE_REMAINDER = @REPLACE_REMAINDER@
+REPLACE_REMAINDERF = @REPLACE_REMAINDERF@
+REPLACE_REMAINDERL = @REPLACE_REMAINDERL@
REPLACE_REMOVE = @REPLACE_REMOVE@
REPLACE_RENAME = @REPLACE_RENAME@
REPLACE_RENAMEAT = @REPLACE_RENAMEAT@
REPLACE_RMDIR = @REPLACE_RMDIR@
+REPLACE_ROUND = @REPLACE_ROUND@
+REPLACE_ROUNDF = @REPLACE_ROUNDF@
+REPLACE_ROUNDL = @REPLACE_ROUNDL@
REPLACE_SELECT = @REPLACE_SELECT@
REPLACE_SETENV = @REPLACE_SETENV@
REPLACE_SETLOCALE = @REPLACE_SETLOCALE@
+REPLACE_SIGNBIT = @REPLACE_SIGNBIT@
+REPLACE_SIGNBIT_USING_GCC = @REPLACE_SIGNBIT_USING_GCC@
REPLACE_SLEEP = @REPLACE_SLEEP@
REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
REPLACE_SPRINTF = @REPLACE_SPRINTF@
+REPLACE_SQRTL = @REPLACE_SQRTL@
REPLACE_STAT = @REPLACE_STAT@
REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@
REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
@@ -1711,6 +2020,9 @@ REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@
REPLACE_TIMEGM = @REPLACE_TIMEGM@
REPLACE_TMPFILE = @REPLACE_TMPFILE@
REPLACE_TOWLOWER = @REPLACE_TOWLOWER@
+REPLACE_TRUNC = @REPLACE_TRUNC@
+REPLACE_TRUNCF = @REPLACE_TRUNCF@
+REPLACE_TRUNCL = @REPLACE_TRUNCL@
REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@
REPLACE_UNLINK = @REPLACE_UNLINK@
REPLACE_UNLINKAT = @REPLACE_UNLINKAT@
@@ -1737,6 +2049,7 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@
SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
+STDALIGN_H = @STDALIGN_H@
STDARG_H = @STDARG_H@
STDBOOL_H = @STDBOOL_H@
STDDEF_H = @STDDEF_H@
@@ -1751,6 +2064,7 @@ TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@
UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@
UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@
UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@
+UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
USE_ACL = @USE_ACL@
@@ -1847,9 +2161,8 @@ AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies subdir-objects
# Special rules for C# auxiliary programs.
# Special rules for Tcl auxiliary program.
-EXTRA_DIST = FILES project-id ChangeLog.0 \
- gnu/gettext/DumpResource.java gnu/gettext/GetURL.java \
- msgfmt.cs msgunfmt.cs msgunfmt.tcl
+EXTRA_DIST = FILES project-id gnu/gettext/DumpResource.java \
+ gnu/gettext/GetURL.java msgfmt.cs msgunfmt.cs msgunfmt.tcl
MOSTLYCLEANFILES = core *.stackdump $(am__append_4)
CLEANFILES = gnu.gettext.DumpResource$(EXEEXT) \
gnu.gettext.GetURL$(EXEEXT) gettext.jar gnu/gettext/*.class \
@@ -1863,7 +2176,8 @@ po-lex.h open-catalog.h read-catalog-abstract.h read-catalog.h \
read-po.h read-properties.h read-stringtable.h \
str-list.h \
color.h write-catalog.h write-po.h write-properties.h write-stringtable.h \
-dir-list.h file-list.h po-gram-gen.h po-gram-gen2.h \
+dir-list.h file-list.h po-gram-gen.h po-gram-gen2.h cldr-plural.h \
+cldr-plural-exp.h locating-rule.h its.h \
msgl-charset.h msgl-equal.h msgl-iconv.h msgl-ascii.h msgl-cat.h msgl-header.h \
msgl-english.h msgl-check.h msgl-fsearch.h msgfmt.h msgunfmt.h \
plural-count.h plural-eval.h plural-distrib.h \
@@ -1874,11 +2188,12 @@ read-resources.h write-resources.h \
read-tcl.h write-tcl.h \
write-qt.h \
read-desktop.h write-desktop.h \
+write-xml.h \
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 libexpat-compat.h
+x-javascript.h x-vala.h x-gsettings.h x-desktop.h x-appdata.h
aliaspath = $(localedir)
jardir = $(datadir)/gettext
@@ -1921,7 +2236,7 @@ dir-list.c str-list.c
@WOE32DLL_FALSE@ format-perl.c format-perl-brace.c format-php.c \
@WOE32DLL_FALSE@ format-gcc-internal.c format-gfc-internal.c \
@WOE32DLL_FALSE@ format-qt.c format-qt-plural.c format-kde.c \
-@WOE32DLL_FALSE@ format-boost.c format-lua.c \
+@WOE32DLL_FALSE@ format-kde-kuit.c format-boost.c format-lua.c \
@WOE32DLL_FALSE@ format-javascript.c
@WOE32DLL_TRUE@FORMAT_SOURCE = ../woe32dll/c++format.cc \
@WOE32DLL_TRUE@ format-invalid.h format-c.c format-c-parse.h \
@@ -1933,7 +2248,8 @@ dir-list.c str-list.c
@WOE32DLL_TRUE@ format-perl.c format-perl-brace.c format-php.c \
@WOE32DLL_TRUE@ format-gcc-internal.c format-gfc-internal.c \
@WOE32DLL_TRUE@ format-qt.c format-qt-plural.c format-kde.c \
-@WOE32DLL_TRUE@ format-boost.c format-lua.c format-javascript.c
+@WOE32DLL_TRUE@ format-kde-kuit.c format-boost.c format-lua.c \
+@WOE32DLL_TRUE@ format-javascript.c
# libgettextsrc contains all code that is needed by at least two programs.
libgettextsrc_la_SOURCES = $(COMMON_SOURCE) read-catalog.c color.c \
@@ -1941,7 +2257,8 @@ libgettextsrc_la_SOURCES = $(COMMON_SOURCE) read-catalog.c color.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 $(FORMAT_SOURCE) read-desktop.c $(am__append_1)
+ plural-table.c quote.h sentence.h sentence.c $(FORMAT_SOURCE) \
+ read-desktop.c locating-rule.c its.c $(am__append_1)
# msggrep needs pattern matching.
LIBGREP = ../libgrep/libgrep.a
@@ -1950,7 +2267,7 @@ LIBGREP = ../libgrep/libgrep.a
msgcmp_SOURCES = msgcmp.c msgl-fsearch.c
msgfmt_SOURCES = msgfmt.c write-mo.c write-java.c write-csharp.c \
write-resources.c write-tcl.c write-qt.c write-desktop.c \
- ../../gettext-runtime/intl/hash-string.c
+ write-xml.c ../../gettext-runtime/intl/hash-string.c
@WOE32DLL_FALSE@msgmerge_SOURCES = msgmerge.c msgl-fsearch.c \
@WOE32DLL_FALSE@ lang-table.c plural-count.c
@WOE32DLL_TRUE@msgmerge_SOURCES = ../woe32dll/c++msgmerge.cc \
@@ -1961,16 +2278,14 @@ msgunfmt_SOURCES = msgunfmt.c read-mo.c read-java.c read-csharp.c \
@WOE32DLL_FALSE@ x-python.c x-lisp.c x-elisp.c x-librep.c \
@WOE32DLL_FALSE@ x-scheme.c x-smalltalk.c x-java.c x-csharp.c \
@WOE32DLL_FALSE@ x-awk.c x-ycp.c x-tcl.c x-perl.c x-php.c \
-@WOE32DLL_FALSE@ x-rst.c x-glade.c x-lua.c x-javascript.c \
-@WOE32DLL_FALSE@ x-vala.c x-gsettings.c libexpat-compat.c \
+@WOE32DLL_FALSE@ x-rst.c x-lua.c x-javascript.c x-vala.c \
@WOE32DLL_FALSE@ x-desktop.c
@WOE32DLL_TRUE@xgettext_SOURCES = ../woe32dll/c++xgettext.cc x-c.c \
@WOE32DLL_TRUE@ x-po.c x-sh.c x-python.c x-lisp.c x-elisp.c \
@WOE32DLL_TRUE@ x-librep.c x-scheme.c x-smalltalk.c x-java.c \
@WOE32DLL_TRUE@ x-csharp.c x-awk.c x-ycp.c x-tcl.c x-perl.c \
-@WOE32DLL_TRUE@ x-php.c x-rst.c x-glade.c x-lua.c \
-@WOE32DLL_TRUE@ x-javascript.c x-vala.c x-gsettings.c \
-@WOE32DLL_TRUE@ libexpat-compat.c x-desktop.c
+@WOE32DLL_TRUE@ x-php.c x-rst.c x-lua.c x-javascript.c x-vala.c \
+@WOE32DLL_TRUE@ x-desktop.c
@WOE32DLL_FALSE@msgattrib_SOURCES = msgattrib.c
@WOE32DLL_TRUE@msgattrib_SOURCES = ../woe32dll/c++msgattrib.cc
@WOE32DLL_FALSE@msgcat_SOURCES = msgcat.c
@@ -2000,6 +2315,9 @@ msginit_SOURCES = msginit.c lang-table.c plural-count.c \
recode_sr_latin_SOURCES = recode-sr-latin.c filter-sr-latin.c
hostname_SOURCES = hostname.c
urlget_SOURCES = urlget.c
+cldr_plurals_SOURCES = cldr-plural.y cldr-plural-exp.c cldr-plurals.c
+cldr_plurals_CFLAGS = $(AM_CFLAGS) $(INCXML)
+cldr_plurals_LDADD = libgettextsrc.la $(LDADD)
# How to build libgettextsrc.la.
# Need ../gnulib-lib/libgettextlib.la.
@@ -2012,7 +2330,7 @@ urlget_SOURCES = urlget.c
libgettextsrc_la_LDFLAGS = -release @VERSION@ \
../gnulib-lib/libgettextlib.la $(LTLIBUNISTRING) @LTLIBINTL@ \
@LTLIBICONV@ -lc -no-undefined $(am__append_2)
-libgettextsrc_la_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_3)
+libgettextsrc_la_CPPFLAGS = $(AM_CPPFLAGS) $(INCXML) $(am__append_3)
# Compile-time flags for particular source files.
msgmerge_CFLAGS = $(AM_CFLAGS) $(OPENMP_CFLAGS)
@@ -2026,7 +2344,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)
@@ -2077,6 +2395,7 @@ msguniq_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(bindir)\"
recode_sr_latin_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(bindir)\"
hostname_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
urlget_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
+cldr_plurals_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
@RELOCATABLE_VIA_LD_TRUE@msgcmp_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
@RELOCATABLE_VIA_LD_TRUE@msgfmt_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
@RELOCATABLE_VIA_LD_TRUE@msgmerge_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
@@ -2095,6 +2414,7 @@ urlget_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
@RELOCATABLE_VIA_LD_TRUE@recode_sr_latin_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(bindir)`
@RELOCATABLE_VIA_LD_TRUE@hostname_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(pkglibdir)`
@RELOCATABLE_VIA_LD_TRUE@urlget_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(pkglibdir)`
+@RELOCATABLE_VIA_LD_TRUE@cldr_plurals_LDFLAGS = `$(RELOCATABLE_LDFLAGS) $(pkglibdir)`
# Linking with C++ libraries is needed _only_ on mingw and Cygwin.
@WOE32DLL_FALSE@libgettextsrc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
@@ -2210,7 +2530,7 @@ urlget_CPPFLAGS = $(AM_CPPFLAGS) -DINSTALLDIR=\"$(pkglibdir)\"
# Special rules for bison and flex generated files.
BUILT_SOURCES = \
- po-gram-gen.c po-gram-gen.h po-gram-gen2.h
+ po-gram-gen.c po-gram-gen.h po-gram-gen2.h cldr-plural.c cldr-plural.h
# Special rules for Java compilation.
@@ -2243,7 +2563,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnits src/Makefile
-.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -2383,6 +2702,10 @@ clean-noinstPROGRAMS:
echo " rm -f" $$list; \
rm -f $$list
+cldr-plurals$(EXEEXT): $(cldr_plurals_OBJECTS) $(cldr_plurals_DEPENDENCIES) $(EXTRA_cldr_plurals_DEPENDENCIES)
+ @rm -f cldr-plurals$(EXEEXT)
+ $(AM_V_CCLD)$(cldr_plurals_LINK) $(cldr_plurals_OBJECTS) $(cldr_plurals_LDADD) $(LIBS)
+
hostname$(EXEEXT): $(hostname_OBJECTS) $(hostname_DEPENDENCIES) $(EXTRA_hostname_DEPENDENCIES)
@rm -f hostname$(EXEEXT)
$(AM_V_CCLD)$(hostname_LINK) $(hostname_OBJECTS) $(hostname_LDADD) $(LIBS)
@@ -2592,6 +2915,9 @@ libgettextsrc_la-plural-eval.lo: plural-eval.c
libgettextsrc_la-plural-table.lo: plural-table.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-plural-table.lo `test -f 'plural-table.c' || echo '$(srcdir)/'`plural-table.c
+libgettextsrc_la-sentence.lo: sentence.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-sentence.lo `test -f 'sentence.c' || echo '$(srcdir)/'`sentence.c
+
libgettextsrc_la-format.lo: format.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-format.lo `test -f 'format.c' || echo '$(srcdir)/'`format.c
@@ -2661,6 +2987,9 @@ libgettextsrc_la-format-qt-plural.lo: format-qt-plural.c
libgettextsrc_la-format-kde.lo: format-kde.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-format-kde.lo `test -f 'format-kde.c' || echo '$(srcdir)/'`format-kde.c
+libgettextsrc_la-format-kde-kuit.lo: format-kde-kuit.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-format-kde-kuit.lo `test -f 'format-kde-kuit.c' || echo '$(srcdir)/'`format-kde-kuit.c
+
libgettextsrc_la-format-boost.lo: format-boost.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-format-boost.lo `test -f 'format-boost.c' || echo '$(srcdir)/'`format-boost.c
@@ -2673,9 +3002,33 @@ libgettextsrc_la-format-javascript.lo: format-javascript.c
libgettextsrc_la-read-desktop.lo: read-desktop.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-read-desktop.lo `test -f 'read-desktop.c' || echo '$(srcdir)/'`read-desktop.c
+libgettextsrc_la-locating-rule.lo: locating-rule.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-locating-rule.lo `test -f 'locating-rule.c' || echo '$(srcdir)/'`locating-rule.c
+
+libgettextsrc_la-its.lo: its.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgettextsrc_la-its.lo `test -f 'its.c' || echo '$(srcdir)/'`its.c
+
../woe32dll/libgettextsrc_la-gettextsrc-exports.lo: ../woe32dll/gettextsrc-exports.c
$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgettextsrc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../woe32dll/libgettextsrc_la-gettextsrc-exports.lo `test -f '../woe32dll/gettextsrc-exports.c' || echo '$(srcdir)/'`../woe32dll/gettextsrc-exports.c
+cldr_plurals-cldr-plural.o: cldr-plural.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cldr_plurals_CPPFLAGS) $(CPPFLAGS) $(cldr_plurals_CFLAGS) $(CFLAGS) -c -o cldr_plurals-cldr-plural.o `test -f 'cldr-plural.c' || echo '$(srcdir)/'`cldr-plural.c
+
+cldr_plurals-cldr-plural.obj: cldr-plural.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cldr_plurals_CPPFLAGS) $(CPPFLAGS) $(cldr_plurals_CFLAGS) $(CFLAGS) -c -o cldr_plurals-cldr-plural.obj `if test -f 'cldr-plural.c'; then $(CYGPATH_W) 'cldr-plural.c'; else $(CYGPATH_W) '$(srcdir)/cldr-plural.c'; fi`
+
+cldr_plurals-cldr-plural-exp.o: cldr-plural-exp.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cldr_plurals_CPPFLAGS) $(CPPFLAGS) $(cldr_plurals_CFLAGS) $(CFLAGS) -c -o cldr_plurals-cldr-plural-exp.o `test -f 'cldr-plural-exp.c' || echo '$(srcdir)/'`cldr-plural-exp.c
+
+cldr_plurals-cldr-plural-exp.obj: cldr-plural-exp.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cldr_plurals_CPPFLAGS) $(CPPFLAGS) $(cldr_plurals_CFLAGS) $(CFLAGS) -c -o cldr_plurals-cldr-plural-exp.obj `if test -f 'cldr-plural-exp.c'; then $(CYGPATH_W) 'cldr-plural-exp.c'; else $(CYGPATH_W) '$(srcdir)/cldr-plural-exp.c'; fi`
+
+cldr_plurals-cldr-plurals.o: cldr-plurals.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cldr_plurals_CPPFLAGS) $(CPPFLAGS) $(cldr_plurals_CFLAGS) $(CFLAGS) -c -o cldr_plurals-cldr-plurals.o `test -f 'cldr-plurals.c' || echo '$(srcdir)/'`cldr-plurals.c
+
+cldr_plurals-cldr-plurals.obj: cldr-plurals.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cldr_plurals_CPPFLAGS) $(CPPFLAGS) $(cldr_plurals_CFLAGS) $(CFLAGS) -c -o cldr_plurals-cldr-plurals.obj `if test -f 'cldr-plurals.c'; then $(CYGPATH_W) 'cldr-plurals.c'; else $(CYGPATH_W) '$(srcdir)/cldr-plurals.c'; fi`
+
hostname-hostname.o: hostname.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(hostname_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hostname-hostname.o `test -f 'hostname.c' || echo '$(srcdir)/'`hostname.c
@@ -2796,6 +3149,12 @@ msgfmt-write-desktop.o: write-desktop.c
msgfmt-write-desktop.obj: write-desktop.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(msgfmt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msgfmt-write-desktop.obj `if test -f 'write-desktop.c'; then $(CYGPATH_W) 'write-desktop.c'; else $(CYGPATH_W) '$(srcdir)/write-desktop.c'; fi`
+msgfmt-write-xml.o: write-xml.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(msgfmt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msgfmt-write-xml.o `test -f 'write-xml.c' || echo '$(srcdir)/'`write-xml.c
+
+msgfmt-write-xml.obj: write-xml.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(msgfmt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o msgfmt-write-xml.obj `if test -f 'write-xml.c'; then $(CYGPATH_W) 'write-xml.c'; else $(CYGPATH_W) '$(srcdir)/write-xml.c'; fi`
+
../../gettext-runtime/intl/msgfmt-hash-string.o: ../../gettext-runtime/intl/hash-string.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(msgfmt_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../gettext-runtime/intl/msgfmt-hash-string.o `test -f '../../gettext-runtime/intl/hash-string.c' || echo '$(srcdir)/'`../../gettext-runtime/intl/hash-string.c
@@ -3030,12 +3389,6 @@ xgettext-x-rst.o: x-rst.c
xgettext-x-rst.obj: x-rst.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-rst.obj `if test -f 'x-rst.c'; then $(CYGPATH_W) 'x-rst.c'; else $(CYGPATH_W) '$(srcdir)/x-rst.c'; fi`
-xgettext-x-glade.o: x-glade.c
- $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-glade.o `test -f 'x-glade.c' || echo '$(srcdir)/'`x-glade.c
-
-xgettext-x-glade.obj: x-glade.c
- $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-glade.obj `if test -f 'x-glade.c'; then $(CYGPATH_W) 'x-glade.c'; else $(CYGPATH_W) '$(srcdir)/x-glade.c'; fi`
-
xgettext-x-lua.o: x-lua.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-lua.o `test -f 'x-lua.c' || echo '$(srcdir)/'`x-lua.c
@@ -3054,18 +3407,6 @@ xgettext-x-vala.o: x-vala.c
xgettext-x-vala.obj: x-vala.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-vala.obj `if test -f 'x-vala.c'; then $(CYGPATH_W) 'x-vala.c'; else $(CYGPATH_W) '$(srcdir)/x-vala.c'; fi`
-xgettext-x-gsettings.o: x-gsettings.c
- $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-gsettings.o `test -f 'x-gsettings.c' || echo '$(srcdir)/'`x-gsettings.c
-
-xgettext-x-gsettings.obj: x-gsettings.c
- $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-gsettings.obj `if test -f 'x-gsettings.c'; then $(CYGPATH_W) 'x-gsettings.c'; else $(CYGPATH_W) '$(srcdir)/x-gsettings.c'; fi`
-
-xgettext-libexpat-compat.o: libexpat-compat.c
- $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-libexpat-compat.o `test -f 'libexpat-compat.c' || echo '$(srcdir)/'`libexpat-compat.c
-
-xgettext-libexpat-compat.obj: libexpat-compat.c
- $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-libexpat-compat.obj `if test -f 'libexpat-compat.c'; then $(CYGPATH_W) 'libexpat-compat.c'; else $(CYGPATH_W) '$(srcdir)/libexpat-compat.c'; fi`
-
xgettext-x-desktop.o: x-desktop.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xgettext_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xgettext-x-desktop.o `test -f 'x-desktop.c' || echo '$(srcdir)/'`x-desktop.c
@@ -3282,6 +3623,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+ -rm -f cldr-plural.c
-rm -f po-gram-gen.c
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
@@ -3376,6 +3718,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
uninstall-libLTLIBRARIES uninstall-local
+.PRECIOUS: Makefile
+
# No need to install libgettextsrc.a, except on AIX.
install-exec-hook: install-exec-clean
@@ -3392,6 +3736,7 @@ po-gram-gen2.h: po-gram-gen.h
$(SED) -e 's/yy/po_gram_/g' -e 's/extern /extern DLL_VARIABLE /' \
$${srcdir}po-gram-gen.h > $@-tmp && \
mv $@-tmp $@
+po-gram-gen.h: po-gram-gen.c
# Special rules for installation of auxiliary programs.
@@ -3399,6 +3744,7 @@ install-exec-local:
$(MKDIR_P) $(DESTDIR)$(pkglibdir)
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) hostname$(EXEEXT) $(DESTDIR)$(pkglibdir)/hostname$(EXEEXT)
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) urlget$(EXEEXT) $(DESTDIR)$(pkglibdir)/urlget$(EXEEXT)
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) cldr-plurals$(EXEEXT) $(DESTDIR)$(pkglibdir)/cldr-plurals$(EXEEXT)
$(INSTALL_SCRIPT) user-email $(DESTDIR)$(pkglibdir)/user-email
$(INSTALL_SCRIPT) $(srcdir)/project-id $(DESTDIR)$(pkglibdir)/project-id
@@ -3408,6 +3754,7 @@ installdirs-local:
uninstall-local:
$(RM) $(DESTDIR)$(pkglibdir)/hostname$(EXEEXT)
$(RM) $(DESTDIR)$(pkglibdir)/urlget$(EXEEXT)
+ $(RM) $(DESTDIR)$(pkglibdir)/cldr-plurals$(EXEEXT)
$(RM) $(DESTDIR)$(pkglibdir)/user-email
$(RM) $(DESTDIR)$(pkglibdir)/project-id
diff --git a/gettext-tools/src/cldr-plural-exp.c b/gettext-tools/src/cldr-plural-exp.c
new file mode 100644
index 0000000..e55b26d
--- /dev/null
+++ b/gettext-tools/src/cldr-plural-exp.c
@@ -0,0 +1,695 @@
+/* Unicode CLDR plural rule parser and converter
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "unistr.h"
+#include "xalloc.h"
+
+#include "cldr-plural-exp.h"
+#include "cldr-plural.h"
+
+/* The grammar of Unicode CLDR plural rules is defined at:
+ http://unicode.org/reports/tr35/tr35-numbers.html#Plural_rules_syntax
+
+ This implementation only supports the "preferred" form, which
+ doesn't support obsolete keywords "in", "is", "not", and "within".
+
+ Unlike gettext, CLDR allows an unsigned decimal value as an
+ operand, in addition to unsigned integers. For simplicity, we
+ treat decimal relations as if it has a constant truth value.
+
+ The implementation is largely based on the idea of Michele Locati's
+ cldr-to-gettext-plural-rules:
+ https://github.com/mlocati/cldr-to-gettext-plural-rules */
+
+void
+cldr_plural_range_free (struct cldr_plural_range_ty *range)
+{
+ if (range->start != range->end)
+ free (range->start);
+ free (range->end);
+ free (range);
+}
+
+void
+cldr_plural_range_list_free (struct cldr_plural_range_list_ty *ranges)
+{
+ while (ranges->nitems-- > 0)
+ cldr_plural_range_free (ranges->items[ranges->nitems]);
+ free (ranges->items);
+ free (ranges);
+}
+
+void
+cldr_plural_condition_free (struct cldr_plural_condition_ty *condition)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_AND
+ || condition->type == CLDR_PLURAL_CONDITION_OR)
+ {
+ cldr_plural_condition_free (condition->value.conditions[0]);
+ cldr_plural_condition_free (condition->value.conditions[1]);
+ }
+ else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
+ cldr_plural_relation_free (condition->value.relation);
+ free (condition);
+}
+
+void
+cldr_plural_relation_free (struct cldr_plural_relation_ty *relation)
+{
+ free (relation->expression);
+ cldr_plural_range_list_free (relation->ranges);
+ free (relation);
+}
+
+static void
+cldr_plural_rule_free (struct cldr_plural_rule_ty *rule)
+{
+ free (rule->name);
+ cldr_plural_condition_free (rule->condition);
+ free (rule);
+}
+
+void
+cldr_plural_rule_list_free (struct cldr_plural_rule_list_ty *rules)
+{
+ while (rules->nitems-- > 0)
+ cldr_plural_rule_free (rules->items[rules->nitems]);
+ free (rules->items);
+ free (rules);
+}
+
+struct cldr_plural_rule_list_ty *
+cldr_plural_parse (const char *input)
+{
+ struct cldr_plural_parse_args arg;
+
+ memset (&arg, 0, sizeof (struct cldr_plural_parse_args));
+ arg.cp = input;
+ arg.cp_end = input + strlen (input);
+ arg.result = XMALLOC (struct cldr_plural_rule_list_ty);
+ memset (arg.result, 0, sizeof (struct cldr_plural_rule_list_ty));
+
+ if (yyparse (&arg) != 0)
+ return NULL;
+
+ return arg.result;
+}
+
+#define OPERAND_ZERO_P(o) \
+ (((o)->type == CLDR_PLURAL_OPERAND_INTEGER \
+ && (o)->value.ival == 0) \
+ || ((o)->type == CLDR_PLURAL_OPERAND_DECIMAL \
+ && (o)->value.dval.d == 0))
+
+static enum cldr_plural_condition
+eval_relation (struct cldr_plural_relation_ty *relation)
+{
+ switch (relation->expression->operand)
+ {
+ case 'n': case 'i':
+ {
+ /* Coerce decimal values in ranges into integers. */
+ size_t i;
+ for (i = 0; i < relation->ranges->nitems; i++)
+ {
+ struct cldr_plural_range_ty *range = relation->ranges->items[i];
+ if (range->start->type == CLDR_PLURAL_OPERAND_DECIMAL)
+ {
+ int truncated = (int) range->start->value.dval.d;
+ range->start->type = CLDR_PLURAL_OPERAND_INTEGER;
+ range->start->value.ival
+ = range->start->value.dval.d == truncated
+ ? truncated : truncated + 1;
+ }
+ if (range->end->type == CLDR_PLURAL_OPERAND_DECIMAL)
+ {
+ range->end->type = CLDR_PLURAL_OPERAND_INTEGER;
+ range->end->value.ival = (int) (range->end->value.dval.d);
+ }
+ }
+ relation->expression->operand = 'i';
+ }
+ break;
+ case 'f': case 't':
+ case 'v': case 'w':
+ {
+ /* Since plural expression in gettext only supports unsigned
+ integer, turn relations whose operand is either 'f', 't',
+ 'v', or 'w' into a constant truth value. */
+ /* FIXME: check mod? */
+ size_t i;
+ for (i = 0; i < relation->ranges->nitems; i++)
+ {
+ struct cldr_plural_range_ty *range = relation->ranges->items[i];
+ if ((relation->type == CLDR_PLURAL_RELATION_EQUAL
+ && (!OPERAND_ZERO_P (range->start)
+ || !OPERAND_ZERO_P (range->end)))
+ || (relation->type == CLDR_PLURAL_RELATION_NOT_EQUAL
+ && (OPERAND_ZERO_P (range->start)
+ || OPERAND_ZERO_P (range->end))))
+ return CLDR_PLURAL_CONDITION_FALSE;
+ }
+ return CLDR_PLURAL_CONDITION_TRUE;
+ }
+ break;
+ }
+ return CLDR_PLURAL_CONDITION_RELATION;
+}
+
+static void
+eval_condition (struct cldr_plural_condition_ty *condition)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_AND)
+ {
+ eval_condition (condition->value.conditions[0]);
+ eval_condition (condition->value.conditions[1]);
+
+ if (condition->value.conditions[0]->type
+ == CLDR_PLURAL_CONDITION_FALSE
+ || condition->value.conditions[1]->type
+ == CLDR_PLURAL_CONDITION_FALSE)
+ {
+ cldr_plural_condition_free (condition->value.conditions[0]);
+ cldr_plural_condition_free (condition->value.conditions[1]);
+ condition->type = CLDR_PLURAL_CONDITION_FALSE;
+ }
+ else if (condition->value.conditions[0]->type
+ == CLDR_PLURAL_CONDITION_TRUE
+ && condition->value.conditions[1]->type
+ == CLDR_PLURAL_CONDITION_TRUE)
+ {
+ cldr_plural_condition_free (condition->value.conditions[0]);
+ cldr_plural_condition_free (condition->value.conditions[1]);
+ condition->type = CLDR_PLURAL_CONDITION_TRUE;
+ }
+ else if (condition->value.conditions[0]->type
+ == CLDR_PLURAL_CONDITION_TRUE)
+ {
+ struct cldr_plural_condition_ty *original
+ = condition->value.conditions[1];
+ cldr_plural_condition_free (condition->value.conditions[0]);
+ condition->type = condition->value.conditions[1]->type;
+ condition->value = condition->value.conditions[1]->value;
+ free (original);
+ }
+ else if (condition->value.conditions[1]->type
+ == CLDR_PLURAL_CONDITION_TRUE)
+ {
+ struct cldr_plural_condition_ty *original
+ = condition->value.conditions[0];
+ cldr_plural_condition_free (condition->value.conditions[1]);
+ condition->type = condition->value.conditions[0]->type;
+ condition->value = condition->value.conditions[0]->value;
+ free (original);
+ }
+ }
+ else if (condition->type == CLDR_PLURAL_CONDITION_OR)
+ {
+ eval_condition (condition->value.conditions[0]);
+ eval_condition (condition->value.conditions[1]);
+
+ if (condition->value.conditions[0]->type
+ == CLDR_PLURAL_CONDITION_TRUE
+ || condition->value.conditions[1]->type
+ == CLDR_PLURAL_CONDITION_TRUE)
+ {
+ cldr_plural_condition_free (condition->value.conditions[0]);
+ cldr_plural_condition_free (condition->value.conditions[1]);
+ condition->type = CLDR_PLURAL_CONDITION_TRUE;
+ }
+ else if (condition->value.conditions[0]->type
+ == CLDR_PLURAL_CONDITION_FALSE
+ && condition->value.conditions[1]->type
+ == CLDR_PLURAL_CONDITION_FALSE)
+ {
+ cldr_plural_condition_free (condition->value.conditions[0]);
+ cldr_plural_condition_free (condition->value.conditions[1]);
+ condition->type = CLDR_PLURAL_CONDITION_FALSE;
+ }
+ else if (condition->value.conditions[0]->type
+ == CLDR_PLURAL_CONDITION_FALSE)
+ {
+ struct cldr_plural_condition_ty *original
+ = condition->value.conditions[1];
+ cldr_plural_condition_free (condition->value.conditions[0]);
+ condition->type = condition->value.conditions[1]->type;
+ condition->value = condition->value.conditions[1]->value;
+ free (original);
+ }
+ else if (condition->value.conditions[1]->type
+ == CLDR_PLURAL_CONDITION_FALSE)
+ {
+ struct cldr_plural_condition_ty *original
+ = condition->value.conditions[0];
+ cldr_plural_condition_free (condition->value.conditions[1]);
+ condition->type = condition->value.conditions[0]->type;
+ condition->value = condition->value.conditions[0]->value;
+ free (original);
+ }
+ }
+ else
+ {
+ enum cldr_plural_condition value =
+ eval_relation (condition->value.relation);
+ if (value == CLDR_PLURAL_CONDITION_TRUE
+ || value == CLDR_PLURAL_CONDITION_FALSE)
+ {
+ cldr_plural_relation_free (condition->value.relation);
+ condition->type = value;
+ }
+ }
+}
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+static int
+find_largest_modulus (struct cldr_plural_condition_ty *condition)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_AND
+ || condition->type == CLDR_PLURAL_CONDITION_OR)
+ {
+ int modulus0 =
+ find_largest_modulus (condition->value.conditions[0]);
+ int modulus1 =
+ find_largest_modulus (condition->value.conditions[1]);
+ return MAX (modulus0, modulus1);
+ }
+ else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
+ return condition->value.relation->expression->mod;
+ else
+ return 0;
+}
+
+static int
+find_largest_number (struct cldr_plural_condition_ty *condition)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_AND
+ || condition->type == CLDR_PLURAL_CONDITION_OR)
+ {
+ int number0 =
+ find_largest_number (condition->value.conditions[0]);
+ int number1 =
+ find_largest_number (condition->value.conditions[1]);
+ return MAX (number0, number1);
+ }
+ else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
+ {
+ int number = 0;
+ size_t i;
+ for (i = 0; i < condition->value.relation->ranges->nitems; i++)
+ {
+ struct cldr_plural_operand_ty *operand;
+
+ operand = condition->value.relation->ranges->items[i]->end;
+ if (operand->type == CLDR_PLURAL_OPERAND_INTEGER
+ && operand->value.ival > number)
+ number = operand->value.ival;
+ else if (operand->type == CLDR_PLURAL_OPERAND_DECIMAL
+ && operand->value.dval.d > number)
+ number = (int) operand->value.dval.d;
+ }
+ return number;
+ }
+ else
+ return 0;
+}
+
+static bool
+apply_condition (struct cldr_plural_condition_ty *condition, int value)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_AND)
+ return apply_condition (condition->value.conditions[0], value)
+ && apply_condition (condition->value.conditions[1], value);
+ else if (condition->type == CLDR_PLURAL_CONDITION_OR)
+ return apply_condition (condition->value.conditions[0], value)
+ || apply_condition (condition->value.conditions[1], value);
+ else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
+ {
+ struct cldr_plural_relation_ty *relation
+ = condition->value.relation;
+ int number = value;
+ size_t i;
+
+ if (relation->expression->mod > 0)
+ number %= relation->expression->mod;
+ for (i = 0; i < relation->ranges->nitems; i++)
+ {
+ struct cldr_plural_range_ty *range = relation->ranges->items[i];
+ if (range->start->value.ival <= number
+ && number <= range->end->value.ival)
+ return relation->type == CLDR_PLURAL_RELATION_EQUAL;
+ }
+ return relation->type != CLDR_PLURAL_RELATION_EQUAL;
+ }
+ return false;
+}
+
+static void
+print_expression (struct cldr_plural_expression_ty *expression, bool space,
+ FILE *fp)
+{
+ if (expression->mod == 0)
+ fprintf (fp, "n");
+ else
+ fprintf (fp, space ? "n %% %d" : "n%%%d", expression->mod);
+}
+
+static void
+print_relation (struct cldr_plural_relation_ty *relation,
+ enum cldr_plural_condition parent, bool space,
+ FILE *fp)
+{
+ if (relation->type == CLDR_PLURAL_RELATION_EQUAL)
+ {
+ size_t i;
+ if (parent == CLDR_PLURAL_CONDITION_AND
+ && relation->ranges->nitems > 1)
+ fputc ('(', fp);
+ for (i = 0; i < relation->ranges->nitems; i++)
+ {
+ struct cldr_plural_range_ty *range = relation->ranges->items[i];
+ if (i > 0)
+ fprintf (fp, " || ");
+ if (range->start->value.ival == range->end->value.ival)
+ {
+ print_expression (relation->expression, space, fp);
+ fprintf (fp,
+ space && relation->ranges->nitems == 1
+ ? " == %d" : "==%d",
+ range->start->value.ival);
+ }
+ else if (range->start->value.ival == 0)
+ {
+ print_expression (relation->expression, false, fp);
+ fprintf (fp, "<=%d", range->end->value.ival);
+ }
+ else
+ {
+ if (parent == CLDR_PLURAL_CONDITION_OR
+ || relation->ranges->nitems > 1)
+ fputc ('(', fp);
+ print_expression (relation->expression, false, fp);
+ fprintf (fp, ">=%d", range->start->value.ival);
+ fprintf (fp, " && ");
+ print_expression (relation->expression, false, fp);
+ fprintf (fp, "<=%d", range->end->value.ival);
+ if (parent == CLDR_PLURAL_CONDITION_OR
+ || relation->ranges->nitems > 1)
+ fputc (')', fp);
+ }
+ }
+ if (parent == CLDR_PLURAL_CONDITION_AND
+ && relation->ranges->nitems > 1)
+ fputc (')', fp);
+ }
+ else
+ {
+ size_t i;
+ if (parent == CLDR_PLURAL_CONDITION_OR
+ && relation->ranges->nitems > 1)
+ fputc ('(', fp);
+ for (i = 0; i < relation->ranges->nitems; i++)
+ {
+ struct cldr_plural_range_ty *range = relation->ranges->items[i];
+ if (i > 0)
+ fprintf (fp," && ");
+ if (range->start->value.ival == range->end->value.ival)
+ {
+ print_expression (relation->expression, space, fp);
+ fprintf (fp, space && relation->ranges->nitems == 1
+ ? " != %d" : "!=%d", range->start->value.ival);
+ }
+ else if (range->start->value.ival == 0)
+ {
+ print_expression (relation->expression, false, fp);
+ fprintf (fp, ">%d", range->end->value.ival);
+ }
+ else
+ {
+ if (parent == CLDR_PLURAL_CONDITION_AND
+ || relation->ranges->nitems > 1)
+ fputc ('(', fp);
+ print_expression (relation->expression, false, fp);
+ fprintf (fp, "<%d", range->start->value.ival);
+ fprintf (fp, " || ");
+ print_expression (relation->expression, false, fp);
+ fprintf (fp, ">%d", range->end->value.ival);
+ if (parent == CLDR_PLURAL_CONDITION_AND
+ || relation->ranges->nitems > 1)
+ fputc (')', fp);
+ }
+ }
+ if (parent == CLDR_PLURAL_CONDITION_OR
+ && relation->ranges->nitems > 1)
+ fputc (')', fp);
+ }
+}
+
+static bool
+print_condition (struct cldr_plural_condition_ty *condition,
+ enum cldr_plural_condition parent, bool space,
+ FILE *fp)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_AND)
+ {
+ if (parent == CLDR_PLURAL_CONDITION_OR)
+ fputc ('(', fp);
+ print_condition (condition->value.conditions[0],
+ CLDR_PLURAL_CONDITION_AND, false,
+ fp);
+ fprintf (fp, " && ");
+ print_condition (condition->value.conditions[1],
+ CLDR_PLURAL_CONDITION_AND, false,
+ fp);
+ if (parent == CLDR_PLURAL_CONDITION_OR)
+ fputc (')', fp);
+ return true;
+ }
+ else if (condition->type == CLDR_PLURAL_CONDITION_OR)
+ {
+ if (parent == CLDR_PLURAL_CONDITION_AND)
+ fputc ('(', fp);
+ print_condition (condition->value.conditions[0],
+ CLDR_PLURAL_CONDITION_OR, false,
+ fp);
+ fprintf (fp, " || ");
+ print_condition (condition->value.conditions[1],
+ CLDR_PLURAL_CONDITION_OR, false,
+ fp);
+ if (parent == CLDR_PLURAL_CONDITION_AND)
+ fputc (')', fp);
+ return true;
+ }
+ else if (condition->type == CLDR_PLURAL_CONDITION_RELATION)
+ {
+ print_relation (condition->value.relation, parent, space, fp);
+ return true;
+ }
+ return false;
+}
+
+#define RULE_PRINTABLE_P(r) \
+ ((r)->condition->type != CLDR_PLURAL_CONDITION_TRUE \
+ && (r)->condition->type != CLDR_PLURAL_CONDITION_FALSE)
+
+/* Convert n == N into n != N. */
+static bool
+print_condition_negation (struct cldr_plural_condition_ty *condition, FILE *fp)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_RELATION
+ && condition->value.relation->type == CLDR_PLURAL_RELATION_EQUAL
+ && condition->value.relation->ranges->nitems == 1
+ && condition->value.relation->ranges->items[0]->start
+ == condition->value.relation->ranges->items[0]->end)
+ {
+ fprintf (fp, "nplurals=2; plural=(n != %d);\n",
+ condition->value.relation->ranges->items[0]->start->value.ival);
+ return true;
+ }
+ return false;
+}
+
+/* Convert n == 0,...,N into n > N. */
+static bool
+print_condition_greater (struct cldr_plural_condition_ty *condition, FILE *fp)
+{
+ if (condition->type == CLDR_PLURAL_CONDITION_RELATION
+ && condition->value.relation->type == CLDR_PLURAL_RELATION_EQUAL)
+ {
+ int last = -1;
+ size_t i;
+ for (i = 0; i < condition->value.relation->ranges->nitems; i++)
+ {
+ struct cldr_plural_range_ty *range =
+ condition->value.relation->ranges->items[i];
+ if (range->start->type != CLDR_PLURAL_OPERAND_INTEGER
+ || range->end->type != CLDR_PLURAL_OPERAND_INTEGER
+ || range->start->value.ival != last + 1)
+ break;
+ last = range->end->value.ival;
+ }
+ if (i == condition->value.relation->ranges->nitems)
+ {
+ struct cldr_plural_range_ty *range =
+ condition->value.relation->ranges->items[i - 1];
+ fprintf (fp, "nplurals=2; plural=(n > %d);\n",
+ range->end->value.ival);
+ return true;
+ }
+ }
+ return false;
+}
+
+typedef bool (*print_condition_function_ty) (struct cldr_plural_condition_ty *,
+ FILE *);
+static print_condition_function_ty print_condition_functions[] =
+ {
+ print_condition_negation,
+ print_condition_greater
+ };
+
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+
+void
+cldr_plural_rule_list_print (struct cldr_plural_rule_list_ty *rules, FILE *fp)
+{
+ size_t i;
+ size_t count;
+ size_t nplurals;
+ int modulus_max = 0;
+
+ /* Prune trivial conditions. */
+ for (i = 0; i < rules->nitems; i++)
+ {
+ struct cldr_plural_rule_ty *rule = rules->items[i];
+ eval_condition (rule->condition);
+ }
+
+ /* Omit trivial rules (e.g., the last rule for "ru") with the
+ following algorithm:
+ 1. From all rules, find the largest modulus M
+ 2. Prepare a bit vector with M elements and initialize it with zeros
+ 3. Loop over the rules, until all bits are set:
+ For each value in the range [1, M], apply a rule, and flip the
+ corresponding bit if it evaluates true */
+
+ /* Find the largest modulus. */
+ for (i = 0; i < rules->nitems; i++)
+ {
+ struct cldr_plural_rule_ty *rule = rules->items[i];
+ int modulus = find_largest_modulus (rule->condition);
+ int number = find_largest_number (rule->condition);
+ /* If the rule contains a range whose end is larger than
+ MODULUS, we can't use MODULUS as the upper bound. Skip
+ it. */
+ if (modulus >= number && modulus > modulus_max)
+ modulus_max = modulus;
+ }
+
+ if (modulus_max > 0)
+ {
+ bool *values = XNMALLOC (modulus_max, bool);
+
+ memset (values, 0, sizeof (bool) * modulus_max);
+ for (i = 0; i < rules->nitems; i++)
+ {
+ struct cldr_plural_rule_ty *rule = rules->items[i];
+ int j;
+
+ for (j = 0; j < modulus_max; j++)
+ {
+ bool result = apply_condition (rule->condition, j + 1);
+ if (result)
+ values[j] = true;
+ }
+
+ /* Check if all bits are set. Then we can omit one more rule. */
+ for (j = 0; j < modulus_max; j++)
+ if (values[j] == false)
+ break;
+ if (j == modulus_max)
+ break;
+ }
+
+ free (values);
+
+ while (i < rules->nitems)
+ cldr_plural_rule_free (rules->items[--rules->nitems]);
+ }
+
+ for (i = 0, nplurals = 1; i < rules->nitems; i++)
+ if (RULE_PRINTABLE_P (rules->items[i]))
+ nplurals++;
+
+ /* Special case when rules is empty. */
+ if (nplurals == 1)
+ {
+ fprintf (fp, "nplurals=1; plural=0;\n");
+ return;
+ }
+
+ /* If we have only one printable rule, apply some heuristics. */
+ if (nplurals == 2)
+ {
+ struct cldr_plural_condition_ty *condition;
+ size_t j;
+
+ for (j = 0; j < rules->nitems; j++)
+ if (RULE_PRINTABLE_P (rules->items[j]))
+ break;
+
+ condition = rules->items[j]->condition;
+ for (j = 0; j < SIZEOF (print_condition_functions); j++)
+ if (print_condition_functions[j] (condition, fp))
+ return;
+ }
+
+ /* If there are more printable rules, build a ternary operator. */
+ fprintf (fp, "nplurals=%zu; plural=(", nplurals);
+ for (i = 0, count = 0; i < rules->nitems; i++)
+ {
+ struct cldr_plural_rule_ty *rule = rules->items[i];
+ if (print_condition (rule->condition,
+ CLDR_PLURAL_CONDITION_FALSE,
+ nplurals == 2,
+ fp)
+ && rules->nitems > 1)
+ {
+ bool printable_left = false;
+ size_t j;
+
+ for (j = i + 1; j < rules->nitems; j++)
+ if (RULE_PRINTABLE_P (rules->items[j]))
+ printable_left = true;
+
+ if (i < rules->nitems - 1 && printable_left)
+ fprintf (fp, " ? %zu : ", count++);
+ }
+ }
+ if (rules->nitems > 1)
+ fprintf (fp, " ? %zu : %zu", count, count + 1);
+ fprintf (fp, ");\n");
+}
diff --git a/gettext-tools/src/cldr-plural-exp.h b/gettext-tools/src/cldr-plural-exp.h
new file mode 100644
index 0000000..84c8a73
--- /dev/null
+++ b/gettext-tools/src/cldr-plural-exp.h
@@ -0,0 +1,141 @@
+/* Unicode CLDR plural rule parser and converter
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _CLDR_PLURAL_EXP_H
+#define _CLDR_PLURAL_EXP_H 1
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum cldr_plural_operand
+ {
+ CLDR_PLURAL_OPERAND_INTEGER,
+ CLDR_PLURAL_OPERAND_DECIMAL
+ };
+
+struct cldr_plural_operand_ty
+{
+ enum cldr_plural_operand type;
+ union
+ {
+ int ival;
+ struct
+ {
+ double d;
+ int nfractions;
+ } dval;
+ } value;
+};
+
+enum cldr_plural_relation
+ {
+ CLDR_PLURAL_RELATION_EQUAL,
+ CLDR_PLURAL_RELATION_NOT_EQUAL
+ };
+
+struct cldr_plural_range_ty
+{
+ struct cldr_plural_operand_ty *start;
+ struct cldr_plural_operand_ty *end;
+};
+
+struct cldr_plural_range_list_ty
+{
+ struct cldr_plural_range_ty **items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+struct cldr_plural_expression_ty
+{
+ /* 'n', 'i', 'f', 't', 'v', 'w' */
+ int operand;
+
+ /* 0 if not given */
+ int mod;
+};
+
+struct cldr_plural_relation_ty
+{
+ struct cldr_plural_expression_ty *expression;
+ enum cldr_plural_relation type;
+ struct cldr_plural_range_list_ty *ranges;
+};
+
+enum cldr_plural_condition
+ {
+ CLDR_PLURAL_CONDITION_AND,
+ CLDR_PLURAL_CONDITION_OR,
+ CLDR_PLURAL_CONDITION_RELATION,
+ CLDR_PLURAL_CONDITION_TRUE,
+ CLDR_PLURAL_CONDITION_FALSE
+ };
+
+struct cldr_plural_condition_ty
+{
+ enum cldr_plural_condition type;
+ union
+ {
+ struct cldr_plural_relation_ty *relation;
+ struct cldr_plural_condition_ty *conditions[2];
+ } value;
+};
+
+struct cldr_plural_rule_ty
+{
+ char *name;
+ struct cldr_plural_condition_ty *condition;
+};
+
+struct cldr_plural_rule_list_ty
+{
+ struct cldr_plural_rule_ty **items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+struct cldr_plural_parse_args
+{
+ const char *cp;
+ const char *cp_end;
+ struct cldr_plural_rule_list_ty *result;
+};
+
+extern void
+cldr_plural_range_free (struct cldr_plural_range_ty *range);
+extern void
+cldr_plural_range_list_free (struct cldr_plural_range_list_ty *ranges);
+extern void
+cldr_plural_condition_free (struct cldr_plural_condition_ty *condition);
+extern void
+cldr_plural_relation_free (struct cldr_plural_relation_ty *relation);
+
+extern struct cldr_plural_rule_list_ty *
+cldr_plural_parse (const char *input);
+extern void
+cldr_plural_rule_list_free (struct cldr_plural_rule_list_ty *rules);
+extern void
+cldr_plural_rule_list_print (struct cldr_plural_rule_list_ty *rules, FILE *fp);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CLDR_PLURAL_EXP_H */
diff --git a/gettext-tools/src/cldr-plural.c b/gettext-tools/src/cldr-plural.c
new file mode 100644
index 0000000..d0fc4f8
--- /dev/null
+++ b/gettext-tools/src/cldr-plural.c
@@ -0,0 +1,2013 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "3.0.4"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 2
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 19 "cldr-plural.y" /* yacc.c:339 */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "unistr.h"
+#include "xalloc.h"
+
+#include "cldr-plural-exp.h"
+#include "cldr-plural.h"
+
+/* Prototypes for local functions. */
+static int yylex (YYSTYPE *lval, struct cldr_plural_parse_args *arg);
+static void yyerror (struct cldr_plural_parse_args *arg, const char *str);
+
+/* Allocation of expressions. */
+
+static struct cldr_plural_rule_ty *
+new_rule (char *name, struct cldr_plural_condition_ty *condition)
+{
+ struct cldr_plural_rule_ty *result =
+ XMALLOC (struct cldr_plural_rule_ty);
+ result->name = name;
+ result->condition = condition;
+ return result;
+}
+
+static struct cldr_plural_condition_ty *
+new_leaf_condition (struct cldr_plural_relation_ty *relation)
+{
+ struct cldr_plural_condition_ty *result =
+ XMALLOC (struct cldr_plural_condition_ty);
+ result->type = CLDR_PLURAL_CONDITION_RELATION;
+ result->value.relation = relation;
+ return result;
+}
+
+static struct cldr_plural_condition_ty *
+new_branch_condition (enum cldr_plural_condition type,
+ struct cldr_plural_condition_ty *condition0,
+ struct cldr_plural_condition_ty *condition1)
+{
+ struct cldr_plural_condition_ty *result =
+ XMALLOC (struct cldr_plural_condition_ty);
+ result->type = type;
+ result->value.conditions[0] = condition0;
+ result->value.conditions[1] = condition1;
+ return result;
+}
+
+static struct cldr_plural_relation_ty *
+new_relation (struct cldr_plural_expression_ty *expression,
+ enum cldr_plural_relation type,
+ struct cldr_plural_range_list_ty *ranges)
+{
+ struct cldr_plural_relation_ty *result =
+ XMALLOC (struct cldr_plural_relation_ty);
+ result->expression = expression;
+ result->type = type;
+ result->ranges = ranges;
+ return result;
+}
+
+static struct cldr_plural_expression_ty *
+new_expression (int operand, int mod)
+{
+ struct cldr_plural_expression_ty *result =
+ XMALLOC (struct cldr_plural_expression_ty);
+ result->operand = operand;
+ result->mod = mod;
+ return result;
+}
+
+static struct cldr_plural_range_list_ty *
+add_range (struct cldr_plural_range_list_ty *ranges,
+ struct cldr_plural_range_ty *range)
+{
+ if (ranges->nitems == ranges->nitems_max)
+ {
+ ranges->nitems_max = ranges->nitems_max * 2 + 1;
+ ranges->items = xrealloc (ranges->items,
+ sizeof (struct cldr_plural_range_ty *)
+ * ranges->nitems_max);
+ }
+ ranges->items[ranges->nitems++] = range;
+ return ranges;
+}
+
+static struct cldr_plural_range_ty *
+new_range (struct cldr_plural_operand_ty *start,
+ struct cldr_plural_operand_ty *end)
+{
+ struct cldr_plural_range_ty *result =
+ XMALLOC (struct cldr_plural_range_ty);
+ result->start = start;
+ result->end = end;
+ return result;
+}
+
+#line 170 "cldr-plural.c" /* yacc.c:339 */
+
+# ifndef YY_NULLPTR
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULLPTR nullptr
+# else
+# define YY_NULLPTR 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "y.tab.h". */
+#ifndef YY_YY_CLDR_PLURAL_H_INCLUDED
+# define YY_YY_CLDR_PLURAL_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ AND = 258,
+ OR = 259,
+ RANGE = 260,
+ ELLIPSIS = 261,
+ OTHER = 262,
+ AT_INTEGER = 263,
+ AT_DECIMAL = 264,
+ KEYWORD = 265,
+ INTEGER = 266,
+ DECIMAL = 267,
+ OPERAND = 268
+ };
+#endif
+/* Tokens. */
+#define AND 258
+#define OR 259
+#define RANGE 260
+#define ELLIPSIS 261
+#define OTHER 262
+#define AT_INTEGER 263
+#define AT_DECIMAL 264
+#define KEYWORD 265
+#define INTEGER 266
+#define DECIMAL 267
+#define OPERAND 268
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 127 "cldr-plural.y" /* yacc.c:355 */
+
+ char *sval;
+ struct cldr_plural_condition_ty *cval;
+ struct cldr_plural_relation_ty *lval;
+ struct cldr_plural_expression_ty *eval;
+ struct cldr_plural_range_ty *gval;
+ struct cldr_plural_operand_ty *oval;
+ struct cldr_plural_range_list_ty *rval;
+ int ival;
+
+#line 247 "cldr-plural.c" /* yacc.c:355 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int yyparse (struct cldr_plural_parse_args *arg);
+
+#endif /* !YY_YY_CLDR_PLURAL_H_INCLUDED */
+
+/* Copy the second part of user declarations. */
+
+#line 263 "cldr-plural.c" /* yacc.c:358 */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (0)
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 7
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 55
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 21
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 17
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 32
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 52
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 268
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 17, 2, 2, 2, 18, 2, 2,
+ 2, 2, 2, 2, 19, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 15, 14,
+ 2, 16, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 20, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13
+};
+
+#if YYDEBUG
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 159, 159, 160, 163, 176, 179, 183, 189, 193,
+ 201, 205, 211, 215, 221, 228, 234, 238, 244, 251,
+ 254, 255, 258, 259, 262, 264, 265, 267, 268, 271,
+ 273, 275, 277
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "AND", "OR", "RANGE", "ELLIPSIS",
+ "OTHER", "AT_INTEGER", "AT_DECIMAL", "KEYWORD", "INTEGER", "DECIMAL",
+ "OPERAND", "';'", "':'", "'='", "'!'", "'%'", "','", "'~'", "$accept",
+ "rules", "rule", "condition", "and_condition", "relation", "expression",
+ "range_list", "range_or_integer", "range", "samples", "at_integer",
+ "at_decimal", "sample_list", "sample_list1", "sample_ellipsis",
+ "sample_range", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 59, 58, 61, 33, 37, 44,
+ 126
+};
+# endif
+
+#define YYPACT_NINF -20
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-20)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int8 yypact[] =
+{
+ 3, -11, -7, 0, -20, 4, -2, -20, 3, -9,
+ -20, 8, 2, 1, 15, -20, -1, -20, 5, 6,
+ -20, 9, -20, -9, -20, 10, -2, -20, -2, 11,
+ 11, 12, 7, -5, -20, -20, -20, 15, -20, 19,
+ 13, -20, -20, 13, -20, -20, -20, -20, 16, 11,
+ -20, -20
+};
+
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 0, 0, 0, 2, 20, 0, 1, 0, 0,
+ 5, 22, 12, 20, 6, 8, 0, 3, 31, 29,
+ 21, 27, 25, 0, 19, 0, 0, 4, 0, 0,
+ 0, 0, 0, 0, 24, 23, 13, 7, 9, 17,
+ 10, 14, 16, 11, 32, 30, 28, 26, 0, 0,
+ 18, 15
+};
+
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -20, -20, 21, -20, 14, 17, -20, 18, -19, -20,
+ 20, -20, -20, 23, -20, -20, 22
+};
+
+ /* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 3, 4, 13, 14, 15, 16, 40, 41, 42,
+ 10, 11, 24, 20, 21, 34, 22
+};
+
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_uint8 yytable[] =
+{
+ 7, 46, 18, 19, 5, 26, 18, 19, 6, 9,
+ 1, 12, 9, 2, 8, 29, 30, 23, 28, 45,
+ 25, 36, 39, 44, 48, 31, 32, 50, 33, 17,
+ 51, 0, 49, 27, 0, 0, 0, 0, 0, 0,
+ 37, 0, 0, 0, 0, 38, 35, 0, 43, 0,
+ 0, 0, 0, 0, 0, 47
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 0, 6, 11, 12, 15, 4, 11, 12, 15, 8,
+ 7, 13, 8, 10, 14, 16, 17, 9, 3, 12,
+ 18, 11, 11, 11, 5, 20, 20, 11, 19, 8,
+ 49, -1, 19, 13, -1, -1, -1, -1, -1, -1,
+ 26, -1, -1, -1, -1, 28, 23, -1, 30, -1,
+ -1, -1, -1, -1, -1, 33
+};
+
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 7, 10, 22, 23, 15, 15, 0, 14, 8,
+ 31, 32, 13, 24, 25, 26, 27, 23, 11, 12,
+ 34, 35, 37, 9, 33, 18, 4, 31, 3, 16,
+ 17, 20, 20, 19, 36, 34, 11, 25, 26, 11,
+ 28, 29, 30, 28, 11, 12, 6, 37, 5, 19,
+ 11, 29
+};
+
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 21, 22, 22, 23, 23, 24, 24, 25, 25,
+ 26, 26, 27, 27, 28, 28, 29, 29, 30, 31,
+ 32, 32, 33, 33, 34, 35, 35, 36, 36, 37,
+ 37, 37, 37
+};
+
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 3, 4, 3, 1, 3, 1, 3,
+ 3, 3, 1, 3, 1, 3, 1, 1, 3, 2,
+ 0, 2, 0, 2, 2, 1, 3, 0, 2, 1,
+ 3, 1, 3
+};
+
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (arg, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (0)
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, arg); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct cldr_plural_parse_args *arg)
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ YYUSE (arg);
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct cldr_plural_parse_args *arg)
+{
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, arg);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, struct cldr_plural_parse_args *arg)
+{
+ unsigned long int yylno = yyrline[yyrule];
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , arg);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule, arg); \
+} while (0)
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULLPTR;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct cldr_plural_parse_args *arg)
+{
+ YYUSE (yyvaluep);
+ YYUSE (arg);
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ switch (yytype)
+ {
+ case 10: /* KEYWORD */
+#line 138 "cldr-plural.y" /* yacc.c:1257 */
+ { free (((*yyvaluep).sval)); }
+#line 1121 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 11: /* INTEGER */
+#line 143 "cldr-plural.y" /* yacc.c:1257 */
+ { free (((*yyvaluep).oval)); }
+#line 1127 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 12: /* DECIMAL */
+#line 143 "cldr-plural.y" /* yacc.c:1257 */
+ { free (((*yyvaluep).oval)); }
+#line 1133 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 13: /* OPERAND */
+#line 145 "cldr-plural.y" /* yacc.c:1257 */
+ { }
+#line 1139 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 24: /* condition */
+#line 139 "cldr-plural.y" /* yacc.c:1257 */
+ { cldr_plural_condition_free (((*yyvaluep).cval)); }
+#line 1145 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 25: /* and_condition */
+#line 139 "cldr-plural.y" /* yacc.c:1257 */
+ { cldr_plural_condition_free (((*yyvaluep).cval)); }
+#line 1151 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 26: /* relation */
+#line 140 "cldr-plural.y" /* yacc.c:1257 */
+ { cldr_plural_relation_free (((*yyvaluep).lval)); }
+#line 1157 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 27: /* expression */
+#line 141 "cldr-plural.y" /* yacc.c:1257 */
+ { free (((*yyvaluep).eval)); }
+#line 1163 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 28: /* range_list */
+#line 144 "cldr-plural.y" /* yacc.c:1257 */
+ { cldr_plural_range_list_free (((*yyvaluep).rval)); }
+#line 1169 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 29: /* range_or_integer */
+#line 142 "cldr-plural.y" /* yacc.c:1257 */
+ { cldr_plural_range_free (((*yyvaluep).gval)); }
+#line 1175 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+ case 30: /* range */
+#line 142 "cldr-plural.y" /* yacc.c:1257 */
+ { cldr_plural_range_free (((*yyvaluep).gval)); }
+#line 1181 "cldr-plural.c" /* yacc.c:1257 */
+ break;
+
+
+ default:
+ break;
+ }
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+int
+yyparse (struct cldr_plural_parse_args *arg)
+{
+/* The lookahead symbol. */
+int yychar;
+
+
+/* The semantic value of the lookahead symbol. */
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+YY_INITIAL_VALUE (static YYSTYPE yyval_default;)
+YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default);
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = yylex (&yylval, arg);
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ '$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
+#line 164 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ struct cldr_plural_rule_ty *rule = new_rule ((yyvsp[-3].sval), (yyvsp[-1].cval));
+ struct cldr_plural_rule_list_ty *result = arg->result;
+ if (result->nitems == result->nitems_max)
+ {
+ result->nitems_max = result->nitems_max * 2 + 1;
+ result->items = xrealloc (result->items,
+ sizeof (struct cldr_plural_rule_ty *)
+ * result->nitems_max);
+ }
+ result->items[result->nitems++] = rule;
+ }
+#line 1460 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 6:
+#line 180 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.cval) = (yyvsp[0].cval);
+ }
+#line 1468 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 7:
+#line 184 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.cval) = new_branch_condition (CLDR_PLURAL_CONDITION_OR, (yyvsp[-2].cval), (yyvsp[0].cval));
+ }
+#line 1476 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 8:
+#line 190 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.cval) = new_leaf_condition ((yyvsp[0].lval));
+ }
+#line 1484 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 9:
+#line 194 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.cval) = new_branch_condition (CLDR_PLURAL_CONDITION_AND,
+ (yyvsp[-2].cval),
+ new_leaf_condition ((yyvsp[0].lval)));
+ }
+#line 1494 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 10:
+#line 202 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.lval) = new_relation ((yyvsp[-2].eval), CLDR_PLURAL_RELATION_EQUAL, (yyvsp[0].rval));
+ }
+#line 1502 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 11:
+#line 206 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.lval) = new_relation ((yyvsp[-2].eval), CLDR_PLURAL_RELATION_NOT_EQUAL, (yyvsp[0].rval));
+ }
+#line 1510 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 12:
+#line 212 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.eval) = new_expression ((yyvsp[0].ival), 0);
+ }
+#line 1518 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 13:
+#line 216 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.eval) = new_expression ((yyvsp[-2].ival), (yyvsp[0].oval)->value.ival);
+ }
+#line 1526 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 14:
+#line 222 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ struct cldr_plural_range_list_ty *ranges =
+ XMALLOC (struct cldr_plural_range_list_ty);
+ memset (ranges, 0, sizeof (struct cldr_plural_range_list_ty));
+ (yyval.rval) = add_range (ranges, (yyvsp[0].gval));
+ }
+#line 1537 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 15:
+#line 229 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.rval) = add_range ((yyvsp[-2].rval), (yyvsp[0].gval));
+ }
+#line 1545 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 16:
+#line 235 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.gval) = (yyvsp[0].gval);
+ }
+#line 1553 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 17:
+#line 239 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.gval) = new_range ((yyvsp[0].oval), (yyvsp[0].oval));
+ }
+#line 1561 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 18:
+#line 245 "cldr-plural.y" /* yacc.c:1646 */
+ {
+ (yyval.gval) = new_range ((yyvsp[-2].oval), (yyvsp[0].oval));
+ }
+#line 1569 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 29:
+#line 272 "cldr-plural.y" /* yacc.c:1646 */
+ { free ((yyvsp[0].oval)); }
+#line 1575 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 30:
+#line 274 "cldr-plural.y" /* yacc.c:1646 */
+ { free ((yyvsp[-2].oval)); free ((yyvsp[0].oval)); }
+#line 1581 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 31:
+#line 276 "cldr-plural.y" /* yacc.c:1646 */
+ { free ((yyvsp[0].oval)); }
+#line 1587 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+ case 32:
+#line 278 "cldr-plural.y" /* yacc.c:1646 */
+ { free ((yyvsp[-2].oval)); free ((yyvsp[0].oval)); }
+#line 1593 "cldr-plural.c" /* yacc.c:1646 */
+ break;
+
+
+#line 1597 "cldr-plural.c" /* yacc.c:1646 */
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now 'shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (arg, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (arg, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, arg);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, arg);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (arg, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, arg);
+ }
+ /* Do not reclaim the symbols of the rule whose action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, arg);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ return yyresult;
+}
+#line 281 "cldr-plural.y" /* yacc.c:1906 */
+
+
+static int
+yylex (YYSTYPE *lval, struct cldr_plural_parse_args *arg)
+{
+ const char *exp = arg->cp;
+ ucs4_t uc;
+ int length;
+ int result;
+ static char *buffer;
+ static size_t bufmax;
+ size_t bufpos;
+
+ while (1)
+ {
+ if (exp[0] == '\0')
+ {
+ arg->cp = exp;
+ return YYEOF;
+ }
+
+ if (exp[0] != ' ' && exp[0] != '\t')
+ break;
+
+ ++exp;
+ }
+
+ length = u8_mbtouc (&uc, (const uint8_t *) exp, arg->cp_end - exp);
+ if (uc == 0x2026)
+ {
+ arg->cp = exp + length;
+ return ELLIPSIS;
+ }
+ else if (strncmp ("...", exp, 3) == 0)
+ {
+ arg->cp = exp + 3;
+ return ELLIPSIS;
+ }
+ else if (strncmp ("..", exp, 2) == 0)
+ {
+ arg->cp = exp + 2;
+ return RANGE;
+ }
+ else if (strncmp ("other", exp, 5) == 0)
+ {
+ arg->cp = exp + 5;
+ return OTHER;
+ }
+ else if (strncmp ("@integer", exp, 8) == 0)
+ {
+ arg->cp = exp + 8;
+ return AT_INTEGER;
+ }
+ else if (strncmp ("@decimal", exp, 8) == 0)
+ {
+ arg->cp = exp + 8;
+ return AT_DECIMAL;
+ }
+
+ result = *exp++;
+ switch (result)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ unsigned long int ival = result - '0';
+
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ ival *= 10;
+ ival += exp[0] - '0';
+ ++exp;
+ }
+
+ lval->oval = XMALLOC (struct cldr_plural_operand_ty);
+ if (exp[0] == '.' && exp[1] >= '0' && exp[1] <= '9')
+ {
+ double dval = ival;
+ int denominator = 10, nfractions = 0;
+ ++exp;
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ dval += (exp[0] - '0') / (double) denominator;
+ denominator *= 10;
+ ++nfractions;
+ ++exp;
+ }
+ lval->oval->type = CLDR_PLURAL_OPERAND_DECIMAL;
+ lval->oval->value.dval.d = dval;
+ lval->oval->value.dval.nfractions = nfractions;
+ result = DECIMAL;
+ }
+ else
+ {
+ lval->oval->type = CLDR_PLURAL_OPERAND_INTEGER;
+ lval->oval->value.ival = ival;
+ result = INTEGER;
+ }
+ }
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+ case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
+ case 'v': case 'w': case 'x': case 'y': case 'z':
+ bufpos = 0;
+ for (;;)
+ {
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos++] = result;
+ result = *exp;
+ switch (result)
+ {
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ ++exp;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos] = '\0';
+
+ /* Operands. */
+ if (bufpos == 1)
+ {
+ switch (buffer[0])
+ {
+ case 'n': case 'i': case 'f': case 't': case 'v': case 'w':
+ arg->cp = exp;
+ lval->ival = buffer[0];
+ return OPERAND;
+ default:
+ break;
+ }
+ }
+
+ /* Keywords. */
+ if (strcmp (buffer, "and") == 0)
+ {
+ arg->cp = exp;
+ return AND;
+ }
+ else if (strcmp (buffer, "or") == 0)
+ {
+ arg->cp = exp;
+ return OR;
+ }
+
+ lval->sval = xstrdup (buffer);
+ result = KEYWORD;
+ break;
+ case '!':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ result = '!';
+ }
+ else
+ result = YYERRCODE;
+ break;
+ default:
+ break;
+ }
+
+ arg->cp = exp;
+
+ return result;
+}
+
+static void
+yyerror (struct cldr_plural_parse_args *arg, char const *s)
+{
+ fprintf (stderr, "%s\n", s);
+}
diff --git a/gettext-tools/src/cldr-plural.h b/gettext-tools/src/cldr-plural.h
new file mode 100644
index 0000000..4122af5
--- /dev/null
+++ b/gettext-tools/src/cldr-plural.h
@@ -0,0 +1,102 @@
+/* A Bison parser, made by GNU Bison 3.0.4. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_YY_CLDR_PLURAL_H_INCLUDED
+# define YY_YY_CLDR_PLURAL_H_INCLUDED
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ enum yytokentype
+ {
+ AND = 258,
+ OR = 259,
+ RANGE = 260,
+ ELLIPSIS = 261,
+ OTHER = 262,
+ AT_INTEGER = 263,
+ AT_DECIMAL = 264,
+ KEYWORD = 265,
+ INTEGER = 266,
+ DECIMAL = 267,
+ OPERAND = 268
+ };
+#endif
+/* Tokens. */
+#define AND 258
+#define OR 259
+#define RANGE 260
+#define ELLIPSIS 261
+#define OTHER 262
+#define AT_INTEGER 263
+#define AT_DECIMAL 264
+#define KEYWORD 265
+#define INTEGER 266
+#define DECIMAL 267
+#define OPERAND 268
+
+/* Value type. */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+
+union YYSTYPE
+{
+#line 127 "cldr-plural.y" /* yacc.c:1909 */
+
+ char *sval;
+ struct cldr_plural_condition_ty *cval;
+ struct cldr_plural_relation_ty *lval;
+ struct cldr_plural_expression_ty *eval;
+ struct cldr_plural_range_ty *gval;
+ struct cldr_plural_operand_ty *oval;
+ struct cldr_plural_range_list_ty *rval;
+ int ival;
+
+#line 91 "cldr-plural.h" /* yacc.c:1909 */
+};
+
+typedef union YYSTYPE YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+int yyparse (struct cldr_plural_parse_args *arg);
+
+#endif /* !YY_YY_CLDR_PLURAL_H_INCLUDED */
diff --git a/gettext-tools/src/cldr-plural.y b/gettext-tools/src/cldr-plural.y
new file mode 100644
index 0000000..d3128cd
--- /dev/null
+++ b/gettext-tools/src/cldr-plural.y
@@ -0,0 +1,469 @@
+/* Unicode CLDR plural rule parser and converter
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+%{
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "unistr.h"
+#include "xalloc.h"
+
+#include "cldr-plural-exp.h"
+#include "cldr-plural.h"
+
+/* Prototypes for local functions. */
+static int yylex (YYSTYPE *lval, struct cldr_plural_parse_args *arg);
+static void yyerror (struct cldr_plural_parse_args *arg, const char *str);
+
+/* Allocation of expressions. */
+
+static struct cldr_plural_rule_ty *
+new_rule (char *name, struct cldr_plural_condition_ty *condition)
+{
+ struct cldr_plural_rule_ty *result =
+ XMALLOC (struct cldr_plural_rule_ty);
+ result->name = name;
+ result->condition = condition;
+ return result;
+}
+
+static struct cldr_plural_condition_ty *
+new_leaf_condition (struct cldr_plural_relation_ty *relation)
+{
+ struct cldr_plural_condition_ty *result =
+ XMALLOC (struct cldr_plural_condition_ty);
+ result->type = CLDR_PLURAL_CONDITION_RELATION;
+ result->value.relation = relation;
+ return result;
+}
+
+static struct cldr_plural_condition_ty *
+new_branch_condition (enum cldr_plural_condition type,
+ struct cldr_plural_condition_ty *condition0,
+ struct cldr_plural_condition_ty *condition1)
+{
+ struct cldr_plural_condition_ty *result =
+ XMALLOC (struct cldr_plural_condition_ty);
+ result->type = type;
+ result->value.conditions[0] = condition0;
+ result->value.conditions[1] = condition1;
+ return result;
+}
+
+static struct cldr_plural_relation_ty *
+new_relation (struct cldr_plural_expression_ty *expression,
+ enum cldr_plural_relation type,
+ struct cldr_plural_range_list_ty *ranges)
+{
+ struct cldr_plural_relation_ty *result =
+ XMALLOC (struct cldr_plural_relation_ty);
+ result->expression = expression;
+ result->type = type;
+ result->ranges = ranges;
+ return result;
+}
+
+static struct cldr_plural_expression_ty *
+new_expression (int operand, int mod)
+{
+ struct cldr_plural_expression_ty *result =
+ XMALLOC (struct cldr_plural_expression_ty);
+ result->operand = operand;
+ result->mod = mod;
+ return result;
+}
+
+static struct cldr_plural_range_list_ty *
+add_range (struct cldr_plural_range_list_ty *ranges,
+ struct cldr_plural_range_ty *range)
+{
+ if (ranges->nitems == ranges->nitems_max)
+ {
+ ranges->nitems_max = ranges->nitems_max * 2 + 1;
+ ranges->items = xrealloc (ranges->items,
+ sizeof (struct cldr_plural_range_ty *)
+ * ranges->nitems_max);
+ }
+ ranges->items[ranges->nitems++] = range;
+ return ranges;
+}
+
+static struct cldr_plural_range_ty *
+new_range (struct cldr_plural_operand_ty *start,
+ struct cldr_plural_operand_ty *end)
+{
+ struct cldr_plural_range_ty *result =
+ XMALLOC (struct cldr_plural_range_ty);
+ result->start = start;
+ result->end = end;
+ return result;
+}
+%}
+
+%parse-param {struct cldr_plural_parse_args *arg}
+%lex-param {struct cldr_plural_parse_args *arg}
+%define api.pure full
+
+%union {
+ char *sval;
+ struct cldr_plural_condition_ty *cval;
+ struct cldr_plural_relation_ty *lval;
+ struct cldr_plural_expression_ty *eval;
+ struct cldr_plural_range_ty *gval;
+ struct cldr_plural_operand_ty *oval;
+ struct cldr_plural_range_list_ty *rval;
+ int ival;
+}
+
+%destructor { free ($$); } <sval>
+%destructor { cldr_plural_condition_free ($$); } <cval>
+%destructor { cldr_plural_relation_free ($$); } <lval>
+%destructor { free ($$); } <eval>
+%destructor { cldr_plural_range_free ($$); } <gval>
+%destructor { free ($$); } <oval>
+%destructor { cldr_plural_range_list_free ($$); } <rval>
+%destructor { } <ival>
+
+%token AND OR RANGE ELLIPSIS OTHER AT_INTEGER AT_DECIMAL
+%token<sval> KEYWORD
+%token<oval> INTEGER DECIMAL
+%token<ival> OPERAND
+%type<cval> condition and_condition
+%type<lval> relation
+%type<eval> expression
+%type<gval> range range_or_integer
+%type<rval> range_list
+
+%%
+
+rules: rule
+ | rules ';' rule
+ ;
+
+rule: KEYWORD ':' condition samples
+ {
+ struct cldr_plural_rule_ty *rule = new_rule ($1, $3);
+ struct cldr_plural_rule_list_ty *result = arg->result;
+ if (result->nitems == result->nitems_max)
+ {
+ result->nitems_max = result->nitems_max * 2 + 1;
+ result->items = xrealloc (result->items,
+ sizeof (struct cldr_plural_rule_ty *)
+ * result->nitems_max);
+ }
+ result->items[result->nitems++] = rule;
+ }
+ | OTHER ':' samples
+ ;
+
+condition: and_condition
+ {
+ $$ = $1;
+ }
+ | condition OR and_condition
+ {
+ $$ = new_branch_condition (CLDR_PLURAL_CONDITION_OR, $1, $3);
+ }
+ ;
+
+and_condition: relation
+ {
+ $$ = new_leaf_condition ($1);
+ }
+ | and_condition AND relation
+ {
+ $$ = new_branch_condition (CLDR_PLURAL_CONDITION_AND,
+ $1,
+ new_leaf_condition ($3));
+ }
+ ;
+
+relation: expression '=' range_list
+ {
+ $$ = new_relation ($1, CLDR_PLURAL_RELATION_EQUAL, $3);
+ }
+ | expression '!' range_list
+ {
+ $$ = new_relation ($1, CLDR_PLURAL_RELATION_NOT_EQUAL, $3);
+ }
+ ;
+
+expression: OPERAND
+ {
+ $$ = new_expression ($1, 0);
+ }
+ | OPERAND '%' INTEGER
+ {
+ $$ = new_expression ($1, $3->value.ival);
+ }
+ ;
+
+range_list: range_or_integer
+ {
+ struct cldr_plural_range_list_ty *ranges =
+ XMALLOC (struct cldr_plural_range_list_ty);
+ memset (ranges, 0, sizeof (struct cldr_plural_range_list_ty));
+ $$ = add_range (ranges, $1);
+ }
+ | range_list ',' range_or_integer
+ {
+ $$ = add_range ($1, $3);
+ }
+ ;
+
+range_or_integer: range
+ {
+ $$ = $1;
+ }
+ | INTEGER
+ {
+ $$ = new_range ($1, $1);
+ }
+ ;
+
+range: INTEGER RANGE INTEGER
+ {
+ $$ = new_range ($1, $3);
+ }
+ ;
+
+/* FIXME: collect samples */
+samples: at_integer at_decimal
+ ;
+
+at_integer: %empty
+ | AT_INTEGER sample_list
+ ;
+
+at_decimal: %empty
+ | AT_DECIMAL sample_list
+ ;
+
+sample_list: sample_list1 sample_ellipsis
+ ;
+sample_list1: sample_range
+ | sample_list1 ',' sample_range
+ ;
+sample_ellipsis: %empty
+ | ',' ELLIPSIS
+ ;
+
+sample_range: DECIMAL
+ { free ($1); }
+ | DECIMAL '~' DECIMAL
+ { free ($1); free ($3); }
+ | INTEGER
+ { free ($1); }
+ | INTEGER '~' INTEGER
+ { free ($1); free ($3); }
+ ;
+
+%%
+
+static int
+yylex (YYSTYPE *lval, struct cldr_plural_parse_args *arg)
+{
+ const char *exp = arg->cp;
+ ucs4_t uc;
+ int length;
+ int result;
+ static char *buffer;
+ static size_t bufmax;
+ size_t bufpos;
+
+ while (1)
+ {
+ if (exp[0] == '\0')
+ {
+ arg->cp = exp;
+ return YYEOF;
+ }
+
+ if (exp[0] != ' ' && exp[0] != '\t')
+ break;
+
+ ++exp;
+ }
+
+ length = u8_mbtouc (&uc, (const uint8_t *) exp, arg->cp_end - exp);
+ if (uc == 0x2026)
+ {
+ arg->cp = exp + length;
+ return ELLIPSIS;
+ }
+ else if (strncmp ("...", exp, 3) == 0)
+ {
+ arg->cp = exp + 3;
+ return ELLIPSIS;
+ }
+ else if (strncmp ("..", exp, 2) == 0)
+ {
+ arg->cp = exp + 2;
+ return RANGE;
+ }
+ else if (strncmp ("other", exp, 5) == 0)
+ {
+ arg->cp = exp + 5;
+ return OTHER;
+ }
+ else if (strncmp ("@integer", exp, 8) == 0)
+ {
+ arg->cp = exp + 8;
+ return AT_INTEGER;
+ }
+ else if (strncmp ("@decimal", exp, 8) == 0)
+ {
+ arg->cp = exp + 8;
+ return AT_DECIMAL;
+ }
+
+ result = *exp++;
+ switch (result)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ unsigned long int ival = result - '0';
+
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ ival *= 10;
+ ival += exp[0] - '0';
+ ++exp;
+ }
+
+ lval->oval = XMALLOC (struct cldr_plural_operand_ty);
+ if (exp[0] == '.' && exp[1] >= '0' && exp[1] <= '9')
+ {
+ double dval = ival;
+ int denominator = 10, nfractions = 0;
+ ++exp;
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ dval += (exp[0] - '0') / (double) denominator;
+ denominator *= 10;
+ ++nfractions;
+ ++exp;
+ }
+ lval->oval->type = CLDR_PLURAL_OPERAND_DECIMAL;
+ lval->oval->value.dval.d = dval;
+ lval->oval->value.dval.nfractions = nfractions;
+ result = DECIMAL;
+ }
+ else
+ {
+ lval->oval->type = CLDR_PLURAL_OPERAND_INTEGER;
+ lval->oval->value.ival = ival;
+ result = INTEGER;
+ }
+ }
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+ case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
+ case 'v': case 'w': case 'x': case 'y': case 'z':
+ bufpos = 0;
+ for (;;)
+ {
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos++] = result;
+ result = *exp;
+ switch (result)
+ {
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'x': case 'y':
+ case 'z':
+ ++exp;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos] = '\0';
+
+ /* Operands. */
+ if (bufpos == 1)
+ {
+ switch (buffer[0])
+ {
+ case 'n': case 'i': case 'f': case 't': case 'v': case 'w':
+ arg->cp = exp;
+ lval->ival = buffer[0];
+ return OPERAND;
+ default:
+ break;
+ }
+ }
+
+ /* Keywords. */
+ if (strcmp (buffer, "and") == 0)
+ {
+ arg->cp = exp;
+ return AND;
+ }
+ else if (strcmp (buffer, "or") == 0)
+ {
+ arg->cp = exp;
+ return OR;
+ }
+
+ lval->sval = xstrdup (buffer);
+ result = KEYWORD;
+ break;
+ case '!':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ result = '!';
+ }
+ else
+ result = YYERRCODE;
+ break;
+ default:
+ break;
+ }
+
+ arg->cp = exp;
+
+ return result;
+}
+
+static void
+yyerror (struct cldr_plural_parse_args *arg, char const *s)
+{
+ fprintf (stderr, "%s\n", s);
+}
diff --git a/gettext-tools/src/cldr-plurals.c b/gettext-tools/src/cldr-plurals.c
new file mode 100644
index 0000000..abbd0c2
--- /dev/null
+++ b/gettext-tools/src/cldr-plurals.c
@@ -0,0 +1,370 @@
+/* Unicode CLDR plural rule parser and converter
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "basename.h"
+#include "cldr-plural-exp.h"
+#include "c-ctype.h"
+#include <errno.h>
+#include <error.h>
+#include <getopt.h>
+#include "gettext.h"
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <locale.h>
+#include "progname.h"
+#include "propername.h"
+#include "relocatable.h"
+#include <stdlib.h>
+#include <string.h>
+#include "xalloc.h"
+
+#define _(s) gettext(s)
+
+
+static char *
+extract_rules (FILE *fp,
+ const char *real_filename, const char *logical_filename,
+ const char *locale)
+{
+ xmlDocPtr doc;
+ xmlNodePtr node, n;
+ size_t locale_length;
+ char *buffer = NULL, *p;
+ size_t bufmax = 0;
+ size_t buflen = 0;
+
+ doc = xmlReadFd (fileno (fp), logical_filename, NULL,
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOERROR
+ | XML_PARSE_NOBLANKS);
+ if (doc == NULL)
+ error (EXIT_FAILURE, 0, _("memory exhausted"));
+
+ node = xmlDocGetRootElement (doc);
+ if (!node || !xmlStrEqual (node->name, BAD_CAST "supplementalData"))
+ {
+ error_at_line (0, 0,
+ logical_filename,
+ xmlGetLineNo (node),
+ _("\
+The root element must be <%s>"),
+ "supplementalData");
+ goto out;
+ }
+
+ for (n = node->children; n; n = n->next)
+ {
+ if (n->type == XML_ELEMENT_NODE
+ && xmlStrEqual (n->name, BAD_CAST "plurals"))
+ break;
+ }
+ if (!n)
+ {
+ error (0, 0, _("The element <%s> does not contain a <%s> element"),
+ "supplementalData", "plurals");
+ goto out;
+ }
+
+ locale_length = strlen (locale);
+ for (n = n->children; n; n = n->next)
+ {
+ xmlChar *locales;
+ xmlChar *cp;
+ xmlNodePtr n2;
+ bool found = false;
+
+ if (n->type != XML_ELEMENT_NODE
+ || !xmlStrEqual (n->name, BAD_CAST "pluralRules"))
+ continue;
+
+ if (!xmlHasProp (n, BAD_CAST "locales"))
+ {
+ error_at_line (0, 0,
+ logical_filename,
+ xmlGetLineNo (n),
+ _("\
+The element <%s> does not have attribute <%s>"),
+ "pluralRules", "locales");
+ continue;
+ }
+
+ cp = locales = xmlGetProp (n, BAD_CAST "locales");
+ while (*cp != '\0')
+ {
+ while (c_isspace (*cp))
+ cp++;
+ if (xmlStrncmp (cp, BAD_CAST locale, locale_length) == 0
+ && (*(cp + locale_length) == '\0'
+ || c_isspace (*(cp + locale_length))))
+ {
+ found = true;
+ break;
+ }
+ while (*cp && !c_isspace (*cp))
+ cp++;
+ }
+ xmlFree (locales);
+
+ if (!found)
+ continue;
+
+ for (n2 = n->children; n2; n2 = n2->next)
+ {
+ xmlChar *count;
+ xmlChar *content;
+ size_t length;
+
+ if (n2->type != XML_ELEMENT_NODE
+ || !xmlStrEqual (n2->name, BAD_CAST "pluralRule"))
+ continue;
+
+ if (!xmlHasProp (n2, BAD_CAST "count"))
+ {
+ error_at_line (0, 0,
+ logical_filename,
+ xmlGetLineNo (n2),
+ _("\
+The element <%s> does not have attribute <%s>"),
+ "pluralRule", "count");
+ break;
+ }
+
+ count = xmlGetProp (n2, BAD_CAST "count");
+ content = xmlNodeGetContent (n2);
+ length = xmlStrlen (count) + strlen (": ")
+ + xmlStrlen (content) + strlen ("; ");
+
+ if (buflen + length + 1 > bufmax)
+ {
+ bufmax *= 2;
+ if (bufmax < buflen + length + 1)
+ bufmax = buflen + length + 1;
+ buffer = (char *) xrealloc (buffer, bufmax);
+ }
+
+ sprintf (buffer + buflen, "%s: %s; ", count, content);
+ xmlFree (count);
+ xmlFree (content);
+
+ buflen += length;
+ }
+ }
+
+ if (buffer)
+ {
+ /* Scrub the last semicolon, if any. */
+ p = strrchr (buffer, ';');
+ if (p)
+ *p = '\0';
+ }
+
+ out:
+ xmlFreeDoc (doc);
+ return buffer;
+}
+
+/* Display usage information and exit. */
+static void
+usage (int status)
+{
+ if (status != EXIT_SUCCESS)
+ fprintf (stderr, _("Try '%s --help' for more information.\n"),
+ program_name);
+ else
+ {
+ printf (_("\
+Usage: %s [OPTION...] [LOCALE RULES]...\n\
+"), program_name);
+ printf ("\n");
+ /* xgettext: no-wrap */
+ printf (_("\
+Extract or convert Unicode CLDR plural rules.\n\
+\n\
+If both LOCALE and RULES are specified, it reads CLDR plural rules for\n\
+LOCALE from RULES and print them in a form suitable for gettext use.\n\
+If no argument is given, it reads CLDR plural rules from the standard input.\n\
+"));
+ printf ("\n");
+ /* xgettext: no-wrap */
+ printf (_("\
+Mandatory arguments to long options are mandatory for short options too.\n\
+Similarly for optional arguments.\n\
+"));
+ printf ("\n");
+ printf (_("\
+ -c, --cldr print plural rules in the CLDR format\n"));
+ printf (_("\
+ -h, --help display this help and exit\n"));
+ printf (_("\
+ -V, --version output version information and exit\n"));
+ printf ("\n");
+ /* TRANSLATORS: The placeholder indicates the bug-reporting address
+ for this package. Please add _another line_ saying
+ "Report translation bugs to <...>\n" with the address for translation
+ bugs (typically your translation team's web or email address). */
+ fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"),
+ stdout);
+ }
+ exit (status);
+}
+
+/* Long options. */
+static const struct option long_options[] =
+{
+ { "cldr", no_argument, NULL, 'c' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+};
+
+int
+main (int argc, char **argv)
+{
+ bool opt_cldr_format = false;
+ bool do_help = false;
+ bool do_version = false;
+ int optchar;
+
+ /* Set program name for messages. */
+ set_program_name (argv[0]);
+
+#ifdef HAVE_SETLOCALE
+ /* Set locale via LC_ALL. */
+ setlocale (LC_ALL, "");
+#endif
+
+ /* Set the text message domain. */
+ bindtextdomain (PACKAGE, relocate (LOCALEDIR));
+ bindtextdomain ("bison-runtime", relocate (BISON_LOCALEDIR));
+ textdomain (PACKAGE);
+
+ while ((optchar = getopt_long (argc, argv, "chV", long_options, NULL)) != EOF)
+ switch (optchar)
+ {
+ case '\0': /* Long option. */
+ break;
+
+ case 'c':
+ opt_cldr_format = true;
+ break;
+
+ case 'h':
+ do_help = true;
+ break;
+
+ case 'V':
+ do_version = true;
+ break;
+
+ default:
+ usage (EXIT_FAILURE);
+ /* NOTREACHED */
+ }
+
+ /* Version information requested. */
+ if (do_version)
+ {
+ printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
+ /* xgettext: no-wrap */
+ printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
+This is free software: you are free to change and redistribute it.\n\
+There is NO WARRANTY, to the extent permitted by law.\n\
+"),
+ "2015");
+ printf (_("Written by %s.\n"), proper_name ("Daiki Ueno"));
+ exit (EXIT_SUCCESS);
+ }
+
+ /* Help is requested. */
+ if (do_help)
+ usage (EXIT_SUCCESS);
+
+ if (argc == optind + 2)
+ {
+ /* Two arguments: Read CLDR rules from a file. */
+ const char *locale = argv[optind];
+ const char *logical_filename = argv[optind + 1];
+ char *extracted_rules;
+ FILE *fp;
+
+ LIBXML_TEST_VERSION
+
+ fp = fopen (logical_filename, "r");
+ if (fp == NULL)
+ error (1, 0, _("%s cannot be read"), logical_filename);
+
+ extracted_rules = extract_rules (fp, logical_filename, logical_filename,
+ locale);
+ fclose (fp);
+ if (extracted_rules == NULL)
+ error (1, 0, _("cannot extract rules for %s"), locale);
+
+ if (opt_cldr_format)
+ printf ("%s\n", extracted_rules);
+ else
+ {
+ struct cldr_plural_rule_list_ty *result;
+
+ result = cldr_plural_parse (extracted_rules);
+ if (result == NULL)
+ error (1, 0, _("cannot parse CLDR rule"));
+
+ cldr_plural_rule_list_print (result, stdout);
+ cldr_plural_rule_list_free (result);
+ }
+ free (extracted_rules);
+ }
+ else if (argc == optind)
+ {
+ /* No argument: Read CLDR rules from standard input. */
+ char *line = NULL;
+ size_t line_size = 0;
+ for (;;)
+ {
+ int line_len;
+ struct cldr_plural_rule_list_ty *result;
+
+ line_len = getline (&line, &line_size, stdin);
+ if (line_len < 0)
+ break;
+ if (line_len > 0 && line[line_len - 1] == '\n')
+ line[--line_len] = '\0';
+
+ result = cldr_plural_parse (line);
+ if (result)
+ {
+ cldr_plural_rule_list_print (result, stdout);
+ cldr_plural_rule_list_free (result);
+ }
+ }
+
+ free (line);
+ }
+ else
+ {
+ error (1, 0, _("extra operand %s"), argv[optind]);
+ }
+
+ return 0;
+}
diff --git a/gettext-tools/src/color.c b/gettext-tools/src/color.c
index 47daf00..b372b2e 100644
--- a/gettext-tools/src/color.c
+++ b/gettext-tools/src/color.c
@@ -1,5 +1,5 @@
/* Color and styling handling.
- Copyright (C) 2006-2008 Free Software Foundation, Inc.
+ Copyright (C) 2006-2008, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2006.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/color.h b/gettext-tools/src/color.h
index f47f40f..25211ac 100644
--- a/gettext-tools/src/color.h
+++ b/gettext-tools/src/color.h
@@ -1,5 +1,5 @@
/* Color and styling handling.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2006.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/dir-list.c b/gettext-tools/src/dir-list.c
index ee46d05..2ab0fd2 100644
--- a/gettext-tools/src/dir-list.c
+++ b/gettext-tools/src/dir-list.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1996, 1998, 2000-2002, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1998, 2000-2002, 2006, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/dir-list.h b/gettext-tools/src/dir-list.h
index 6ce32bb..954e017 100644
--- a/gettext-tools/src/dir-list.h
+++ b/gettext-tools/src/dir-list.h
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1996, 1998, 2000-2003 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1998, 2000-2003, 2015 Free Software Foundation,
+ Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/file-list.c b/gettext-tools/src/file-list.c
index 2ee983d..c60f6a0 100644
--- a/gettext-tools/src/file-list.c
+++ b/gettext-tools/src/file-list.c
@@ -1,5 +1,6 @@
/* Reading file lists.
- Copyright (C) 1995-1998, 2000-2002, 2007 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2002, 2007, 2015 Free Software
+ Foundation, Inc.
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
diff --git a/gettext-tools/src/file-list.h b/gettext-tools/src/file-list.h
index 9665fbe..a43f6a4 100644
--- a/gettext-tools/src/file-list.h
+++ b/gettext-tools/src/file-list.h
@@ -1,5 +1,5 @@
/* Reading file lists.
- Copyright (C) 2001-2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/filter-quote.c b/gettext-tools/src/filter-quote.c
index 2e9b7dc..25ac391 100644
--- a/gettext-tools/src/filter-quote.c
+++ b/gettext-tools/src/filter-quote.c
@@ -1,5 +1,5 @@
/* Convert ASCII quotations to Unicode quotations.
- Copyright (C) 2014 Free Software Foundation, Inc.
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
Written by Daiki Ueno <ueno@gnu.org>, 2014.
This program is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@
/* Specification. */
#include "filters.h"
+#include "quote.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@@ -30,28 +31,83 @@
#define BOLD_START "\x1b[1m"
#define BOLD_END "\x1b[0m"
+struct result
+{
+ char *output;
+ char *offset;
+ bool bold;
+};
+
+static void
+convert_quote_callback (char quote, const char *quoted, size_t quoted_length,
+ void *data)
+{
+ struct result *result = data;
+
+ switch (quote)
+ {
+ case '\0':
+ memcpy (result->offset, quoted, quoted_length);
+ result->offset += quoted_length;
+ break;
+
+ case '"':
+ /* U+201C: LEFT DOUBLE QUOTATION MARK */
+ memcpy (result->offset, "\xe2\x80\x9c", 3);
+ result->offset += 3;
+ if (result->bold)
+ {
+ memcpy (result->offset, BOLD_START, 4);
+ result->offset += 4;
+ }
+ memcpy (result->offset, quoted, quoted_length);
+ result->offset += quoted_length;
+ if (result->bold)
+ {
+ memcpy (result->offset, BOLD_END, 4);
+ result->offset += 4;
+ }
+ /* U+201D: RIGHT DOUBLE QUOTATION MARK */
+ memcpy (result->offset, "\xe2\x80\x9d", 3);
+ result->offset += 3;
+ break;
+
+ case '\'':
+ /* U+2018: LEFT SINGLE QUOTATION MARK */
+ memcpy (result->offset, "\xe2\x80\x98", 3);
+ result->offset += 3;
+ if (result->bold)
+ {
+ memcpy (result->offset, BOLD_START, 4);
+ result->offset += 4;
+ }
+ memcpy (result->offset, quoted, quoted_length);
+ result->offset += quoted_length;
+ if (result->bold)
+ {
+ memcpy (result->offset, BOLD_END, 4);
+ result->offset += 4;
+ }
+ /* U+2019: RIGHT SINGLE QUOTATION MARK */
+ memcpy (result->offset, "\xe2\x80\x99", 3);
+ result->offset += 3;
+ break;
+ }
+}
+
/* This is a direct translation of po/quot.sed and po/boldquot.sed. */
static void
convert_ascii_quote_to_unicode (const char *input, size_t input_len,
char **output_p, size_t *output_len_p,
bool bold)
{
- const char *start, *end, *p;
- char *output, *r;
- bool state;
+ const char *p;
size_t quote_count;
-
- start = input;
- end = &input[input_len - 1];
-
- /* True if we have seen a character which could be an opening
- quotation mark. Note that we can't determine if it is really an
- opening quotation mark until we see a closing quotation mark. */
- state = false;
+ struct result result;
/* Count the number of quotation characters. */
quote_count = 0;
- for (p = start; p <= end; p++)
+ for (p = input; p < input + input_len; p++)
{
size_t len;
@@ -65,144 +121,16 @@ convert_ascii_quote_to_unicode (const char *input, size_t input_len,
}
/* Large enough. */
- r = output = XNMALLOC (input_len - quote_count
- + (bold ? 7 : 3) * quote_count + 1,
- char);
-
-#undef COPY_SEEN
-#define COPY_SEEN \
- do \
- { \
- memcpy (r, start, p - start); \
- r += p - start; \
- start = p; \
- } \
- while (0)
-
- for (p = start; p <= end; p++)
- {
- switch (*p)
- {
- case '"':
- if (state)
- {
- if (*start == '"')
- {
- if (p > start + 1)
- {
- /* U+201C: LEFT DOUBLE QUOTATION MARK */
- memcpy (r, "\xe2\x80\x9c", 3);
- r += 3;
- if (bold)
- {
- memcpy (r, BOLD_START, 4);
- r += 4;
- }
- memcpy (r, start + 1, p - start - 1);
- r += p - start - 1;
- if (bold)
- {
- memcpy (r, BOLD_END, 4);
- r += 4;
- }
- /* U+201D: RIGHT DOUBLE QUOTATION MARK */
- memcpy (r, "\xe2\x80\x9d", 3);
- r += 3;
- }
- else
- {
- /* Consider "" as "". */
- memcpy (r, "\"\"", 2);
- r += 2;
- }
- start = p + 1;
- state = false;
- }
- }
- else
- {
- COPY_SEEN;
- state = true;
- }
- break;
-
- case '`':
- if (state)
- {
- if (*start == '`')
- COPY_SEEN;
- }
- else
- {
- COPY_SEEN;
- state = true;
- }
- break;
-
- case '\'':
- if (state)
- {
- if (/* `...' */
- *start == '`'
- /* '...', where:
- - The left quote is preceded by a space, and the
- right quote is followed by a space.
- - The left quote is preceded by a space, and the
- right quote is at the end of line.
- - The left quote is at the beginning of the line, and
- the right quote is followed by a space.
- */
- || (*start == '\''
- && (((start > input && *(start - 1) == ' ')
- && (p == end || *(p + 1) == '\n' || *(p + 1) == ' '))
- || ((start == input || *(start - 1) == '\n')
- && p < end && *(p + 1) == ' '))))
- {
- /* U+2018: LEFT SINGLE QUOTATION MARK */
- memcpy (r, "\xe2\x80\x98", 3);
- r += 3;
- if (bold)
- {
- memcpy (r, BOLD_START, 4);
- r += 4;
- }
- memcpy (r, start + 1, p - start - 1);
- r += p - start - 1;
- if (bold)
- {
- memcpy (r, BOLD_END, 4);
- r += 4;
- }
- /* U+2019: RIGHT SINGLE QUOTATION MARK */
- memcpy (r, "\xe2\x80\x99", 3);
- r += 3;
- start = p + 1;
- }
- else
- COPY_SEEN;
- state = false;
- }
- else if (p == input || *(p - 1) == '\n' || *(p - 1) == ' ')
- {
- COPY_SEEN;
- state = true;
- }
- break;
- }
- }
+ result.output = XNMALLOC (input_len - quote_count
+ + (bold ? 7 : 3) * quote_count + 1,
+ char);
+ result.offset = result.output;
+ result.bold = bold;
-#undef COPY_SEEN
-
- /* Copy the rest to R. */
- if (p > start)
- {
- memcpy (r, start, p - start);
- r += p - start;
- }
- *r = '\0';
+ scan_quoted (input, input_len, convert_quote_callback, &result);
- *output_p = output;
- *output_len_p = r - output;
+ *output_p = result.output;
+ *output_len_p = result.offset - result.output;
}
void
diff --git a/gettext-tools/src/filter-sr-latin.c b/gettext-tools/src/filter-sr-latin.c
index d6dbd95..ea5457f 100644
--- a/gettext-tools/src/filter-sr-latin.c
+++ b/gettext-tools/src/filter-sr-latin.c
@@ -1,5 +1,5 @@
/* Recode Serbian text from Cyrillic to Latin script.
- Copyright (C) 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2006-2007, 2009, 2015 Free Software Foundation, Inc.
Written by Danilo Šegan <danilo@gnome.org>, 2006,
and Bruno Haible <bruno@clisp.org>, 2006.
diff --git a/gettext-tools/src/format-awk.c b/gettext-tools/src/format-awk.c
index 91251c4..efaa2d7 100644
--- a/gettext-tools/src/format-awk.c
+++ b/gettext-tools/src/format-awk.c
@@ -1,5 +1,6 @@
/* awk format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-boost.c b/gettext-tools/src/format-boost.c
index 688ba97..a390078 100644
--- a/gettext-tools/src/format-boost.c
+++ b/gettext-tools/src/format-boost.c
@@ -1,5 +1,6 @@
/* Boost format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2006.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-c-parse.h b/gettext-tools/src/format-c-parse.h
index bacfcef..4918fd5 100644
--- a/gettext-tools/src/format-c-parse.h
+++ b/gettext-tools/src/format-c-parse.h
@@ -1,5 +1,6 @@
/* Parsing C format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009-2010 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009-2010, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-c.c b/gettext-tools/src/format-c.c
index d88f8de..b2dc9dc 100644
--- a/gettext-tools/src/format-c.c
+++ b/gettext-tools/src/format-c.c
@@ -1,5 +1,6 @@
/* C format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-csharp.c b/gettext-tools/src/format-csharp.c
index feb3fcf..1f5e715 100644
--- a/gettext-tools/src/format-csharp.c
+++ b/gettext-tools/src/format-csharp.c
@@ -1,5 +1,6 @@
/* C# 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 <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-elisp.c b/gettext-tools/src/format-elisp.c
index 2e43fde..2eb99ac 100644
--- a/gettext-tools/src/format-elisp.c
+++ b/gettext-tools/src/format-elisp.c
@@ -1,5 +1,6 @@
/* Emacs Lisp format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-gcc-internal.c b/gettext-tools/src/format-gcc-internal.c
index 7057628..f5ca5e8 100644
--- a/gettext-tools/src/format-gcc-internal.c
+++ b/gettext-tools/src/format-gcc-internal.c
@@ -1,5 +1,5 @@
/* GCC internal format strings.
- Copyright (C) 2003-2009 Free Software Foundation, Inc.
+ Copyright (C) 2003-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-gfc-internal.c b/gettext-tools/src/format-gfc-internal.c
index 4fbbc66..1932c17 100644
--- a/gettext-tools/src/format-gfc-internal.c
+++ b/gettext-tools/src/format-gfc-internal.c
@@ -1,5 +1,5 @@
/* GFC (GNU Fortran Compiler) internal format strings.
- Copyright (C) 2003-2009 Free Software Foundation, Inc.
+ Copyright (C) 2003-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2009.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-invalid.h b/gettext-tools/src/format-invalid.h
index 3ad60aa..ed6c501 100644
--- a/gettext-tools/src/format-invalid.h
+++ b/gettext-tools/src/format-invalid.h
@@ -1,5 +1,5 @@
/* Common reasons that make a format string invalid.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-java.c b/gettext-tools/src/format-java.c
index 5196835..a69c84f 100644
--- a/gettext-tools/src/format-java.c
+++ b/gettext-tools/src/format-java.c
@@ -1,5 +1,6 @@
/* Java format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-javascript.c b/gettext-tools/src/format-javascript.c
index d76a8d7..fa39e20 100644
--- a/gettext-tools/src/format-javascript.c
+++ b/gettext-tools/src/format-javascript.c
@@ -1,5 +1,6 @@
/* JavaScript format strings.
- Copyright (C) 2001-2004, 2006-2009, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2009, 2013, 2015 Free Software
+ Foundation, Inc.
Written by Andreas Stricker <andy@knitter.ch>, 2010.
It's based on python format module from Bruno Haible.
diff --git a/gettext-tools/src/format-kde-kuit.c b/gettext-tools/src/format-kde-kuit.c
new file mode 100644
index 0000000..128d05d
--- /dev/null
+++ b/gettext-tools/src/format-kde-kuit.c
@@ -0,0 +1,411 @@
+/* KUIT (KDE User Interface Text) format strings.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+ Written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "format.h"
+#include "unistr.h"
+#include "xalloc.h"
+#include "xvasprintf.h"
+#include "gettext.h"
+
+#if IN_LIBGETTEXTPO
+/* Use included markup parser to avoid extra dependency from
+ libgettextpo to libxml2. */
+# ifndef FORMAT_KDE_KUIT_FALLBACK_MARKUP
+# define FORMAT_KDE_KUIT_USE_FALLBACK_MARKUP 1
+# endif
+#else
+# define FORMAT_KDE_KUIT_USE_LIBXML2 1
+#endif
+
+#if FORMAT_KDE_KUIT_USE_LIBXML2
+# include <libxml/parser.h>
+#elif FORMAT_KDE_KUIT_USE_FALLBACK_MARKUP
+# include "markup.h"
+#endif
+
+
+#define _(str) gettext (str)
+
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+
+
+/* KUIT (KDE User Interface Text) is an XML-like markup which augments
+ translatable strings 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 a well-formed XML document,
+ except that it allows '&' as a Qt accelerator marker and '%' as a
+ format directive. */
+
+struct spec
+{
+ /* A format string descriptor returned from formatstring_kde.parse. */
+ void *base;
+};
+
+#define XML_NS "https://www.gnu.org/s/gettext/kde"
+
+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, excluding NameStartChar:
+ 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 an XML reference. */
+static bool
+is_reference (const char *input)
+{
+ const char *str = input;
+ const char *str_limit = str + strlen (input);
+ ucs4_t uc;
+ int i;
+
+ str += u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
+ assert (uc == '&');
+
+ 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;
+}
+
+
+static void *
+format_parse (const char *format, bool translated, char *fdi,
+ char **invalid_reason)
+{
+ struct spec spec;
+ struct spec *result;
+ const char *str;
+ const char *str_limit;
+ size_t amp_count;
+ char *buffer, *bp;
+
+ spec.base = NULL;
+
+ /* Preprocess the input, putting the content in a <gt:kuit> element. */
+ str = format;
+ str_limit = str + strlen (format);
+
+ 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)
+ + strlen ("<gt:kuit xmlns:gt=\"" XML_NS "\"></gt:kuit>")
+ + 1);
+ *buffer = '\0';
+
+ bp = buffer;
+ bp = stpcpy (bp, "<gt:kuit xmlns:gt=\"" XML_NS "\">");
+ 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;
+ }
+ stpcpy (bp, "</gt:kuit>");
+
+#if FORMAT_KDE_KUIT_USE_LIBXML2
+ {
+ xmlDocPtr doc;
+
+ doc = xmlReadMemory (buffer, strlen (buffer), "", NULL,
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOERROR
+ | XML_PARSE_NOBLANKS);
+ if (doc == NULL)
+ {
+ xmlError *err = xmlGetLastError ();
+ *invalid_reason =
+ xasprintf (_("error while parsing: %s"),
+ err->message);
+ free (buffer);
+ xmlFreeDoc (doc);
+ return NULL;
+ }
+
+ free (buffer);
+ xmlFreeDoc (doc);
+ }
+#elif FORMAT_KDE_KUIT_FALLBACK_MARKUP
+ {
+ markup_parser_ty parser;
+ markup_parse_context_ty *context;
+
+ memset (&parser, 0, sizeof (markup_parser_ty));
+ context = markup_parse_context_new (&parser, 0, NULL);
+ if (!markup_parse_context_parse (context, buffer, strlen (buffer)))
+ {
+ *invalid_reason =
+ xasprintf (_("error while parsing: %s"),
+ markup_parse_context_get_error (context));
+ free (buffer);
+ markup_parse_context_free (context);
+ return NULL;
+ }
+
+ if (!markup_parse_context_end_parse (context))
+ {
+ *invalid_reason =
+ xasprintf (_("error while parsing: %s"),
+ markup_parse_context_get_error (context));
+ free (buffer);
+ markup_parse_context_free (context);
+ return NULL;
+ }
+
+ free (buffer);
+ markup_parse_context_free (context);
+ }
+#else
+ /* No support for XML. */
+#endif
+
+ spec.base = formatstring_kde.parse (format, translated, fdi, invalid_reason);
+ if (spec.base == NULL)
+ return NULL;
+
+ result = XMALLOC (struct spec);
+ *result = spec;
+ return result;
+}
+
+static void
+format_free (void *descr)
+{
+ struct spec *spec = descr;
+ formatstring_kde.free (spec->base);
+ free (spec);
+}
+
+static int
+format_get_number_of_directives (void *descr)
+{
+ struct spec *spec = descr;
+ return formatstring_kde.get_number_of_directives (spec->base);
+}
+
+static bool
+format_check (void *msgid_descr, void *msgstr_descr, bool equality,
+ formatstring_error_logger_t error_logger,
+ const char *pretty_msgid, const char *pretty_msgstr)
+{
+ struct spec *msgid_spec = msgid_descr;
+ struct spec *msgstr_spec = msgstr_descr;
+
+ return formatstring_kde.check (msgid_spec->base, msgstr_spec->base, equality,
+ error_logger,
+ pretty_msgid, pretty_msgstr);
+}
+
+struct formatstring_parser formatstring_kde_kuit =
+{
+ format_parse,
+ format_free,
+ format_get_number_of_directives,
+ NULL,
+ format_check
+};
+
+
+#ifdef TEST
+
+/* Test program: Print the argument list specification returned by
+ format_parse for strings read from standard input. */
+
+#include <stdio.h>
+
+static void
+format_print (void *descr)
+{
+ struct spec *spec = (struct spec *) descr;
+ unsigned int last;
+ unsigned int i;
+
+ if (spec == NULL)
+ {
+ printf ("INVALID");
+ return;
+ }
+
+ printf ("(");
+ last = 1;
+ for (i = 0; i < spec->numbered_arg_count; i++)
+ {
+ unsigned int number = spec->numbered[i].number;
+
+ if (i > 0)
+ printf (" ");
+ if (number < last)
+ abort ();
+ for (; last < number; last++)
+ printf ("_ ");
+ last = number + 1;
+ }
+ printf (")");
+}
+
+int
+main ()
+{
+ for (;;)
+ {
+ char *line = NULL;
+ size_t line_size = 0;
+ int line_len;
+ char *invalid_reason;
+ void *descr;
+
+ line_len = getline (&line, &line_size, stdin);
+ if (line_len < 0)
+ break;
+ if (line_len > 0 && line[line_len - 1] == '\n')
+ line[--line_len] = '\0';
+
+ invalid_reason = NULL;
+ descr = format_parse (line, false, NULL, &invalid_reason);
+
+ format_print (descr);
+ printf ("\n");
+ if (descr == NULL)
+ printf ("%s\n", invalid_reason);
+
+ free (invalid_reason);
+ free (line);
+ }
+
+ return 0;
+}
+
+/*
+ * For Emacs M-x compile
+ * Local Variables:
+ * compile-command: "/bin/sh ../libtool --tag=CC --mode=link gcc -o a.out -static -O -g -Wall -I.. -I../gnulib-lib -I../intl -DHAVE_CONFIG_H -DTEST format-kde-kuit.c ../gnulib-lib/libgettextlib.la"
+ * End:
+ */
+
+#endif /* TEST */
diff --git a/gettext-tools/src/format-kde.c b/gettext-tools/src/format-kde.c
index 90e887d..6848781 100644
--- a/gettext-tools/src/format-kde.c
+++ b/gettext-tools/src/format-kde.c
@@ -1,5 +1,6 @@
/* 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 <bruno@clisp.org>, 2007.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-librep.c b/gettext-tools/src/format-librep.c
index 05185ad..9c15aea 100644
--- a/gettext-tools/src/format-librep.c
+++ b/gettext-tools/src/format-librep.c
@@ -1,5 +1,6 @@
/* librep format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-lisp.c b/gettext-tools/src/format-lisp.c
index 7d423a5..2f9949e 100644
--- a/gettext-tools/src/format-lisp.c
+++ b/gettext-tools/src/format-lisp.c
@@ -1,5 +1,6 @@
/* Lisp format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-lua.c b/gettext-tools/src/format-lua.c
index 272def4..6a68b82 100644
--- a/gettext-tools/src/format-lua.c
+++ b/gettext-tools/src/format-lua.c
@@ -1,5 +1,5 @@
/* Lua format strings.
- Copyright (C) 2012 Free Software Foundation, Inc.
+ Copyright (C) 2012, 2015 Free Software Foundation, Inc.
Written by Ľubomír Remák <lubomirr@lubomirr.eu>, 2012.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-pascal.c b/gettext-tools/src/format-pascal.c
index 7e0c505..b443ba7 100644
--- a/gettext-tools/src/format-pascal.c
+++ b/gettext-tools/src/format-pascal.c
@@ -1,5 +1,6 @@
/* Object Pascal format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009-2010 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009-2010, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-perl-brace.c b/gettext-tools/src/format-perl-brace.c
index 3ab05ce..64a0663 100644
--- a/gettext-tools/src/format-perl-brace.c
+++ b/gettext-tools/src/format-perl-brace.c
@@ -1,5 +1,5 @@
/* Perl brace format strings.
- Copyright (C) 2004, 2006-2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006-2007, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-perl.c b/gettext-tools/src/format-perl.c
index 730d190..af741e9 100644
--- a/gettext-tools/src/format-perl.c
+++ b/gettext-tools/src/format-perl.c
@@ -1,5 +1,6 @@
/* Perl format strings.
- Copyright (C) 2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006-2007, 2009, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-php.c b/gettext-tools/src/format-php.c
index 5dd6d7f..ebaaa33 100644
--- a/gettext-tools/src/format-php.c
+++ b/gettext-tools/src/format-php.c
@@ -1,5 +1,6 @@
/* PHP format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-python-brace.c b/gettext-tools/src/format-python-brace.c
index 141d3df..4323230 100644
--- a/gettext-tools/src/format-python-brace.c
+++ b/gettext-tools/src/format-python-brace.c
@@ -1,5 +1,6 @@
/* Python brace format strings.
- Copyright (C) 2004, 2006-2007, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006-2007, 2013, 2015 Free Software Foundation,
+ Inc.
Written by Daiki Ueno <ueno@gnu.org>, 2013.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-python.c b/gettext-tools/src/format-python.c
index d6a1338..8af3c12 100644
--- a/gettext-tools/src/format-python.c
+++ b/gettext-tools/src/format-python.c
@@ -1,5 +1,6 @@
/* Python format strings.
- Copyright (C) 2001-2004, 2006-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2009, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-qt-plural.c b/gettext-tools/src/format-qt-plural.c
index 5301d42..fafe6ab 100644
--- a/gettext-tools/src/format-qt-plural.c
+++ b/gettext-tools/src/format-qt-plural.c
@@ -1,5 +1,6 @@
/* Qt plural 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 <bruno@clisp.org>, 2009.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-qt.c b/gettext-tools/src/format-qt.c
index 3f759a2..abdc4da 100644
--- a/gettext-tools/src/format-qt.c
+++ b/gettext-tools/src/format-qt.c
@@ -1,5 +1,6 @@
/* Qt 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 <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-scheme.c b/gettext-tools/src/format-scheme.c
index 02c6182..adc1cc6 100644
--- a/gettext-tools/src/format-scheme.c
+++ b/gettext-tools/src/format-scheme.c
@@ -1,5 +1,5 @@
/* Scheme format strings.
- Copyright (C) 2001-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-sh.c b/gettext-tools/src/format-sh.c
index b796fcd..eeeec04 100644
--- a/gettext-tools/src/format-sh.c
+++ b/gettext-tools/src/format-sh.c
@@ -1,5 +1,6 @@
/* Shell 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 <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-tcl.c b/gettext-tools/src/format-tcl.c
index e338c6d..1254b2d 100644
--- a/gettext-tools/src/format-tcl.c
+++ b/gettext-tools/src/format-tcl.c
@@ -1,5 +1,6 @@
/* Tcl format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format-ycp.c b/gettext-tools/src/format-ycp.c
index 762a5d7..398b644 100644
--- a/gettext-tools/src/format-ycp.c
+++ b/gettext-tools/src/format-ycp.c
@@ -1,5 +1,6 @@
/* YCP and Smalltalk format strings.
- Copyright (C) 2001-2004, 2006-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/format.c b/gettext-tools/src/format.c
index c73ad7d..69b1f47 100644
--- a/gettext-tools/src/format.c
+++ b/gettext-tools/src/format.c
@@ -1,5 +1,5 @@
/* Format strings.
- Copyright (C) 2001-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
@@ -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..b311e48 100644
--- a/gettext-tools/src/format.h
+++ b/gettext-tools/src/format.h
@@ -1,5 +1,5 @@
/* Format strings.
- Copyright (C) 2001-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
@@ -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/gnu/gettext/DumpResource.java b/gettext-tools/src/gnu/gettext/DumpResource.java
index 77c6e01..40a1d92 100644
--- a/gettext-tools/src/gnu/gettext/DumpResource.java
+++ b/gettext-tools/src/gnu/gettext/DumpResource.java
@@ -1,5 +1,5 @@
/* GNU gettext for Java
- * Copyright (C) 2001-2003, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2001-2003, 2007, 2015 Free Software Foundation, Inc.
*
* 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
diff --git a/gettext-tools/src/gnu/gettext/GetURL.java b/gettext-tools/src/gnu/gettext/GetURL.java
index f42ccc4..9faac6d 100644
--- a/gettext-tools/src/gnu/gettext/GetURL.java
+++ b/gettext-tools/src/gnu/gettext/GetURL.java
@@ -1,5 +1,5 @@
/* Fetch an URL's contents.
- * Copyright (C) 2001, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2008, 2015 Free Software Foundation, Inc.
*
* 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
diff --git a/gettext-tools/src/hostname.c b/gettext-tools/src/hostname.c
index a7032b3..684aa4e 100644
--- a/gettext-tools/src/hostname.c
+++ b/gettext-tools/src/hostname.c
@@ -1,5 +1,6 @@
/* Display hostname in various forms.
- Copyright (C) 2001-2003, 2006-2007, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006-2007, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/its.c b/gettext-tools/src/its.c
new file mode 100644
index 0000000..ce4880a
--- /dev/null
+++ b/gettext-tools/src/its.c
@@ -0,0 +1,1946 @@
+/* Internationalization Tag Set (ITS) handling
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* Specification. */
+#include "its.h"
+
+#include <assert.h>
+#include <errno.h>
+#include "error.h"
+#include "gettext.h"
+#include "hash.h"
+#include <stdint.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xmlwriter.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <stdlib.h>
+#include "trim.h"
+#include "xalloc.h"
+#include "xvasprintf.h"
+
+#define _(str) gettext (str)
+
+/* The Internationalization Tag Set (ITS) 2.0 standard is available at:
+ http://www.w3.org/TR/its20/
+
+ This implementation supports only a few data categories, useful for
+ gettext-based projects. Other data categories can be added by
+ extending the its_rule_class_ty class and registering it in
+ init_classes().
+
+ The message extraction is performed in three steps. In the first
+ step, its_rule_list_apply() assigns values to nodes in an XML
+ document. In the second step, its_rule_list_extract_nodes() marks
+ translatable nodes. In the final step,
+ its_rule_list_extract_text() extracts text contents from the marked
+ nodes.
+
+ The values assigned to a node are represented as an array of
+ key-value pairs, where both keys and values are string. The array
+ is stored in node->_private. To retrieve the values for a node,
+ use its_rule_list_eval(). */
+
+#define ITS_NS "http://www.w3.org/2005/11/its"
+#define XML_NS "http://www.w3.org/XML/1998/namespace"
+#define GT_NS "https://www.gnu.org/s/gettext/ns/its/extensions/1.0"
+
+struct its_value_ty
+{
+ char *name;
+ char *value;
+};
+
+struct its_value_list_ty
+{
+ struct its_value_ty *items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+static void
+its_value_list_append (struct its_value_list_ty *values,
+ const char *name,
+ const char *value)
+{
+ struct its_value_ty _value;
+
+ _value.name = xstrdup (name);
+ _value.value = xstrdup (value);
+
+ if (values->nitems == values->nitems_max)
+ {
+ values->nitems_max = 2 * values->nitems_max + 1;
+ values->items =
+ xrealloc (values->items,
+ sizeof (struct its_value_ty) * values->nitems_max);
+ }
+ memcpy (&values->items[values->nitems++], &_value,
+ sizeof (struct its_value_ty));
+}
+
+static const char *
+its_value_list_get_value (struct its_value_list_ty *values,
+ const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < values->nitems; i++)
+ {
+ struct its_value_ty *value = &values->items[i];
+ if (strcmp (value->name, name) == 0)
+ return value->value;
+ }
+ return NULL;
+}
+
+static void
+its_value_list_set_value (struct its_value_list_ty *values,
+ const char *name,
+ const char *value)
+{
+ size_t i;
+
+ for (i = 0; i < values->nitems; i++)
+ {
+ struct its_value_ty *_value = &values->items[i];
+ if (strcmp (_value->name, name) == 0)
+ {
+ free (_value->value);
+ _value->value = xstrdup (value);
+ break;
+ }
+ }
+
+ if (i == values->nitems)
+ its_value_list_append (values, name, value);
+}
+
+static void
+its_value_list_merge (struct its_value_list_ty *values,
+ struct its_value_list_ty *other)
+{
+ size_t i;
+
+ for (i = 0; i < other->nitems; i++)
+ {
+ struct its_value_ty *other_value = &other->items[i];
+ size_t j;
+
+ for (j = 0; j < values->nitems; j++)
+ {
+ struct its_value_ty *value = &values->items[j];
+
+ if (strcmp (value->name, other_value->name) == 0
+ && strcmp (value->value, other_value->value) != 0)
+ {
+ free (value->value);
+ value->value = xstrdup (other_value->value);
+ break;
+ }
+ }
+
+ if (j == values->nitems)
+ its_value_list_append (values, other_value->name, other_value->value);
+ }
+}
+
+static void
+its_value_list_destroy (struct its_value_list_ty *values)
+{
+ size_t i;
+
+ for (i = 0; i < values->nitems; i++)
+ {
+ free (values->items[i].name);
+ free (values->items[i].value);
+ }
+ free (values->items);
+}
+
+struct its_pool_ty
+{
+ struct its_value_list_ty *items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+static struct its_value_list_ty *
+its_pool_alloc_value_list (struct its_pool_ty *pool)
+{
+ struct its_value_list_ty *values;
+
+ if (pool->nitems == pool->nitems_max)
+ {
+ pool->nitems_max = 2 * pool->nitems_max + 1;
+ pool->items =
+ xrealloc (pool->items,
+ sizeof (struct its_value_list_ty) * pool->nitems_max);
+ }
+
+ values = &pool->items[pool->nitems++];
+ memset (values, 0, sizeof (struct its_value_list_ty));
+ return values;
+}
+
+static const char *
+its_pool_get_value_for_node (struct its_pool_ty *pool, xmlNode *node,
+ const char *name)
+{
+ intptr_t index = (intptr_t) node->_private;
+ if (index > 0)
+ {
+ struct its_value_list_ty *values;
+
+ assert (index <= pool->nitems);
+ values = &pool->items[index - 1];
+
+ return its_value_list_get_value (values, name);
+ }
+ return NULL;
+}
+
+static void
+its_pool_destroy (struct its_pool_ty *pool)
+{
+ size_t i;
+
+ for (i = 0; i < pool->nitems; i++)
+ its_value_list_destroy (&pool->items[i]);
+ free (pool->items);
+}
+
+struct its_rule_list_ty
+{
+ struct its_rule_ty **items;
+ size_t nitems;
+ size_t nitems_max;
+
+ struct its_pool_ty pool;
+};
+
+struct its_node_list_ty
+{
+ xmlNode **items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+static void
+its_node_list_append (struct its_node_list_ty *nodes,
+ xmlNode *node)
+{
+ if (nodes->nitems == nodes->nitems_max)
+ {
+ nodes->nitems_max = 2 * nodes->nitems_max + 1;
+ nodes->items =
+ xrealloc (nodes->items, sizeof (xmlNode *) * nodes->nitems_max);
+ }
+ nodes->items[nodes->nitems++] = node;
+}
+
+/* Base class representing an ITS rule in global definition. */
+struct its_rule_class_ty
+{
+ /* How many bytes to malloc for an instance of this class. */
+ size_t size;
+
+ /* What to do immediately after the instance is malloc()ed. */
+ void (*constructor) (struct its_rule_ty *pop, xmlNode *node);
+
+ /* What to do immediately before the instance is free()ed. */
+ void (*destructor) (struct its_rule_ty *pop);
+
+ /* How to apply the rule to all elements in DOC. */
+ void (* apply) (struct its_rule_ty *pop, struct its_pool_ty *pool,
+ xmlDoc *doc);
+
+ /* How to evaluate the value of NODE according to the rule. */
+ struct its_value_list_ty *(* eval) (struct its_rule_ty *pop,
+ struct its_pool_ty *pool, xmlNode *node);
+};
+
+#define ITS_RULE_TY \
+ struct its_rule_class_ty *methods; \
+ char *selector; \
+ struct its_value_list_ty values; \
+ xmlNs **namespaces;
+
+struct its_rule_ty
+{
+ ITS_RULE_TY
+};
+
+static hash_table classes;
+
+static void
+its_rule_destructor (struct its_rule_ty *pop)
+{
+ free (pop->selector);
+ its_value_list_destroy (&pop->values);
+ if (pop->namespaces)
+ {
+ size_t i;
+ for (i = 0; pop->namespaces[i] != NULL; i++)
+ xmlFreeNs (pop->namespaces[i]);
+ free (pop->namespaces);
+ }
+}
+
+static void
+its_rule_apply (struct its_rule_ty *rule, struct its_pool_ty *pool, xmlDoc *doc)
+{
+ xmlXPathContext *context;
+ xmlXPathObject *object;
+ size_t i;
+
+ if (!rule->selector)
+ {
+ error (0, 0, _("selector is not specified"));
+ return;
+ }
+
+ context = xmlXPathNewContext (doc);
+ if (!context)
+ {
+ error (0, 0, _("cannot create XPath context"));
+ return;
+ }
+
+ if (rule->namespaces)
+ {
+ size_t i;
+ for (i = 0; rule->namespaces[i] != NULL; i++)
+ {
+ xmlNs *ns = rule->namespaces[i];
+ xmlXPathRegisterNs (context, ns->prefix, ns->href);
+ }
+ }
+
+ object = xmlXPathEval (BAD_CAST rule->selector, context);
+ if (!object)
+ {
+ xmlXPathFreeContext (context);
+ error (0, 0, _("cannot evaluate XPath expression: %s"), rule->selector);
+ return;
+ }
+
+ if (object->nodesetval)
+ {
+ xmlNodeSet *nodes = object->nodesetval;
+ for (i = 0; i < nodes->nodeNr; i++)
+ {
+ xmlNode *node = nodes->nodeTab[i];
+ struct its_value_list_ty *values;
+
+ /* We can't store VALUES in NODE, since the address can
+ change when realloc()ed. */
+ intptr_t index = (intptr_t) node->_private;
+
+ assert (index <= pool->nitems);
+ if (index > 0)
+ values = &pool->items[index - 1];
+ else
+ {
+ values = its_pool_alloc_value_list (pool);
+ node->_private = (void *) pool->nitems;
+ }
+
+ its_value_list_merge (values, &rule->values);
+ }
+ }
+
+ xmlXPathFreeObject (object);
+ xmlXPathFreeContext (context);
+}
+
+static char *
+_its_get_attribute (xmlNode *node, const char *attr, const char *namespace)
+{
+ xmlChar *value;
+ char *result;
+
+ value = xmlGetNsProp (node, BAD_CAST attr, BAD_CAST namespace);
+
+ result = xstrdup ((const char *) value);
+ xmlFree (value);
+
+ return result;
+}
+
+static char *
+normalize_whitespace (const char *text, enum its_whitespace_type_ty whitespace)
+{
+ switch (whitespace)
+ {
+ case ITS_WHITESPACE_PRESERVE:
+ return xstrdup (text);
+
+ case ITS_WHITESPACE_TRIM:
+ return trim (text);
+
+ default:
+ /* Normalize whitespaces within the text, but not at the beginning
+ nor the end of the text. */
+ {
+ char *result, *p, *end;
+
+ result = xstrdup (text);
+ end = result + strlen (result);
+ for (p = result; *p != '\0';)
+ {
+ size_t len = strspn (p, " \t\n");
+ if (len > 0)
+ {
+ *p = ' ';
+ memmove (p + 1, p + len, end - (p + len));
+ end -= len - 1;
+ *end = '\0';
+ p++;
+ }
+ p += strcspn (p, " \t\n");
+ }
+ return result;
+ }
+ }
+}
+
+static char *
+_its_encode_special_chars (const char *content, bool is_attribute)
+{
+ const char *str;
+ size_t amount = 0;
+ char *result, *p;
+
+ for (str = content; *str != '\0'; str++)
+ {
+ switch (*str)
+ {
+ case '&':
+ amount += sizeof ("&amp;");
+ break;
+ case '<':
+ amount += sizeof ("&lt;");
+ break;
+ case '>':
+ amount += sizeof ("&gt;");
+ break;
+ case '"':
+ if (is_attribute)
+ amount += sizeof ("&quot;");
+ else
+ amount += 1;
+ break;
+ default:
+ amount += 1;
+ break;
+ }
+ }
+
+ result = XNMALLOC (amount + 1, char);
+ *result = '\0';
+ p = result;
+ for (str = content; *str != '\0'; str++)
+ {
+ switch (*str)
+ {
+ case '&':
+ p = stpcpy (p, "&amp;");
+ break;
+ case '<':
+ p = stpcpy (p, "&lt;");
+ break;
+ case '>':
+ p = stpcpy (p, "&gt;");
+ break;
+ case '"':
+ if (is_attribute)
+ p = stpcpy (p, "&quot;");
+ else
+ *p++ = '"';
+ break;
+ default:
+ *p++ = *str;
+ break;
+ }
+ }
+ *p = '\0';
+ return result;
+}
+
+static char *
+_its_collect_text_content (xmlNode *node,
+ enum its_whitespace_type_ty whitespace,
+ bool no_escape)
+{
+ char *buffer = NULL;
+ size_t bufmax = 0;
+ size_t bufpos = 0;
+ xmlNode *n;
+
+ for (n = node->children; n; n = n->next)
+ {
+ char *content = NULL;
+
+ switch (n->type)
+ {
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ {
+ xmlChar *xcontent = xmlNodeGetContent (n);
+ char *econtent;
+ const char *ccontent;
+
+ /* We can't expect xmlTextWriterWriteString() encode
+ special characters as we write text outside of the
+ element. */
+ if (no_escape)
+ econtent = xstrdup ((const char *) xcontent);
+ else
+ econtent =
+ _its_encode_special_chars ((const char *) xcontent,
+ node->type == XML_ATTRIBUTE_NODE);
+ xmlFree (xcontent);
+
+ /* Skip whitespaces at the beginning of the text, if this
+ is the first node. */
+ ccontent = econtent;
+ if (whitespace == ITS_WHITESPACE_NORMALIZE && !n->prev)
+ ccontent = ccontent + strspn (ccontent, " \t\n");
+ content =
+ normalize_whitespace (ccontent, whitespace);
+ free (econtent);
+
+ /* Skip whitespaces at the end of the text, if this
+ is the last node. */
+ if (whitespace == ITS_WHITESPACE_NORMALIZE && !n->next)
+ {
+ char *p = content + strlen (content);
+ for (; p > content; p--)
+ {
+ int c = *(p - 1);
+ if (!(c == ' ' || c == '\t' || c == '\n'))
+ {
+ *p = '\0';
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case XML_ELEMENT_NODE:
+ {
+ xmlOutputBuffer *buffer = xmlAllocOutputBuffer (NULL);
+ xmlTextWriter *writer = xmlNewTextWriter (buffer);
+ char *p = _its_collect_text_content (n, whitespace,
+ no_escape);
+ const char *ccontent;
+
+ xmlTextWriterStartElement (writer, BAD_CAST n->name);
+ if (n->properties)
+ {
+ xmlAttr *attr = n->properties;
+ for (; attr; attr = attr->next)
+ {
+ xmlChar *prop = xmlGetProp (n, attr->name);
+ xmlTextWriterWriteAttribute (writer,
+ attr->name,
+ prop);
+ xmlFree (prop);
+ }
+ }
+ if (*p != '\0')
+ xmlTextWriterWriteRaw (writer, BAD_CAST p);
+ xmlTextWriterEndElement (writer);
+ ccontent = (const char *) xmlOutputBufferGetContent (buffer);
+ content = normalize_whitespace (ccontent, whitespace);
+ xmlFreeTextWriter (writer);
+ free (p);
+ }
+ break;
+
+ case XML_ENTITY_REF_NODE:
+ content = xasprintf ("&%s;", (const char *) n->name);
+ break;
+
+ default:
+ break;
+ }
+
+ if (content != NULL)
+ {
+ size_t length = strlen (content);
+
+ if (bufpos + length + 1 >= bufmax)
+ {
+ bufmax = 2 * bufmax + length + 1;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ strcpy (&buffer[bufpos], content);
+ bufpos += length;
+ }
+ free (content);
+ }
+
+ if (buffer == NULL)
+ buffer = xstrdup ("");
+ return buffer;
+}
+
+static void
+_its_error_missing_attribute (xmlNode *node, const char *attribute)
+{
+ error (0, 0, _("\"%s\" node does not contain \"%s\""),
+ node->name, attribute);
+}
+
+/* Implementation of Translate data category. */
+static void
+its_translate_rule_constructor (struct its_rule_ty *pop, xmlNode *node)
+{
+ char *prop;
+
+ if (!xmlHasProp (node, BAD_CAST "selector"))
+ {
+ _its_error_missing_attribute (node, "selector");
+ return;
+ }
+
+ if (!xmlHasProp (node, BAD_CAST "translate"))
+ {
+ _its_error_missing_attribute (node, "translate");
+ return;
+ }
+
+ prop = _its_get_attribute (node, "selector", NULL);
+ if (prop)
+ pop->selector = prop;
+
+ prop = _its_get_attribute (node, "translate", NULL);
+ its_value_list_append (&pop->values, "translate", prop);
+ free (prop);
+}
+
+struct its_value_list_ty *
+its_translate_rule_eval (struct its_rule_ty *pop, struct its_pool_ty *pool,
+ xmlNode *node)
+{
+ struct its_value_list_ty *result;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+
+ switch (node->type)
+ {
+ case XML_ATTRIBUTE_NODE:
+ /* Attribute nodes don't inherit from the parent elements. */
+ {
+ const char *value =
+ its_pool_get_value_for_node (pool, node, "translate");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "translate", value);
+ return result;
+ }
+
+ /* The default value is translate="no". */
+ its_value_list_append (result, "translate", "no");
+ }
+ break;
+
+ case XML_ELEMENT_NODE:
+ /* Inherit from the parent elements. */
+ {
+ const char *value;
+
+ /* A local attribute overrides the global rule. */
+ if (xmlHasNsProp (node, BAD_CAST "translate", BAD_CAST ITS_NS))
+ {
+ char *prop;
+
+ prop = _its_get_attribute (node, "translate", ITS_NS);
+ its_value_list_append (result, "translate", prop);
+ free (prop);
+ return result;
+ }
+
+ /* Check value for the current node. */
+ value = its_pool_get_value_for_node (pool, node, "translate");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "translate", value);
+ return result;
+ }
+
+ /* Recursively check value for the parent node. */
+ if (node->parent == NULL
+ || node->parent->type != XML_ELEMENT_NODE)
+ /* The default value is translate="yes". */
+ its_value_list_append (result, "translate", "yes");
+ else
+ {
+ struct its_value_list_ty *values;
+
+ values = its_translate_rule_eval (pop, pool, node->parent);
+ its_value_list_merge (result, values);
+ its_value_list_destroy (values);
+ free (values);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static struct its_rule_class_ty its_translate_rule_class =
+ {
+ sizeof (struct its_rule_ty),
+ its_translate_rule_constructor,
+ its_rule_destructor,
+ its_rule_apply,
+ its_translate_rule_eval,
+ };
+
+/* Implementation of Localization Note data category. */
+static void
+its_localization_note_rule_constructor (struct its_rule_ty *pop, xmlNode *node)
+{
+ char *prop;
+ xmlNode *n;
+
+ if (!xmlHasProp (node, BAD_CAST "selector"))
+ {
+ _its_error_missing_attribute (node, "selector");
+ return;
+ }
+
+ if (!xmlHasProp (node, BAD_CAST "locNoteType"))
+ {
+ _its_error_missing_attribute (node, "locNoteType");
+ return;
+ }
+
+ prop = _its_get_attribute (node, "selector", NULL);
+ if (prop)
+ pop->selector = prop;
+
+ for (n = node->children; n; n = n->next)
+ {
+ if (n->type == XML_ELEMENT_NODE
+ && xmlStrEqual (n->name, BAD_CAST "locNote")
+ && xmlStrEqual (n->ns->href, BAD_CAST ITS_NS))
+ break;
+ }
+
+ prop = _its_get_attribute (node, "locNoteType", NULL);
+ if (prop)
+ its_value_list_append (&pop->values, "locNoteType", prop);
+ free (prop);
+
+ if (n)
+ {
+ /* FIXME: Respect space attribute. */
+ char *content = _its_collect_text_content (n, ITS_WHITESPACE_NORMALIZE,
+ false);
+ its_value_list_append (&pop->values, "locNote", content);
+ free (content);
+ }
+ else if (xmlHasProp (node, BAD_CAST "locNotePointer"))
+ {
+ prop = _its_get_attribute (node, "locNotePointer", NULL);
+ its_value_list_append (&pop->values, "locNotePointer", prop);
+ free (prop);
+ }
+ /* FIXME: locNoteRef and locNoteRefPointer */
+}
+
+struct its_value_list_ty *
+its_localization_note_rule_eval (struct its_rule_ty *pop,
+ struct its_pool_ty *pool,
+ xmlNode *node)
+{
+ struct its_value_list_ty *result;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+
+ switch (node->type)
+ {
+ case XML_ATTRIBUTE_NODE:
+ /* Attribute nodes don't inherit from the parent elements. */
+ {
+ const char *value;
+
+ value = its_pool_get_value_for_node (pool, node, "locNoteType");
+ if (value != NULL)
+ its_value_list_set_value (result, "locNoteType", value);
+
+ value = its_pool_get_value_for_node (pool, node, "locNote");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "locNote", value);
+ return result;
+ }
+
+ value = its_pool_get_value_for_node (pool, node, "locNotePointer");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "locNotePointer", value);
+ return result;
+ }
+ }
+ break;
+
+ case XML_ELEMENT_NODE:
+ /* Inherit from the parent elements. */
+ {
+ const char *value;
+
+ /* Local attributes overrides the global rule. */
+ if (xmlHasNsProp (node, BAD_CAST "locNote", BAD_CAST ITS_NS)
+ || xmlHasNsProp (node, BAD_CAST "locNoteRef", BAD_CAST ITS_NS)
+ || xmlHasNsProp (node, BAD_CAST "locNoteType", BAD_CAST ITS_NS))
+ {
+ char *prop;
+
+ if (xmlHasNsProp (node, BAD_CAST "locNote", BAD_CAST ITS_NS))
+ {
+ prop = _its_get_attribute (node, "locNote", ITS_NS);
+ its_value_list_append (result, "locNote", prop);
+ free (prop);
+ }
+
+ /* FIXME: locNoteRef */
+
+ if (xmlHasNsProp (node, BAD_CAST "locNoteType", BAD_CAST ITS_NS))
+ {
+ prop = _its_get_attribute (node, "locNoteType", ITS_NS);
+ its_value_list_append (result, "locNoteType", prop);
+ free (prop);
+ }
+
+ return result;
+ }
+
+ /* Check value for the current node. */
+ value = its_pool_get_value_for_node (pool, node, "locNoteType");
+ if (value != NULL)
+ its_value_list_set_value (result, "locNoteType", value);
+
+ value = its_pool_get_value_for_node (pool, node, "locNote");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "locNote", value);
+ return result;
+ }
+
+ value = its_pool_get_value_for_node (pool, node, "locNotePointer");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "locNotePointer", value);
+ return result;
+ }
+
+ /* Recursively check value for the parent node. */
+ if (node->parent == NULL
+ || node->parent->type != XML_ELEMENT_NODE)
+ return result;
+ else
+ {
+ struct its_value_list_ty *values;
+
+ values = its_localization_note_rule_eval (pop, pool, node->parent);
+ its_value_list_merge (result, values);
+ its_value_list_destroy (values);
+ free (values);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* The default value is None. */
+ return result;
+}
+
+static struct its_rule_class_ty its_localization_note_rule_class =
+ {
+ sizeof (struct its_rule_ty),
+ its_localization_note_rule_constructor,
+ its_rule_destructor,
+ its_rule_apply,
+ its_localization_note_rule_eval,
+ };
+
+/* Implementation of Element Within Text data category. */
+static void
+its_element_within_text_rule_constructor (struct its_rule_ty *pop,
+ xmlNode *node)
+{
+ char *prop;
+
+ if (!xmlHasProp (node, BAD_CAST "selector"))
+ {
+ _its_error_missing_attribute (node, "selector");
+ return;
+ }
+
+ if (!xmlHasProp (node, BAD_CAST "withinText"))
+ {
+ _its_error_missing_attribute (node, "withinText");
+ return;
+ }
+
+ prop = _its_get_attribute (node, "selector", NULL);
+ if (prop)
+ pop->selector = prop;
+
+ prop = _its_get_attribute (node, "withinText", NULL);
+ its_value_list_append (&pop->values, "withinText", prop);
+ free (prop);
+}
+
+struct its_value_list_ty *
+its_element_within_text_rule_eval (struct its_rule_ty *pop,
+ struct its_pool_ty *pool,
+ xmlNode *node)
+{
+ struct its_value_list_ty *result;
+ const char *value;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+
+ if (node->type != XML_ELEMENT_NODE)
+ return result;
+
+ /* A local attribute overrides the global rule. */
+ if (xmlHasNsProp (node, BAD_CAST "withinText", BAD_CAST ITS_NS))
+ {
+ char *prop;
+
+ prop = _its_get_attribute (node, "withinText", ITS_NS);
+ its_value_list_append (result, "withinText", prop);
+ free (prop);
+ return result;
+ }
+
+ /* Doesn't inherit from the parent elements, and the default value
+ is None. */
+ value = its_pool_get_value_for_node (pool, node, "withinText");
+ if (value != NULL)
+ its_value_list_set_value (result, "withinText", value);
+
+ return result;
+}
+
+static struct its_rule_class_ty its_element_within_text_rule_class =
+ {
+ sizeof (struct its_rule_ty),
+ its_element_within_text_rule_constructor,
+ its_rule_destructor,
+ its_rule_apply,
+ its_element_within_text_rule_eval,
+ };
+
+/* Implementation of Preserve Space data category. */
+static void
+its_preserve_space_rule_constructor (struct its_rule_ty *pop,
+ xmlNode *node)
+{
+ char *prop;
+
+ if (!xmlHasProp (node, BAD_CAST "selector"))
+ {
+ _its_error_missing_attribute (node, "selector");
+ return;
+ }
+
+ if (!xmlHasProp (node, BAD_CAST "space"))
+ {
+ _its_error_missing_attribute (node, "space");
+ return;
+ }
+
+ prop = _its_get_attribute (node, "selector", NULL);
+ if (prop)
+ pop->selector = prop;
+
+ prop = _its_get_attribute (node, "space", NULL);
+ if (prop
+ && !(strcmp (prop, "preserve") ==0
+ || strcmp (prop, "default") == 0
+ /* gettext extension: remove leading/trailing whitespaces only. */
+ || (node->ns && xmlStrEqual (node->ns->href, BAD_CAST GT_NS)
+ && strcmp (prop, "trim") == 0)))
+ {
+ error (0, 0, _("invalid attribute value \"%s\" for \"%s\""),
+ prop, "space");
+ free (prop);
+ return;
+ }
+
+ its_value_list_append (&pop->values, "space", prop);
+ free (prop);
+}
+
+struct its_value_list_ty *
+its_preserve_space_rule_eval (struct its_rule_ty *pop,
+ struct its_pool_ty *pool,
+ xmlNode *node)
+{
+ struct its_value_list_ty *result;
+ struct its_value_list_ty *values;
+ const char *value;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+
+ if (node->type != XML_ELEMENT_NODE)
+ return result;
+
+ /* A local attribute overrides the global rule. */
+ if (xmlHasNsProp (node, BAD_CAST "space", BAD_CAST XML_NS))
+ {
+ char *prop;
+
+ prop = _its_get_attribute (node, "space", XML_NS);
+ its_value_list_append (result, "space", prop);
+ free (prop);
+ return result;
+ }
+
+ /* Check value for the current node. */
+ value = its_pool_get_value_for_node (pool, node, "space");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "space", value);
+ return result;
+ }
+
+ if (node->parent == NULL
+ || node->parent->type != XML_ELEMENT_NODE)
+ {
+ /* The default value is space="default". */
+ its_value_list_append (result, "space", "default");
+ return result;
+ }
+
+ /* Recursively check value for the parent node. */
+ values = its_preserve_space_rule_eval (pop, pool, node->parent);
+ its_value_list_merge (result, values);
+ its_value_list_destroy (values);
+ free (values);
+
+ return result;
+}
+
+static struct its_rule_class_ty its_preserve_space_rule_class =
+ {
+ sizeof (struct its_rule_ty),
+ its_preserve_space_rule_constructor,
+ its_rule_destructor,
+ its_rule_apply,
+ its_preserve_space_rule_eval,
+ };
+
+/* Implementation of Context data category. */
+static void
+its_extension_context_rule_constructor (struct its_rule_ty *pop, xmlNode *node)
+{
+ char *prop;
+
+ if (!xmlHasProp (node, BAD_CAST "selector"))
+ {
+ _its_error_missing_attribute (node, "selector");
+ return;
+ }
+
+ if (!xmlHasProp (node, BAD_CAST "contextPointer"))
+ {
+ _its_error_missing_attribute (node, "contextPointer");
+ return;
+ }
+
+ prop = _its_get_attribute (node, "selector", NULL);
+ if (prop)
+ pop->selector = prop;
+
+ prop = _its_get_attribute (node, "contextPointer", NULL);
+ its_value_list_append (&pop->values, "contextPointer", prop);
+ free (prop);
+
+ if (xmlHasProp (node, BAD_CAST "textPointer"))
+ {
+ prop = _its_get_attribute (node, "textPointer", NULL);
+ its_value_list_append (&pop->values, "textPointer", prop);
+ free (prop);
+ }
+}
+
+struct its_value_list_ty *
+its_extension_context_rule_eval (struct its_rule_ty *pop,
+ struct its_pool_ty *pool,
+ xmlNode *node)
+{
+ struct its_value_list_ty *result;
+ const char *value;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+
+ /* Doesn't inherit from the parent elements, and the default value
+ is None. */
+ value = its_pool_get_value_for_node (pool, node, "contextPointer");
+ if (value != NULL)
+ its_value_list_set_value (result, "contextPointer", value);
+
+ value = its_pool_get_value_for_node (pool, node, "textPointer");
+ if (value != NULL)
+ its_value_list_set_value (result, "textPointer", value);
+
+ return result;
+}
+
+static struct its_rule_class_ty its_extension_context_rule_class =
+ {
+ sizeof (struct its_rule_ty),
+ its_extension_context_rule_constructor,
+ its_rule_destructor,
+ its_rule_apply,
+ its_extension_context_rule_eval,
+ };
+
+/* Implementation of Escape Special Characters data category. */
+static void
+its_extension_escape_rule_constructor (struct its_rule_ty *pop, xmlNode *node)
+{
+ char *prop;
+
+ if (!xmlHasProp (node, BAD_CAST "selector"))
+ {
+ _its_error_missing_attribute (node, "selector");
+ return;
+ }
+
+ if (!xmlHasProp (node, BAD_CAST "escape"))
+ {
+ _its_error_missing_attribute (node, "escape");
+ return;
+ }
+
+ prop = _its_get_attribute (node, "selector", NULL);
+ if (prop)
+ pop->selector = prop;
+
+ prop = _its_get_attribute (node, "escape", NULL);
+ its_value_list_append (&pop->values, "escape", prop);
+ free (prop);
+}
+
+struct its_value_list_ty *
+its_extension_escape_rule_eval (struct its_rule_ty *pop,
+ struct its_pool_ty *pool,
+ xmlNode *node)
+{
+ struct its_value_list_ty *result;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+
+ switch (node->type)
+ {
+ case XML_ATTRIBUTE_NODE:
+ /* Attribute nodes don't inherit from the parent elements. */
+ {
+ const char *value =
+ its_pool_get_value_for_node (pool, node, "escape");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "escape", value);
+ return result;
+ }
+ }
+ break;
+
+ case XML_ELEMENT_NODE:
+ /* Inherit from the parent elements. */
+ {
+ const char *value;
+
+ /* Check value for the current node. */
+ value = its_pool_get_value_for_node (pool, node, "escape");
+ if (value != NULL)
+ {
+ its_value_list_set_value (result, "escape", value);
+ return result;
+ }
+
+ /* Recursively check value for the parent node. */
+ if (node->parent != NULL
+ && node->parent->type == XML_ELEMENT_NODE)
+ {
+ struct its_value_list_ty *values;
+
+ values = its_extension_escape_rule_eval (pop, pool, node->parent);
+ its_value_list_merge (result, values);
+ its_value_list_destroy (values);
+ free (values);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static struct its_rule_class_ty its_extension_escape_rule_class =
+ {
+ sizeof (struct its_rule_ty),
+ its_extension_escape_rule_constructor,
+ its_rule_destructor,
+ its_rule_apply,
+ its_extension_escape_rule_eval,
+ };
+
+static struct its_rule_ty *
+its_rule_alloc (struct its_rule_class_ty *method_table, xmlNode *node)
+{
+ struct its_rule_ty *pop;
+
+ pop = (struct its_rule_ty *) xcalloc (1, method_table->size);
+ pop->methods = method_table;
+ if (method_table->constructor)
+ method_table->constructor (pop, node);
+ return pop;
+}
+
+static struct its_rule_ty *
+its_rule_parse (xmlDoc *doc, xmlNode *node)
+{
+ const char *name = (const char *) node->name;
+ void *value;
+
+ if (hash_find_entry (&classes, name, strlen (name), &value) == 0)
+ {
+ struct its_rule_ty *result;
+ xmlNs **namespaces;
+
+ result = its_rule_alloc ((struct its_rule_class_ty *) value, node);
+ namespaces = xmlGetNsList (doc, node);
+ if (namespaces)
+ {
+ size_t i;
+ for (i = 0; namespaces[i] != NULL; i++)
+ ;
+ result->namespaces = XCALLOC (i + 1, xmlNs *);
+ for (i = 0; namespaces[i] != NULL; i++)
+ result->namespaces[i] = xmlCopyNamespace (namespaces[i]);
+ }
+ xmlFree (namespaces);
+ return result;
+ }
+
+ return NULL;
+}
+
+static void
+its_rule_destroy (struct its_rule_ty *pop)
+{
+ if (pop->methods->destructor)
+ pop->methods->destructor (pop);
+}
+
+static void
+init_classes (void)
+{
+#define ADD_RULE_CLASS(n, c) \
+ hash_insert_entry (&classes, n, strlen (n), &c);
+
+ ADD_RULE_CLASS ("translateRule", its_translate_rule_class);
+ ADD_RULE_CLASS ("locNoteRule", its_localization_note_rule_class);
+ ADD_RULE_CLASS ("withinTextRule", its_element_within_text_rule_class);
+ ADD_RULE_CLASS ("preserveSpaceRule", its_preserve_space_rule_class);
+ ADD_RULE_CLASS ("contextRule", its_extension_context_rule_class);
+ ADD_RULE_CLASS ("escapeRule", its_extension_escape_rule_class);
+
+#undef ADD_RULE_CLASS
+}
+
+struct its_rule_list_ty *
+its_rule_list_alloc (void)
+{
+ struct its_rule_list_ty *result;
+
+ if (classes.table == NULL)
+ {
+ hash_init (&classes, 10);
+ init_classes ();
+ }
+
+ result = XCALLOC (1, struct its_rule_list_ty);
+ return result;
+}
+
+void
+its_rule_list_free (struct its_rule_list_ty *rules)
+{
+ size_t i;
+
+ for (i = 0; i < rules->nitems; i++)
+ {
+ its_rule_destroy (rules->items[i]);
+ free (rules->items[i]);
+ }
+ free (rules->items);
+ its_pool_destroy (&rules->pool);
+}
+
+static bool
+its_rule_list_add_from_doc (struct its_rule_list_ty *rules,
+ xmlDoc *doc)
+{
+ xmlNode *root, *node;
+
+ root = xmlDocGetRootElement (doc);
+ if (!(xmlStrEqual (root->name, BAD_CAST "rules")
+ && xmlStrEqual (root->ns->href, BAD_CAST ITS_NS)))
+ {
+ error (0, 0, _("the root element is not \"rules\""
+ " under namespace %s"),
+ ITS_NS);
+ xmlFreeDoc (doc);
+ return false;
+ }
+
+ for (node = root->children; node; node = node->next)
+ {
+ struct its_rule_ty *rule;
+
+ rule = its_rule_parse (doc, node);
+ if (!rule)
+ continue;
+
+ if (rules->nitems == rules->nitems_max)
+ {
+ rules->nitems_max = 2 * rules->nitems_max + 1;
+ rules->items =
+ xrealloc (rules->items,
+ sizeof (struct its_rule_ty *) * rules->nitems_max);
+ }
+ rules->items[rules->nitems++] = rule;
+ }
+
+ return true;
+}
+
+bool
+its_rule_list_add_from_file (struct its_rule_list_ty *rules,
+ const char *filename)
+{
+ xmlDoc *doc;
+ bool result;
+
+ doc = xmlReadFile (filename, "utf-8",
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOBLANKS
+ | XML_PARSE_NOERROR);
+ if (doc == NULL)
+ {
+ xmlError *err = xmlGetLastError ();
+ error (0, 0, _("cannot read %s: %s"), filename, err->message);
+ return false;
+ }
+
+ result = its_rule_list_add_from_doc (rules, doc);
+ xmlFreeDoc (doc);
+ return result;
+}
+
+bool
+its_rule_list_add_from_string (struct its_rule_list_ty *rules,
+ const char *rule)
+{
+ xmlDoc *doc;
+ bool result;
+
+ doc = xmlReadMemory (rule, strlen (rule),
+ "(internal)",
+ NULL,
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOBLANKS
+ | XML_PARSE_NOERROR);
+ if (doc == NULL)
+ {
+ xmlError *err = xmlGetLastError ();
+ error (0, 0, _("cannot read %s: %s"), "(internal)", err->message);
+ return false;
+ }
+
+ result = its_rule_list_add_from_doc (rules, doc);
+ xmlFreeDoc (doc);
+ return result;
+}
+
+static void
+its_rule_list_apply (struct its_rule_list_ty *rules, xmlDoc *doc)
+{
+ size_t i;
+
+ for (i = 0; i < rules->nitems; i++)
+ {
+ struct its_rule_ty *rule = rules->items[i];
+ rule->methods->apply (rule, &rules->pool, doc);
+ }
+}
+
+static struct its_value_list_ty *
+its_rule_list_eval (its_rule_list_ty *rules, xmlNode *node)
+{
+ struct its_value_list_ty *result;
+ size_t i;
+
+ result = XCALLOC (1, struct its_value_list_ty);
+ for (i = 0; i < rules->nitems; i++)
+ {
+ struct its_rule_ty *rule = rules->items[i];
+ struct its_value_list_ty *values;
+
+ values = rule->methods->eval (rule, &rules->pool, node);
+ its_value_list_merge (result, values);
+ its_value_list_destroy (values);
+ free (values);
+ }
+
+ return result;
+}
+
+static bool
+its_rule_list_is_translatable (its_rule_list_ty *rules,
+ xmlNode *node,
+ int depth)
+{
+ struct its_value_list_ty *values;
+ const char *value;
+ xmlNode *n;
+
+ if (node->type != XML_ELEMENT_NODE
+ && node->type != XML_ATTRIBUTE_NODE)
+ return false;
+
+ values = its_rule_list_eval (rules, node);
+
+ /* Check if NODE has translate="yes". */
+ value = its_value_list_get_value (values, "translate");
+ if (!(value && strcmp (value, "yes") == 0))
+ {
+ its_value_list_destroy (values);
+ free (values);
+ return false;
+ }
+
+ /* Check if NODE has withinText="yes", if NODE is not top-level. */
+ if (depth > 0)
+ {
+ value = its_value_list_get_value (values, "withinText");
+ if (!(value && strcmp (value, "yes") == 0))
+ {
+ its_value_list_destroy (values);
+ free (values);
+ return false;
+ }
+ }
+
+ its_value_list_destroy (values);
+ free (values);
+
+ for (n = node->children; n; n = n->next)
+ {
+ switch (n->type)
+ {
+ case XML_ELEMENT_NODE:
+ if (!its_rule_list_is_translatable (rules, n, depth + 1))
+ return false;
+ break;
+
+ case XML_TEXT_NODE:
+ case XML_CDATA_SECTION_NODE:
+ case XML_ENTITY_REF_NODE:
+ case XML_COMMENT_NODE:
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void
+its_rule_list_extract_nodes (its_rule_list_ty *rules,
+ struct its_node_list_ty *nodes,
+ xmlNode *node)
+{
+ if (node->type == XML_ELEMENT_NODE)
+ {
+ xmlNode *n;
+
+ if (node->properties)
+ {
+ xmlAttr *attr = node->properties;
+ for (; attr; attr = attr->next)
+ {
+ xmlNode *n = (xmlNode *) attr;
+ if (its_rule_list_is_translatable (rules, n, 0))
+ its_node_list_append (nodes, n);
+ }
+ }
+
+ if (its_rule_list_is_translatable (rules, node, 0))
+ its_node_list_append (nodes, node);
+ else
+ {
+ for (n = node->children; n; n = n->next)
+ its_rule_list_extract_nodes (rules, nodes, n);
+ }
+ }
+}
+
+static char *
+_its_get_content (struct its_rule_list_ty *rules, xmlNode *node,
+ const char *pointer,
+ enum its_whitespace_type_ty whitespace,
+ bool no_escape)
+{
+ xmlXPathContext *context;
+ xmlXPathObject *object;
+ size_t i;
+ char *result = NULL;
+
+ context = xmlXPathNewContext (node->doc);
+ if (!context)
+ {
+ error (0, 0, _("cannot create XPath context"));
+ return NULL;
+ }
+
+ for (i = 0; i < rules->nitems; i++)
+ {
+ struct its_rule_ty *rule = rules->items[i];
+ if (rule->namespaces)
+ {
+ size_t i;
+ for (i = 0; rule->namespaces[i] != NULL; i++)
+ {
+ xmlNs *ns = rule->namespaces[i];
+ xmlXPathRegisterNs (context, ns->prefix, ns->href);
+ }
+ }
+ }
+
+ xmlXPathSetContextNode (node, context);
+ object = xmlXPathEvalExpression (BAD_CAST pointer, context);
+ if (!object)
+ {
+ xmlXPathFreeContext (context);
+ error (0, 0, _("cannot evaluate XPath location path: %s"),
+ pointer);
+ return NULL;
+ }
+
+ switch (object->type)
+ {
+ case XPATH_NODESET:
+ {
+ xmlNodeSet *nodes = object->nodesetval;
+ string_list_ty sl;
+ size_t i;
+
+ string_list_init (&sl);
+ for (i = 0; i < nodes->nodeNr; i++)
+ {
+ char *content = _its_collect_text_content (nodes->nodeTab[i],
+ whitespace,
+ no_escape);
+ string_list_append (&sl, content);
+ free (content);
+ }
+ result = string_list_concat (&sl);
+ string_list_destroy (&sl);
+ }
+ break;
+
+ case XPATH_STRING:
+ result = xstrdup ((const char *) object->stringval);
+ break;
+
+ default:
+ break;
+ }
+
+ xmlXPathFreeObject (object);
+ xmlXPathFreeContext (context);
+
+ return result;
+}
+
+static void
+_its_comment_append (string_list_ty *comments, const char *data)
+{
+ /* Split multiline comment into lines, and remove leading and trailing
+ whitespace. */
+ char *copy = xstrdup (data);
+ char *p;
+ char *q;
+
+ for (p = copy; (q = strchr (p, '\n')) != NULL; p = q + 1)
+ {
+ while (p[0] == ' ' || p[0] == '\t')
+ p++;
+ while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
+ q--;
+ *q = '\0';
+ string_list_append (comments, p);
+ }
+ q = p + strlen (p);
+ while (p[0] == ' ' || p[0] == '\t')
+ p++;
+ while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
+ q--;
+ *q = '\0';
+ string_list_append (comments, p);
+ free (copy);
+}
+
+static void
+its_rule_list_extract_text (its_rule_list_ty *rules,
+ xmlNode *node,
+ const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ message_list_ty *mlp,
+ its_extract_callback_ty callback)
+{
+ if (node->type == XML_ELEMENT_NODE
+ || node->type == XML_ATTRIBUTE_NODE)
+ {
+ struct its_value_list_ty *values;
+ const char *value;
+ char *msgid = NULL, *msgctxt = NULL, *comment = NULL;
+ enum its_whitespace_type_ty whitespace;
+ bool no_escape;
+
+ values = its_rule_list_eval (rules, node);
+
+ value = its_value_list_get_value (values, "locNote");
+ if (value)
+ comment = xstrdup (value);
+ else
+ {
+ value = its_value_list_get_value (values, "escape");
+ no_escape = value != NULL && strcmp (value, "no") == 0;
+
+ value = its_value_list_get_value (values, "locNotePointer");
+ if (value)
+ comment = _its_get_content (rules, node, value, ITS_WHITESPACE_TRIM,
+ no_escape);
+ }
+
+ if (comment != NULL && *comment != '\0')
+ {
+ string_list_ty comments;
+ char *tmp;
+
+ string_list_init (&comments);
+ _its_comment_append (&comments, comment);
+ tmp = string_list_join (&comments, "\n", '\0', false);
+ free (comment);
+ comment = tmp;
+ }
+ else
+ /* Extract comments preceding the node. */
+ {
+ xmlNode *sibling;
+ string_list_ty comments;
+
+ string_list_init (&comments);
+ for (sibling = node->prev; sibling; sibling = sibling->prev)
+ if (sibling->type != XML_COMMENT_NODE || sibling->prev == NULL)
+ break;
+ if (sibling)
+ {
+ if (sibling->type != XML_COMMENT_NODE)
+ sibling = sibling->next;
+ for (; sibling && sibling->type == XML_COMMENT_NODE;
+ sibling = sibling->next)
+ {
+ xmlChar *content = xmlNodeGetContent (sibling);
+ _its_comment_append (&comments, (const char *) content);
+ xmlFree (content);
+ }
+ free (comment);
+ comment = string_list_join (&comments, "\n", '\0', false);
+ string_list_destroy (&comments);
+ }
+ }
+
+ value = its_value_list_get_value (values, "space");
+ if (value && strcmp (value, "preserve") == 0)
+ whitespace = ITS_WHITESPACE_PRESERVE;
+ else if (value && strcmp (value, "trim") == 0)
+ whitespace = ITS_WHITESPACE_TRIM;
+ else
+ whitespace = ITS_WHITESPACE_NORMALIZE;
+
+ value = its_value_list_get_value (values, "escape");
+ no_escape = value != NULL && strcmp (value, "no") == 0;
+
+ value = its_value_list_get_value (values, "contextPointer");
+ if (value)
+ msgctxt = _its_get_content (rules, node, value, ITS_WHITESPACE_PRESERVE,
+ no_escape);
+
+ value = its_value_list_get_value (values, "textPointer");
+ if (value)
+ msgid = _its_get_content (rules, node, value, ITS_WHITESPACE_PRESERVE,
+ no_escape);
+ its_value_list_destroy (values);
+ free (values);
+
+ if (msgid == NULL)
+ msgid = _its_collect_text_content (node, whitespace, no_escape);
+ if (*msgid != '\0')
+ {
+ lex_pos_ty pos;
+ char *marker;
+
+ pos.file_name = xstrdup (logical_filename);
+ pos.line_number = xmlGetLineNo (node);
+
+ if (node->type == XML_ELEMENT_NODE)
+ {
+ assert (node->parent);
+ marker = xasprintf ("%s/%s", node->parent->name, node->name);
+ }
+ else
+ {
+ assert (node->parent && node->parent->parent);
+ marker = xasprintf ("%s/%s@%s",
+ node->parent->parent->name,
+ node->parent->name,
+ node->name);
+ }
+
+ if (msgctxt != NULL && *msgctxt == '\0')
+ {
+ free (msgctxt);
+ msgctxt = NULL;
+ }
+
+ callback (mlp, msgctxt, msgid, &pos, comment, marker, whitespace);
+ free (marker);
+ }
+ free (msgctxt);
+ free (msgid);
+ free (comment);
+ }
+}
+
+void
+its_rule_list_extract (its_rule_list_ty *rules,
+ FILE *fp, const char *real_filename,
+ const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp,
+ its_extract_callback_ty callback)
+{
+ xmlDoc *doc;
+ struct its_node_list_ty nodes;
+ size_t i;
+
+ doc = xmlReadFd (fileno (fp), logical_filename, NULL,
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOBLANKS
+ | XML_PARSE_NOERROR);
+ if (doc == NULL)
+ {
+ xmlError *err = xmlGetLastError ();
+ error (0, 0, _("cannot read %s: %s"), logical_filename, err->message);
+ return;
+ }
+
+ its_rule_list_apply (rules, doc);
+
+ memset (&nodes, 0, sizeof (struct its_node_list_ty));
+ its_rule_list_extract_nodes (rules,
+ &nodes,
+ xmlDocGetRootElement (doc));
+
+ for (i = 0; i < nodes.nitems; i++)
+ its_rule_list_extract_text (rules, nodes.items[i],
+ logical_filename,
+ flag_table,
+ mdlp->item[0]->messages,
+ callback);
+
+ free (nodes.items);
+ xmlFreeDoc (doc);
+}
+
+struct its_merge_context_ty
+{
+ its_rule_list_ty *rules;
+ xmlDoc *doc;
+ struct its_node_list_ty nodes;
+};
+
+static void
+its_merge_context_merge_node (struct its_merge_context_ty *context,
+ xmlNode *node,
+ const char *language,
+ message_list_ty *mlp)
+{
+ if (node->type == XML_ELEMENT_NODE)
+ {
+ struct its_value_list_ty *values;
+ const char *value;
+ char *msgid = NULL, *msgctxt = NULL;
+ enum its_whitespace_type_ty whitespace;
+ bool no_escape;
+
+ values = its_rule_list_eval (context->rules, node);
+
+ value = its_value_list_get_value (values, "space");
+ if (value && strcmp (value, "preserve") == 0)
+ whitespace = ITS_WHITESPACE_PRESERVE;
+ else if (value && strcmp (value, "trim") == 0)
+ whitespace = ITS_WHITESPACE_TRIM;
+ else
+ whitespace = ITS_WHITESPACE_NORMALIZE;
+
+ value = its_value_list_get_value (values, "escape");
+ no_escape = value != NULL && strcmp (value, "no") == 0;
+
+ value = its_value_list_get_value (values, "contextPointer");
+ if (value)
+ msgctxt = _its_get_content (context->rules, node, value,
+ ITS_WHITESPACE_PRESERVE, no_escape);
+
+ value = its_value_list_get_value (values, "textPointer");
+ if (value)
+ msgid = _its_get_content (context->rules, node, value,
+ ITS_WHITESPACE_PRESERVE, no_escape);
+ its_value_list_destroy (values);
+ free (values);
+
+ if (msgid == NULL)
+ msgid = _its_collect_text_content (node, whitespace, no_escape);
+ if (*msgid != '\0')
+ {
+ message_ty *mp;
+
+ mp = message_list_search (mlp, msgctxt, msgid);
+ if (mp && *mp->msgstr != '\0')
+ {
+ xmlNode *translated;
+
+ translated = xmlNewNode (node->ns, node->name);
+ xmlSetProp (translated, BAD_CAST "xml:lang", BAD_CAST language);
+
+ xmlNodeAddContent (translated, BAD_CAST mp->msgstr);
+ xmlAddNextSibling (node, translated);
+ }
+ }
+ free (msgctxt);
+ free (msgid);
+ }
+}
+
+void
+its_merge_context_merge (its_merge_context_ty *context,
+ const char *language,
+ message_list_ty *mlp)
+{
+ size_t i;
+
+ for (i = 0; i < context->nodes.nitems; i++)
+ its_merge_context_merge_node (context, context->nodes.items[i],
+ language,
+ mlp);
+}
+
+struct its_merge_context_ty *
+its_merge_context_alloc (its_rule_list_ty *rules,
+ const char *filename)
+{
+ xmlDoc *doc;
+ struct its_merge_context_ty *result;
+
+ doc = xmlReadFile (filename, NULL,
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOBLANKS
+ | XML_PARSE_NOERROR);
+ if (doc == NULL)
+ {
+ xmlError *err = xmlGetLastError ();
+ error (0, 0, _("cannot read %s: %s"), filename, err->message);
+ return NULL;
+ }
+
+ its_rule_list_apply (rules, doc);
+
+ result = XMALLOC (struct its_merge_context_ty);
+ result->rules = rules;
+ result->doc = doc;
+
+ /* Collect translatable nodes. */
+ memset (&result->nodes, 0, sizeof (struct its_node_list_ty));
+ its_rule_list_extract_nodes (result->rules,
+ &result->nodes,
+ xmlDocGetRootElement (result->doc));
+
+ return result;
+}
+
+void
+its_merge_context_write (struct its_merge_context_ty *context,
+ FILE *fp)
+{
+ xmlDocFormatDump (fp, context->doc, 1);
+}
+
+void
+its_merge_context_free (struct its_merge_context_ty *context)
+{
+ xmlFreeDoc (context->doc);
+ free (context->nodes.items);
+ free (context);
+}
diff --git a/gettext-tools/src/its.h b/gettext-tools/src/its.h
new file mode 100644
index 0000000..8d597f5
--- /dev/null
+++ b/gettext-tools/src/its.h
@@ -0,0 +1,85 @@
+/* Internationalization Tag Set (ITS) handling
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _ITS_H_
+#define _ITS_H_
+
+#include "message.h"
+#include "xgettext.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum its_whitespace_type_ty
+{
+ ITS_WHITESPACE_PRESERVE,
+ ITS_WHITESPACE_NORMALIZE,
+ ITS_WHITESPACE_TRIM
+};
+
+typedef struct its_rule_list_ty its_rule_list_ty;
+
+typedef message_ty *
+ (*its_extract_callback_ty) (message_list_ty *mlp,
+ const char *msgctxt,
+ const char *msgid,
+ lex_pos_ty *pos,
+ const char *extracted_comment,
+ const char *marker,
+ enum its_whitespace_type_ty whitespace);
+
+/* Creates a fresh its_rule_list_ty holding global ITS rules. */
+extern its_rule_list_ty *its_rule_list_alloc (void);
+
+/* Releases memory allocated for RULES. */
+extern void its_rule_list_free (its_rule_list_ty *rules);
+
+/* Loads global ITS rules from STRING. */
+extern bool its_rule_list_add_from_string (struct its_rule_list_ty *rules,
+ const char *rule);
+
+/* Loads global ITS rules from FILENAME. */
+extern bool its_rule_list_add_from_file (its_rule_list_ty *rules,
+ const char *filename);
+
+/* Extracts messages from FP, accoding to the loaded ITS rules. */
+extern void its_rule_list_extract (its_rule_list_ty *rules,
+ FILE *fp, const char *real_filename,
+ const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp,
+ its_extract_callback_ty callback);
+
+typedef struct its_merge_context_ty its_merge_context_ty;
+
+extern its_merge_context_ty *
+ its_merge_context_alloc (its_rule_list_ty *rules, const char *filename);
+extern void its_merge_context_free (its_merge_context_ty *context);
+extern void its_merge_context_merge (its_merge_context_ty *context,
+ const char *language,
+ message_list_ty *mlp);
+
+extern void its_merge_context_write (its_merge_context_ty *context,
+ FILE *fp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ITS_H_ */
diff --git a/gettext-tools/src/lang-table.c b/gettext-tools/src/lang-table.c
index 9cc1f55..ac69021 100644
--- a/gettext-tools/src/lang-table.c
+++ b/gettext-tools/src/lang-table.c
@@ -1,5 +1,5 @@
/* Table of languages.
- Copyright (C) 2001-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2005.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/lang-table.h b/gettext-tools/src/lang-table.h
index e72e4c4..59f5802 100644
--- a/gettext-tools/src/lang-table.h
+++ b/gettext-tools/src/lang-table.h
@@ -1,5 +1,5 @@
/* Table of languages.
- Copyright (C) 2001-2007 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2005.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/libexpat-compat.c b/gettext-tools/src/libexpat-compat.c
deleted file mode 100644
index ad680db..0000000
--- a/gettext-tools/src/libexpat-compat.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/* xgettext libexpat compatibility.
- Copyright (C) 2002-2003, 2005-2009, 2013 Free Software Foundation, Inc.
-
- This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
-
- 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 <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#if DYNLOAD_LIBEXPAT
-# include <dlfcn.h>
-#else
-# if HAVE_LIBEXPAT
-# include <expat.h>
-# endif
-#endif
-
-/* Keep the references to XML_GetCurrent{Line,Column}Number symbols
- before loading libexpat-compat.h, since they are redefined to
- rpl_XML_GetCurrent{Line,Column}Number . */
-#if !DYNLOAD_LIBEXPAT && XML_MAJOR_VERSION >= 2
-static void *p_XML_GetCurrentLineNumber = (void *) &XML_GetCurrentLineNumber;
-static void *p_XML_GetCurrentColumnNumber = (void *) &XML_GetCurrentColumnNumber;
-#endif
-
-#include "libexpat-compat.h"
-
-/* ======================= Different libexpat ABIs. ======================= */
-
-/* There are three different ABIs of libexpat, regarding the functions
- XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber.
- In expat < 2.0, they return an 'int'.
- In expat >= 2.0, they return
- - a 'long' if expat was compiled with the default flags, or
- - a 'long long' if expat was compiled with -DXML_LARGE_SIZE.
- But the <expat.h> include file does not contain the information whether
- expat was compiled with -DXML_LARGE_SIZE; so the include file is lying!
- For this information, we need to call XML_GetFeatureList(), for
- expat >= 2.0.1; for expat = 2.0.0, we have to assume the default flags. */
-
-#if !DYNLOAD_LIBEXPAT && XML_MAJOR_VERSION >= 2
-
-/* expat >= 2.0 -> Return type is 'int64_t' worst-case. */
-
-/* Return true if libexpat was compiled with -DXML_LARGE_SIZE. */
-static bool
-is_XML_LARGE_SIZE_ABI (void)
-{
- static bool tested;
- static bool is_large;
-
- if (!tested)
- {
- const XML_Feature *features;
-
- is_large = false;
- for (features = XML_GetFeatureList (); features->name != NULL; features++)
- if (strcmp (features->name, "XML_LARGE_SIZE") == 0)
- {
- is_large = true;
- break;
- }
-
- tested = true;
- }
- return is_large;
-}
-
-int64_t
-rpl_XML_GetCurrentLineNumber (XML_Parser parser)
-{
- if (is_XML_LARGE_SIZE_ABI ())
- return ((int64_t (*) (XML_Parser)) p_XML_GetCurrentLineNumber) (parser);
- else
- return ((long (*) (XML_Parser)) p_XML_GetCurrentLineNumber) (parser);
-}
-
-int64_t
-rpl_XML_GetCurrentColumnNumber (XML_Parser parser)
-{
- if (is_XML_LARGE_SIZE_ABI ())
- return ((int64_t (*) (XML_Parser)) p_XML_GetCurrentColumnNumber) (parser);
- else
- return ((long (*) (XML_Parser)) p_XML_GetCurrentColumnNumber) (parser);
-}
-#endif
-
-
-/* ===================== Dynamic loading of libexpat. ===================== */
-
-#if DYNLOAD_LIBEXPAT
-
-static XML_Expat_Version (*p_XML_ExpatVersionInfo) (void);
-
-XML_Expat_Version
-XML_ExpatVersionInfo (void)
-{
- return (*p_XML_ExpatVersionInfo) ();
-}
-
-static const XML_Feature * (*p_XML_GetFeatureList) (void);
-
-const XML_Feature *
-XML_GetFeatureList (void)
-{
- return (*p_XML_GetFeatureList) ();
-}
-
-enum XML_Size_ABI
-get_XML_Size_ABI (void)
-{
- static bool tested;
- static enum XML_Size_ABI abi;
-
- if (!tested)
- {
- if (XML_ExpatVersionInfo () .major >= 2)
- /* expat >= 2.0 -> XML_Size is 'int64_t' or 'long'. */
- {
- const XML_Feature *features;
-
- abi = is_long;
- for (features = XML_GetFeatureList ();
- features->name != NULL;
- features++)
- if (strcmp (features->name, "XML_LARGE_SIZE") == 0)
- {
- abi = is_int64_t;
- break;
- }
- }
- else
- /* expat < 2.0 -> XML_Size is 'int'. */
- abi = is_int;
- tested = true;
- }
- return abi;
-}
-
-static XML_Parser (*p_XML_ParserCreate) (const XML_Char *encoding);
-
-XML_Parser
-XML_ParserCreate (const XML_Char *encoding)
-{
- return (*p_XML_ParserCreate) (encoding);
-}
-
-static void (*p_XML_SetElementHandler) (XML_Parser parser,
- XML_StartElementHandler start,
- XML_EndElementHandler end);
-
-void
-XML_SetElementHandler (XML_Parser parser,
- XML_StartElementHandler start,
- XML_EndElementHandler end)
-{
- (*p_XML_SetElementHandler) (parser, start, end);
-}
-
-
-static void (*p_XML_SetCharacterDataHandler) (XML_Parser parser,
- XML_CharacterDataHandler handler);
-
-void
-XML_SetCharacterDataHandler (XML_Parser parser,
- XML_CharacterDataHandler handler)
-{
- (*p_XML_SetCharacterDataHandler) (parser, handler);
-}
-
-
-static void (*p_XML_SetCommentHandler) (XML_Parser parser,
- XML_CommentHandler handler);
-
-void
-XML_SetCommentHandler (XML_Parser parser, XML_CommentHandler handler)
-{
- (*p_XML_SetCommentHandler) (parser, handler);
-}
-
-
-static int (*p_XML_Parse) (XML_Parser parser, const char *s,
- int len, int isFinal);
-
-int
-XML_Parse (XML_Parser parser, const char *s, int len, int isFinal)
-{
- return (*p_XML_Parse) (parser, s, len, isFinal);
-}
-
-
-static enum XML_Error (*p_XML_GetErrorCode) (XML_Parser parser);
-
-enum XML_Error
-XML_GetErrorCode (XML_Parser parser)
-{
- return (*p_XML_GetErrorCode) (parser);
-}
-
-
-static void *p_XML_GetCurrentLineNumber;
-
-int64_t
-XML_GetCurrentLineNumber (XML_Parser parser)
-{
- switch (get_XML_Size_ABI ())
- {
- case is_int:
- return ((int (*) (XML_Parser)) p_XML_GetCurrentLineNumber) (parser);
- case is_long:
- return ((long (*) (XML_Parser)) p_XML_GetCurrentLineNumber) (parser);
- case is_int64_t:
- return ((int64_t (*) (XML_Parser)) p_XML_GetCurrentLineNumber) (parser);
- default:
- abort ();
- }
-}
-
-static void *p_XML_GetCurrentColumnNumber;
-
-int64_t
-XML_GetCurrentColumnNumber (XML_Parser parser)
-{
- switch (get_XML_Size_ABI ())
- {
- case is_int:
- return ((int (*) (XML_Parser)) p_XML_GetCurrentColumnNumber) (parser);
- case is_long:
- return ((long (*) (XML_Parser)) p_XML_GetCurrentColumnNumber) (parser);
- case is_int64_t:
- return ((int64_t (*) (XML_Parser)) p_XML_GetCurrentColumnNumber) (parser);
- default:
- abort ();
- }
-}
-
-
-static const XML_LChar * (*p_XML_ErrorString) (int code);
-
-const XML_LChar *
-XML_ErrorString (int code)
-{
- return (*p_XML_ErrorString) (code);
-}
-
-static void (*p_XML_ParserFree) (XML_Parser parser);
-
-void
-XML_ParserFree (XML_Parser parser)
-{
- return (*p_XML_ParserFree) (parser);
-}
-
-static int libexpat_loaded = 0;
-
-bool
-load_libexpat ()
-{
- if (libexpat_loaded == 0)
- {
- void *handle;
-
- /* Try to load libexpat-2.x. */
- handle = dlopen ("libexpat.so.1", RTLD_LAZY);
- if (handle == NULL)
- /* Try to load libexpat-1.x. */
- handle = dlopen ("libexpat.so.0", RTLD_LAZY);
- if (handle != NULL
- && (p_XML_ExpatVersionInfo =
- (XML_Expat_Version (*) (void))
- dlsym (handle, "XML_ExpatVersionInfo")) != NULL
- && (p_XML_GetFeatureList =
- (const XML_Feature * (*) (void))
- dlsym (handle, "XML_GetFeatureList")) != NULL
- && (p_XML_ParserCreate =
- (XML_Parser (*) (const XML_Char *))
- dlsym (handle, "XML_ParserCreate")) != NULL
- && (p_XML_SetElementHandler =
- (void (*) (XML_Parser, XML_StartElementHandler, XML_EndElementHandler))
- dlsym (handle, "XML_SetElementHandler")) != NULL
- && (p_XML_SetCharacterDataHandler =
- (void (*) (XML_Parser, XML_CharacterDataHandler))
- dlsym (handle, "XML_SetCharacterDataHandler")) != NULL
- && (p_XML_SetCommentHandler =
- (void (*) (XML_Parser, XML_CommentHandler))
- dlsym (handle, "XML_SetCommentHandler")) != NULL
- && (p_XML_Parse =
- (int (*) (XML_Parser, const char *, int, int))
- dlsym (handle, "XML_Parse")) != NULL
- && (p_XML_GetErrorCode =
- (enum XML_Error (*) (XML_Parser))
- dlsym (handle, "XML_GetErrorCode")) != NULL
- && (p_XML_GetCurrentLineNumber =
- dlsym (handle, "XML_GetCurrentLineNumber")) != NULL
- && (p_XML_GetCurrentColumnNumber =
- dlsym (handle, "XML_GetCurrentColumnNumber")) != NULL
- && (p_XML_ParserFree =
- (void (*) (XML_Parser))
- dlsym (handle, "XML_ParserFree")) != NULL
- && (p_XML_ErrorString =
- (const XML_LChar * (*) (int))
- dlsym (handle, "XML_ErrorString")) != NULL)
- libexpat_loaded = 1;
- else
- libexpat_loaded = -1;
- }
- return libexpat_loaded >= 0;
-}
-
-#endif
diff --git a/gettext-tools/src/libexpat-compat.h b/gettext-tools/src/libexpat-compat.h
deleted file mode 100644
index 2ff6465..0000000
--- a/gettext-tools/src/libexpat-compat.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* xgettext libexpat compatibility.
- Copyright (C) 2002-2003, 2005-2009, 2013 Free Software Foundation, Inc.
-
- This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
-
- 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 <http://www.gnu.org/licenses/>. */
-
-#include <stdbool.h>
-#include <stdint.h>
-#if DYNLOAD_LIBEXPAT
-# include <dlfcn.h>
-#else
-# if HAVE_LIBEXPAT
-# include <expat.h>
-# endif
-#endif
-
-#if !DYNLOAD_LIBEXPAT && XML_MAJOR_VERSION >= 2
-int64_t rpl_XML_GetCurrentLineNumber (XML_Parser parser);
-# undef XML_GetCurrentLineNumber
-# define XML_GetCurrentLineNumber rpl_XML_GetCurrentLineNumber
-
-int64_t rpl_XML_GetCurrentColumnNumber (XML_Parser parser);
-# undef XML_GetCurrentColumnNumber
-# define XML_GetCurrentColumnNumber rpl_XML_GetCurrentColumnNumber
-#endif
-
-/* ===================== Dynamic loading of libexpat. ===================== */
-
-#if DYNLOAD_LIBEXPAT
-typedef struct
- {
- int major;
- int minor;
- int micro;
- }
- XML_Expat_Version;
-enum XML_FeatureEnum { XML_FEATURE_END = 0 };
-typedef struct
- {
- enum XML_FeatureEnum feature;
- const char *name;
- long int value;
- }
- XML_Feature;
-typedef void *XML_Parser;
-typedef char XML_Char;
-typedef char XML_LChar;
-enum XML_Error { XML_ERROR_NONE };
-typedef void (*XML_StartElementHandler) (void *userData, const XML_Char *name, const XML_Char **atts);
-typedef void (*XML_EndElementHandler) (void *userData, const XML_Char *name);
-typedef void (*XML_CharacterDataHandler) (void *userData, const XML_Char *s, int len);
-typedef void (*XML_CommentHandler) (void *userData, const XML_Char *data);
-
-XML_Expat_Version XML_ExpatVersionInfo (void);
-const XML_Feature * XML_GetFeatureList (void);
-
-enum XML_Size_ABI { is_int, is_long, is_int64_t };
-enum XML_Size_ABI get_XML_Size_ABI (void);
-
-XML_Parser XML_ParserCreate (const XML_Char *encoding);
-void XML_SetElementHandler (XML_Parser parser,
- XML_StartElementHandler start,
- XML_EndElementHandler end);
-void XML_SetCharacterDataHandler (XML_Parser parser,
- XML_CharacterDataHandler handler);
-void XML_SetCommentHandler (XML_Parser parser, XML_CommentHandler handler);
-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);
-int64_t XML_GetCurrentColumnNumber (XML_Parser parser);
-const XML_LChar * XML_ErrorString (int code);
-void XML_ParserFree (XML_Parser parser);
-
-bool load_libexpat ();
-
-#define LIBEXPAT_AVAILABLE() (load_libexpat ())
-
-#elif HAVE_LIBEXPAT
-
-#define LIBEXPAT_AVAILABLE() true
-
-#endif
diff --git a/gettext-tools/src/locating-rule.c b/gettext-tools/src/locating-rule.c
new file mode 100644
index 0000000..2a1de19
--- /dev/null
+++ b/gettext-tools/src/locating-rule.c
@@ -0,0 +1,437 @@
+/* XML resource locating rules
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "locating-rule.h"
+
+#include "basename.h"
+#include "concat-filename.h"
+#include "c-strcase.h"
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+
+#if HAVE_DIRENT_H
+# define HAVE_DIR 1
+#else
+# define HAVE_DIR 0
+#endif
+
+#include "dir-list.h"
+#include <errno.h>
+#include "error.h"
+#include "filename.h"
+#include <fnmatch.h>
+#include "gettext.h"
+#include "hash.h"
+#include <libxml/parser.h>
+#include <libxml/uri.h>
+#include "xalloc.h"
+
+#define _(str) gettext (str)
+
+#define LOCATING_RULES_NS "https://www.gnu.org/s/gettext/ns/locating-rules/1.0"
+
+struct document_locating_rule_ty
+{
+ char *ns;
+ char *local_name;
+
+ char *target;
+};
+
+struct document_locating_rule_list_ty
+{
+ struct document_locating_rule_ty *items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+struct locating_rule_ty
+{
+ char *pattern;
+ char *name;
+
+ struct document_locating_rule_list_ty doc_rules;
+ char *target;
+};
+
+struct locating_rule_list_ty
+{
+ struct locating_rule_ty *items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+static char *
+get_attribute (xmlNode *node, const char *attr)
+{
+ xmlChar *value;
+ char *result;
+
+ value = xmlGetProp (node, BAD_CAST attr);
+ result = xstrdup ((const char *) value);
+ xmlFree (value);
+
+ return result;
+}
+
+static const char *
+document_locating_rule_match (struct document_locating_rule_ty *rule,
+ xmlDoc *doc)
+{
+ xmlNode *root;
+
+ root = xmlDocGetRootElement (doc);
+ if (rule->ns != NULL)
+ {
+ if (root->ns == NULL
+ || !xmlStrEqual (root->ns->href, BAD_CAST rule->ns))
+ return NULL;
+ }
+
+ if (rule->local_name != NULL)
+ {
+ if (!xmlStrEqual (root->name,
+ BAD_CAST rule->local_name))
+ return NULL;
+ }
+
+ return rule->target;
+}
+
+static const char *
+locating_rule_match (struct locating_rule_ty *rule,
+ const char *filename,
+ const char *name)
+{
+ if (name != NULL)
+ {
+ if (rule->name == NULL || c_strcasecmp (name, rule->name) != 0)
+ return NULL;
+ }
+ else
+ {
+ const char *base;
+ char *reduced;
+ int err;
+
+ base = strrchr (filename, '/');
+ if (!base)
+ base = filename;
+
+ reduced = xstrdup (base);
+ /* Remove a trailing ".in" - it's a generic suffix. */
+ while (strlen (reduced) >= 3
+ && memcmp (reduced + strlen (reduced) - 3, ".in", 3) == 0)
+ reduced[strlen (reduced) - 3] = '\0';
+
+ err = fnmatch (rule->pattern, basename (reduced), FNM_PATHNAME);
+ free (reduced);
+ if (err != 0)
+ return NULL;
+ }
+
+ /* Check documentRules. */
+ if (rule->doc_rules.nitems > 0)
+ {
+ const char *target;
+ xmlDoc *doc;
+ size_t i;
+
+ doc = xmlReadFile (filename, NULL,
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOBLANKS
+ | XML_PARSE_NOERROR);
+ if (doc == NULL)
+ {
+ xmlError *err = xmlGetLastError ();
+ error (0, 0, _("cannot read %s: %s"), filename, err->message);
+ return NULL;
+ }
+
+ for (i = 0, target = NULL; i < rule->doc_rules.nitems; i++)
+ {
+ target =
+ document_locating_rule_match (&rule->doc_rules.items[i], doc);
+ if (target)
+ break;
+ }
+ xmlFreeDoc (doc);
+ if (target != NULL)
+ return target;
+ }
+
+ if (rule->target != NULL)
+ return rule->target;
+
+ return NULL;
+}
+
+const char *
+locating_rule_list_locate (struct locating_rule_list_ty *rules,
+ const char *filename,
+ const char *name)
+{
+ const char *target = NULL;
+ size_t i;
+
+ for (i = 0; i < rules->nitems; i++)
+ {
+ if (IS_ABSOLUTE_PATH (filename))
+ {
+ target = locating_rule_match (&rules->items[i], filename, name);
+ if (target != NULL)
+ return target;
+ }
+ else
+ {
+ int j;
+
+ for (j = 0; ; ++j)
+ {
+ const char *dir = dir_list_nth (j);
+ char *new_filename;
+
+ if (dir == NULL)
+ break;
+
+ new_filename = xconcatenated_filename (dir, filename, NULL);
+ target = locating_rule_match (&rules->items[i], new_filename,
+ name);
+ free (new_filename);
+ if (target != NULL)
+ return target;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void
+missing_attribute (xmlNode *node, const char *attribute)
+{
+ error (0, 0, _("\"%s\" node does not have \"%s\""), node->name, attribute);
+}
+
+static void
+document_locating_rule_destroy (struct document_locating_rule_ty *rule)
+{
+ free (rule->ns);
+ free (rule->local_name);
+ free (rule->target);
+}
+
+static void
+document_locating_rule_list_add (struct document_locating_rule_list_ty *rules,
+ xmlNode *node)
+{
+ struct document_locating_rule_ty rule;
+
+ if (!xmlHasProp (node, BAD_CAST "target"))
+ {
+ missing_attribute (node, "target");
+ return;
+ }
+
+ memset (&rule, 0, sizeof (struct document_locating_rule_ty));
+
+ if (xmlHasProp (node, BAD_CAST "ns"))
+ rule.ns = get_attribute (node, "ns");
+ if (xmlHasProp (node, BAD_CAST "localName"))
+ rule.local_name = get_attribute (node, "localName");
+ rule.target = get_attribute (node, "target");
+
+ if (rules->nitems == rules->nitems_max)
+ {
+ rules->nitems_max = 2 * rules->nitems_max + 1;
+ rules->items =
+ xrealloc (rules->items,
+ sizeof (struct document_locating_rule_ty)
+ * rules->nitems_max);
+ }
+ memcpy (&rules->items[rules->nitems++], &rule,
+ sizeof (struct document_locating_rule_ty));
+}
+
+static void
+locating_rule_destroy (struct locating_rule_ty *rule)
+{
+ size_t i;
+
+ for (i = 0; i < rule->doc_rules.nitems; i++)
+ document_locating_rule_destroy (&rule->doc_rules.items[i]);
+ free (rule->doc_rules.items);
+
+ free (rule->name);
+ free (rule->pattern);
+ free (rule->target);
+}
+
+static bool
+locating_rule_list_add_from_file (struct locating_rule_list_ty *rules,
+ const char *rule_file_name)
+{
+ xmlDoc *doc;
+ xmlNode *root, *node;
+
+ doc = xmlReadFile (rule_file_name, "utf-8",
+ XML_PARSE_NONET
+ | XML_PARSE_NOWARNING
+ | XML_PARSE_NOBLANKS
+ | XML_PARSE_NOERROR);
+ if (doc == NULL)
+ {
+ error (0, 0, _("cannot read XML file %s"), rule_file_name);
+ return false;
+ }
+
+ root = xmlDocGetRootElement (doc);
+ if (!(xmlStrEqual (root->name, BAD_CAST "locatingRules")
+#if 0
+ && root->ns
+ && xmlStrEqual (root->ns->href, BAD_CAST LOCATING_RULES_NS)
+#endif
+ ))
+ {
+ error (0, 0, _("the root element is not \"locatingRules\""));
+ xmlFreeDoc (doc);
+ return false;
+ }
+
+ for (node = root->children; node; node = node->next)
+ {
+ if (xmlStrEqual (node->name, BAD_CAST "locatingRule"))
+ {
+ struct locating_rule_ty rule;
+
+ if (!xmlHasProp (node, BAD_CAST "pattern"))
+ {
+ missing_attribute (node, "pattern");
+ xmlFreeDoc (doc);
+ continue;
+ }
+
+ memset (&rule, 0, sizeof (struct locating_rule_ty));
+ rule.pattern = get_attribute (node, "pattern");
+ if (xmlHasProp (node, BAD_CAST "name"))
+ rule.name = get_attribute (node, "name");
+ if (xmlHasProp (node, BAD_CAST "target"))
+ rule.target = get_attribute (node, "target");
+ else
+ {
+ xmlNode *n;
+
+ for (n = node->children; n; n = n->next)
+ {
+ if (xmlStrEqual (n->name, BAD_CAST "documentRule"))
+ document_locating_rule_list_add (&rule.doc_rules, n);
+ }
+ }
+ if (rules->nitems == rules->nitems_max)
+ {
+ rules->nitems_max = 2 * rules->nitems_max + 1;
+ rules->items =
+ xrealloc (rules->items,
+ sizeof (struct locating_rule_ty) * rules->nitems_max);
+ }
+ memcpy (&rules->items[rules->nitems++], &rule,
+ sizeof (struct locating_rule_ty));
+ }
+ }
+
+ xmlFreeDoc (doc);
+ return true;
+}
+
+bool
+locating_rule_list_add_from_directory (struct locating_rule_list_ty *rules,
+ const char *directory)
+{
+#if HAVE_DIR
+ DIR *dirp;
+
+ dirp = opendir (directory);
+ if (dirp == NULL)
+ return false;
+
+ for (;;)
+ {
+ struct dirent *dp;
+
+ errno = 0;
+ dp = readdir (dirp);
+ if (dp != NULL)
+ {
+ const char *name = dp->d_name;
+ size_t namlen = strlen (name);
+
+ if (namlen > 4 && memcmp (name + namlen - 4, ".loc", 4) == 0)
+ {
+ char *locator_file_name =
+ xconcatenated_filename (directory, name, NULL);
+ locating_rule_list_add_from_file (rules, locator_file_name);
+ free (locator_file_name);
+ }
+ }
+ else if (errno != 0)
+ return false;
+ else
+ break;
+ }
+ if (closedir (dirp))
+ return false;
+
+#endif
+ return true;
+}
+
+struct locating_rule_list_ty *
+locating_rule_list_alloc (void)
+{
+ struct locating_rule_list_ty *result;
+
+ xmlCheckVersion (LIBXML_VERSION);
+
+ result = XCALLOC (1, struct locating_rule_list_ty);
+
+ return result;
+}
+
+void
+locating_rule_list_destroy (struct locating_rule_list_ty *rules)
+{
+ while (rules->nitems-- > 0)
+ locating_rule_destroy (&rules->items[rules->nitems]);
+ free (rules->items);
+}
+
+void
+locating_rule_list_free (struct locating_rule_list_ty *rules)
+{
+ if (rules != NULL)
+ locating_rule_list_destroy (rules);
+ free (rules);
+}
diff --git a/gettext-tools/src/locating-rule.h b/gettext-tools/src/locating-rule.h
new file mode 100644
index 0000000..f1214bc
--- /dev/null
+++ b/gettext-tools/src/locating-rule.h
@@ -0,0 +1,50 @@
+/* XML resource locating rules
+ Copyright (C) 2015 Free Software Foundation, Inc.
+
+ This file was written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _LOCATING_RULE_H
+#define _LOCATING_RULE_H
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct locating_rule_list_ty locating_rule_list_ty;
+
+/* Creates a fresh locating_rule_list_ty. */
+extern struct locating_rule_list_ty *locating_rule_list_alloc (void);
+
+extern bool
+ locating_rule_list_add_from_directory (locating_rule_list_ty *rules,
+ const char *directory);
+
+/* Determines the location of resource associated with FILENAME,
+ accoding to the loaded locating rules. */
+extern const char *locating_rule_list_locate (locating_rule_list_ty *rules,
+ const char *filename,
+ const char *name);
+
+/* Releases memory allocated for RULES. */
+extern void locating_rule_list_free (locating_rule_list_ty *rules);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LOCATING_RULE_H */
diff --git a/gettext-tools/src/message.c b/gettext-tools/src/message.c
index 586675f..bc1604c 100644
--- a/gettext-tools/src/message.c
+++ b/gettext-tools/src/message.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
@@ -58,6 +59,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 +91,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"
@@ -104,6 +107,14 @@ possible_format_p (enum is_format is_format)
}
+const char *const syntax_check_name[NSYNTAXCHECKS] =
+{
+ /* sc_ellipsis_unicode */ "ellipsis-unicode",
+ /* sc_space_ellipsis */ "space-ellipsis",
+ /* sc_quote_unicode */ "quote-unicode"
+};
+
+
message_ty *
message_alloc (const char *msgctxt,
const char *msgid, const char *msgid_plural,
@@ -130,6 +141,8 @@ message_alloc (const char *msgctxt,
mp->range.min = -1;
mp->range.max = -1;
mp->do_wrap = undecided;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ mp->do_syntax_check[i] = undecided;
mp->prev_msgctxt = NULL;
mp->prev_msgid = NULL;
mp->prev_msgid_plural = NULL;
@@ -235,6 +248,8 @@ message_copy (message_ty *mp)
result->is_format[i] = mp->is_format[i];
result->range = mp->range;
result->do_wrap = mp->do_wrap;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ result->do_syntax_check[i] = mp->do_syntax_check[i];
for (j = 0; j < mp->filepos_count; ++j)
{
lex_pos_ty *pp = &mp->filepos[j];
diff --git a/gettext-tools/src/message.h b/gettext-tools/src/message.h
index bf2215a..ec86ff1 100644
--- a/gettext-tools/src/message.h
+++ b/gettext-tools/src/message.h
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
@@ -67,11 +68,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];
@@ -114,6 +116,29 @@ enum is_wrap
#endif
+/* Kinds of syntax checks which apply to strings. */
+enum syntax_check_type
+{
+ sc_ellipsis_unicode,
+ sc_space_ellipsis,
+ sc_quote_unicode
+};
+#define NSYNTAXCHECKS 3
+extern DLL_VARIABLE const char *const syntax_check_name[NSYNTAXCHECKS];
+
+/* Is current msgid subject to a syntax check? */
+#if 0
+enum is_syntax_check
+{
+ undecided,
+ yes,
+ no
+};
+#else /* HACK - C's enum concept is so stupid */
+#define is_syntax_check is_format
+#endif
+
+
struct altstr
{
const char *msgstr;
@@ -175,6 +200,9 @@ struct message_ty
/* Do we want the string to be wrapped in the emitted PO file? */
enum is_wrap do_wrap;
+ /* Do we want to apply extra syntax checks on the string? */
+ enum is_syntax_check do_syntax_check[NSYNTAXCHECKS];
+
/* The prev_msgctxt, prev_msgid and prev_msgid_plural strings appearing
before the message, if present. Generated by msgmerge. */
const char *prev_msgctxt;
diff --git a/gettext-tools/src/msgattrib.c b/gettext-tools/src/msgattrib.c
index 326f28c..1f945b6 100644
--- a/gettext-tools/src/msgattrib.c
+++ b/gettext-tools/src/msgattrib.c
@@ -1,5 +1,6 @@
/* Manipulates attributes of messages in translation catalogs.
- Copyright (C) 2001-2007, 2009-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2009-2010, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgcat.c b/gettext-tools/src/msgcat.c
index 0cc432c..c0b6fd4 100644
--- a/gettext-tools/src/msgcat.c
+++ b/gettext-tools/src/msgcat.c
@@ -1,5 +1,6 @@
/* Concatenates several translation catalogs.
- Copyright (C) 2001-2007, 2009-2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2009-2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgcmp.c b/gettext-tools/src/msgcmp.c
index f82131d..4fadbb6 100644
--- a/gettext-tools/src/msgcmp.c
+++ b/gettext-tools/src/msgcmp.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2010, 2012, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgcomm.c b/gettext-tools/src/msgcomm.c
index daddf2b..c731297 100644
--- a/gettext-tools/src/msgcomm.c
+++ b/gettext-tools/src/msgcomm.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1997-1998, 2000-2007, 2009-2012 Free Software Foundation, Inc.
+ Copyright (C) 1997-1998, 2000-2007, 2009-2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/msgconv.c b/gettext-tools/src/msgconv.c
index 5c9f7ea..e407ac6 100644
--- a/gettext-tools/src/msgconv.c
+++ b/gettext-tools/src/msgconv.c
@@ -1,5 +1,6 @@
/* Converts a translation catalog to a different character encoding.
- Copyright (C) 2001-2007, 2009-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2009-2010, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgen.c b/gettext-tools/src/msgen.c
index e33c61a..e6eda09 100644
--- a/gettext-tools/src/msgen.c
+++ b/gettext-tools/src/msgen.c
@@ -1,5 +1,6 @@
/* Creates an English translation catalog.
- Copyright (C) 2001-2007, 2009-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2009-2010, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgexec.c b/gettext-tools/src/msgexec.c
index 5239518..e7594fc 100644
--- a/gettext-tools/src/msgexec.c
+++ b/gettext-tools/src/msgexec.c
@@ -1,5 +1,5 @@
/* Pass translations to a subprocess.
- Copyright (C) 2001-2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
@@ -71,6 +71,8 @@ static const char *sub_path;
static char **sub_argv;
static int sub_argc;
+static bool newline;
+
/* Maximum exit code encountered. */
static int exitcode;
@@ -80,6 +82,7 @@ static const struct option long_options[] =
{ "directory", required_argument, NULL, 'D' },
{ "help", no_argument, NULL, 'h' },
{ "input", required_argument, NULL, 'i' },
+ { "newline", no_argument, NULL, CHAR_MAX + 2 },
{ "properties-input", no_argument, NULL, 'P' },
{ "stringtable-input", no_argument, NULL, CHAR_MAX + 1 },
{ "version", no_argument, NULL, 'V' },
@@ -167,6 +170,10 @@ main (int argc, char **argv)
input_syntax = &input_format_stringtable;
break;
+ case CHAR_MAX + 2: /* --newline */
+ newline = true;
+ break;
+
default:
usage (EXIT_FAILURE);
break;
@@ -274,6 +281,11 @@ null byte. The output of \"msgexec 0\" is suitable as input for \"xargs -0\".\n
"));
printf ("\n");
printf (_("\
+Command input:\n"));
+ printf (_("\
+ --newline add newline at the end of input\n"));
+ printf ("\n");
+ printf (_("\
Mandatory arguments to long options are mandatory for short options too.\n"));
printf ("\n");
printf (_("\
@@ -352,6 +364,7 @@ process_string (const message_ty *mp, const char *str, size_t len)
int fd[1];
void (*orig_sigpipe_handler)(int);
int exitstatus;
+ char *newstr;
/* Set environment variables for the subprocess.
Note: These environment variables, especially MSGEXEC_MSGCTXT and
@@ -399,11 +412,23 @@ process_string (const message_ty *mp, const char *str, size_t len)
successfully without having read all of the input that we feed it. */
orig_sigpipe_handler = signal (SIGPIPE, SIG_IGN);
- if (full_write (fd[0], str, len) < len)
+ if (newline)
+ {
+ newstr = XNMALLOC (len + 1, char);
+ memcpy (newstr, str, len);
+ newstr[len++] = '\n';
+ }
+ else
+ newstr = (char *) str;
+
+ if (full_write (fd[0], newstr, len) < len)
if (errno != EPIPE)
error (EXIT_FAILURE, errno,
_("write to %s subprocess failed"), sub_name);
+ if (newstr != str)
+ free (newstr);
+
close (fd[0]);
signal (SIGPIPE, orig_sigpipe_handler);
diff --git a/gettext-tools/src/msgfilter.c b/gettext-tools/src/msgfilter.c
index f9cb1cc..aa358e1 100644
--- a/gettext-tools/src/msgfilter.c
+++ b/gettext-tools/src/msgfilter.c
@@ -1,5 +1,5 @@
/* Edit translations using a subprocess.
- Copyright (C) 2001-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2010, 2012, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
@@ -81,6 +81,8 @@ static const char *sub_path;
static const char **sub_argv;
static int sub_argc;
+static bool newline;
+
/* Filter function. */
static void (*filter) (const char *str, size_t len, char **resultp, size_t *lengthp);
@@ -96,6 +98,7 @@ static const struct option long_options[] =
{ "indent", no_argument, NULL, CHAR_MAX + 1 },
{ "input", required_argument, NULL, 'i' },
{ "keep-header", no_argument, &keep_header, 1 },
+ { "newline", no_argument, NULL, CHAR_MAX + 9 },
{ "no-escape", no_argument, NULL, CHAR_MAX + 2 },
{ "no-location", no_argument, NULL, CHAR_MAX + 8 },
{ "no-wrap", no_argument, NULL, CHAR_MAX + 3 },
@@ -269,6 +272,10 @@ main (int argc, char **argv)
message_print_style_filepos (filepos_comment_none);
break;
+ case CHAR_MAX + 9: /* --newline */
+ newline = true;
+ break;
+
default:
usage (EXIT_FAILURE);
break;
@@ -438,6 +445,12 @@ and writes a modified translation to standard output.\n\
"));
printf ("\n");
printf (_("\
+Filter input and output:\n"));
+ printf (_("\
+ --newline add a newline at the end of input and\n\
+ remove a newline from the end of output"));
+ printf ("\n");
+ printf (_("\
Useful FILTER-OPTIONs when the FILTER is 'sed':\n"));
printf (_("\
-e, --expression=SCRIPT add SCRIPT to the commands to be executed\n"));
@@ -628,6 +641,35 @@ process_string (const char *str, size_t len, char **resultp, size_t *lengthp)
}
+/* Do the same thing as process_string but append a newline to STR
+ before processing, and remove a newline from the result.
+ */
+static void
+process_string_with_newline (const char *str, size_t len, char **resultp,
+ size_t *lengthp)
+{
+ char *newstr;
+ char *result;
+ size_t length;
+
+ newstr = XNMALLOC (len + 1, char);
+ memcpy (newstr, str, len);
+ newstr[len] = '\n';
+
+ process_string (newstr, len + 1, &result, &length);
+
+ free (newstr);
+
+ if (length > 0 && result[length - 1] == '\n')
+ result[--length] = '\0';
+ else
+ error (0, 0, _("filter output is not terminated with a newline"));
+
+ *resultp = result;
+ *lengthp = length;
+}
+
+
static void
process_message (message_ty *mp)
{
@@ -705,7 +747,12 @@ process_message (message_ty *mp)
}
else
unsetenv ("MSGFILTER_PLURAL_FORM");
- process_string (p, strlen (p), &result, &length);
+
+ if (newline)
+ process_string_with_newline (p, strlen (p), &result, &length);
+ else
+ process_string (p, strlen (p), &result, &length);
+
result = (char *) xrealloc (result, length + 1);
result[length] = '\0';
substrings[k] = result;
diff --git a/gettext-tools/src/msgfmt.c b/gettext-tools/src/msgfmt.c
index 3fabd87..0517c99 100644
--- a/gettext-tools/src/msgfmt.c
+++ b/gettext-tools/src/msgfmt.c
@@ -1,5 +1,6 @@
/* Converts Uniforum style .po files to binary .mo files
- Copyright (C) 1995-1998, 2000-2007, 2009-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2007, 2009-2010, 2012, 2015 Free
+ Software Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
@@ -49,6 +50,7 @@
#include "write-tcl.h"
#include "write-qt.h"
#include "write-desktop.h"
+#include "write-xml.h"
#include "propername.h"
#include "message.h"
#include "open-catalog.h"
@@ -61,10 +63,14 @@
#include "msgl-check.h"
#include "msgl-iconv.h"
#include "concat-filename.h"
+#include "its.h"
+#include "locating-rule.h"
#include "gettext.h"
#define _(str) gettext (str)
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+
/* Contains exit status for case in which no premature exit occurs. */
static int exit_status;
@@ -110,6 +116,14 @@ static const char *desktop_base_directory;
static hash_table desktop_keywords;
static bool desktop_default_keywords = true;
+/* XML mode output file specification. */
+static bool xml_mode;
+static const char *xml_locale_name;
+static const char *xml_template_name;
+static const char *xml_base_directory;
+static const char *xml_language;
+static its_rule_list_ty *xml_its_rules;
+
/* We may have more than one input file. Domains with same names in
different files have to merged. So we need a list of tables for
each output file. */
@@ -180,6 +194,7 @@ static const struct option long_options[] =
{ "java", no_argument, NULL, 'j' },
{ "java2", no_argument, NULL, CHAR_MAX + 5 },
{ "keyword", required_argument, NULL, 'k' },
+ { "language", required_argument, NULL, 'L' },
{ "locale", required_argument, NULL, 'l' },
{ "no-hash", no_argument, NULL, CHAR_MAX + 6 },
{ "output-file", required_argument, NULL, 'o' },
@@ -196,6 +211,7 @@ static const struct option long_options[] =
{ "use-untranslated", no_argument, NULL, CHAR_MAX + 12 },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
+ { "xml", no_argument, NULL, 'x' },
{ NULL, 0, NULL, 0 }
};
@@ -211,11 +227,14 @@ static struct msg_domain *new_domain (const char *name, const char *file_name);
static bool is_nonobsolete (const message_ty *mp);
static void read_catalog_file_msgfmt (char *filename,
catalog_input_format_ty input_syntax);
-static string_list_ty *get_languages (const char *directory);
static int msgfmt_desktop_bulk (const char *directory,
const char *template_file_name,
hash_table *keywords,
const char *file_name);
+static int msgfmt_xml_bulk (const char *directory,
+ const char *template_file_name,
+ its_rule_list_ty *its_rules,
+ const char *file_name);
int
@@ -252,8 +271,8 @@ main (int argc, char *argv[])
/* Ensure that write errors on stdout are detected. */
atexit (close_stdout);
- while ((opt = getopt_long (argc, argv, "a:cCd:D:fhjl:o:Pr:vV", long_options,
- NULL))
+ while ((opt = getopt_long (argc, argv, "a:cCd:D:fhjl:L:o:Pr:vVx",
+ long_options, NULL))
!= EOF)
switch (opt)
{
@@ -281,6 +300,7 @@ main (int argc, char *argv[])
csharp_base_directory = optarg;
tcl_base_directory = optarg;
desktop_base_directory = optarg;
+ xml_base_directory = optarg;
break;
case 'D':
dir_list_append (optarg);
@@ -313,6 +333,10 @@ main (int argc, char *argv[])
csharp_locale_name = optarg;
tcl_locale_name = optarg;
desktop_locale_name = optarg;
+ xml_locale_name = optarg;
+ break;
+ case 'L':
+ xml_language = optarg;
break;
case 'o':
output_file_name = optarg;
@@ -333,6 +357,9 @@ main (int argc, char *argv[])
case 'V':
do_version = true;
break;
+ case 'x':
+ xml_mode = true;
+ break;
case CHAR_MAX + 1: /* --check-accelerators */
check_accelerators = true;
if (optarg != NULL)
@@ -402,6 +429,7 @@ main (int argc, char *argv[])
break;
case CHAR_MAX + 16: /* --template=TEMPLATE */
desktop_template_name = optarg;
+ xml_template_name = optarg;
break;
default:
usage (EXIT_FAILURE);
@@ -428,16 +456,20 @@ There is NO WARRANTY, to the extent permitted by law.\n\
usage (EXIT_SUCCESS);
/* Test whether we have a .po file name as argument. */
- if (optind >= argc && !(desktop_mode && desktop_base_directory))
+ if (optind >= argc
+ && !(desktop_mode && desktop_base_directory)
+ && !(xml_mode && xml_base_directory))
{
error (EXIT_SUCCESS, 0, _("no input file given"));
usage (EXIT_FAILURE);
}
- if (optind < argc && desktop_mode && desktop_base_directory)
+ if (optind < argc
+ && ((desktop_mode && desktop_base_directory)
+ || (xml_mode && xml_base_directory)))
{
error (EXIT_SUCCESS, 0,
_("no input file should be given if %s and %s are specified"),
- "--desktop", "-d");
+ desktop_mode ? "--desktop" : "--xml", "-d");
usage (EXIT_FAILURE);
}
@@ -449,10 +481,11 @@ There is NO WARRANTY, to the extent permitted by law.\n\
| (csharp_resources_mode ? 4 : 0)
| (tcl_mode ? 8 : 0)
| (qt_mode ? 16 : 0)
- | (desktop_mode ? 32 : 0);
+ | (desktop_mode ? 32 : 0)
+ | (xml_mode ? 64 : 0);
static const char *mode_options[] =
{ "--java", "--csharp", "--csharp-resources", "--tcl", "--qt",
- "--desktop" };
+ "--desktop", "--xml" };
/* More than one bit set? */
if (modes & (modes - 1))
{
@@ -558,6 +591,34 @@ There is NO WARRANTY, to the extent permitted by law.\n\
usage (EXIT_FAILURE);
}
}
+ else if (xml_mode)
+ {
+ if (xml_template_name == NULL)
+ {
+ error (EXIT_SUCCESS, 0,
+ _("%s requires a \"--template template\" specification"),
+ "--xml");
+ usage (EXIT_FAILURE);
+ }
+ if (output_file_name == NULL)
+ {
+ error (EXIT_SUCCESS, 0,
+ _("%s requires a \"-o file\" specification"),
+ "--xml");
+ usage (EXIT_FAILURE);
+ }
+ if (xml_base_directory != NULL && xml_locale_name != NULL)
+ error (EXIT_FAILURE, 0,
+ _("%s and %s are mutually exclusive in %s"),
+ "-d", "-l", "--xml");
+ if (xml_base_directory == NULL && xml_locale_name == NULL)
+ {
+ error (EXIT_SUCCESS, 0,
+ _("%s requires a \"-l locale\" specification"),
+ "--xml");
+ usage (EXIT_FAILURE);
+ }
+ }
else
{
if (java_resource_name != NULL)
@@ -600,6 +661,80 @@ There is NO WARRANTY, to the extent permitted by law.\n\
exit (exit_status);
}
+ if (xml_mode)
+ {
+ const char *gettextdatadir;
+ char *versioned_gettextdatadir;
+ char *its_dirs[2] = { NULL, NULL };
+ locating_rule_list_ty *its_locating_rules;
+ const char *its_basename;
+ size_t i;
+
+ /* Make it possible to override the locator file location. This
+ is necessary for running the testsuite before "make
+ install". */
+ gettextdatadir = getenv ("GETTEXTDATADIR");
+ if (gettextdatadir == NULL || gettextdatadir[0] == '\0')
+ gettextdatadir = relocate (GETTEXTDATADIR);
+
+ its_dirs[0] = xconcatenated_filename (gettextdatadir, "its", NULL);
+
+ versioned_gettextdatadir =
+ xasprintf ("%s%s", relocate (GETTEXTDATADIR), PACKAGE_SUFFIX);
+ its_dirs[1] = xconcatenated_filename (versioned_gettextdatadir, "its",
+ NULL);
+ free (versioned_gettextdatadir);
+
+ its_locating_rules = locating_rule_list_alloc ();
+ for (i = 0; i < SIZEOF (its_dirs); i++)
+ locating_rule_list_add_from_directory (its_locating_rules, its_dirs[i]);
+
+ its_basename = locating_rule_list_locate (its_locating_rules,
+ xml_template_name,
+ xml_language);
+
+ if (its_basename != NULL)
+ {
+ size_t j;
+
+ xml_its_rules = its_rule_list_alloc ();
+ for (j = 0; j < SIZEOF (its_dirs); j++)
+ {
+ char *its_filename =
+ xconcatenated_filename (its_dirs[j], its_basename, NULL);
+ struct stat statbuf;
+ bool ok = false;
+
+ if (stat (its_filename, &statbuf) == 0)
+ ok = its_rule_list_add_from_file (xml_its_rules, its_filename);
+ free (its_filename);
+ if (ok)
+ break;
+ }
+ if (j == SIZEOF (its_dirs))
+ {
+ its_rule_list_free (xml_its_rules);
+ xml_its_rules = NULL;
+ }
+ }
+ locating_rule_list_free (its_locating_rules);
+
+ if (xml_its_rules == NULL)
+ error (EXIT_FAILURE, 0, _("cannot locate ITS rules for %s"),
+ xml_template_name);
+ }
+
+ /* Bulk processing mode for XML files.
+ Process all .po files in xml_base_directory. */
+ if (xml_mode && xml_base_directory)
+ {
+ exit_status = msgfmt_xml_bulk (xml_base_directory,
+ xml_template_name,
+ xml_its_rules,
+ output_file_name);
+ exit (exit_status);
+ }
+
/* The -o option determines the name of the domain and therefore
the output file. */
if (output_file_name != NULL)
@@ -705,6 +840,15 @@ There is NO WARRANTY, to the extent permitted by law.\n\
if (desktop_keywords.table != NULL)
hash_destroy (&desktop_keywords);
}
+ else if (xml_mode)
+ {
+ if (msgdomain_write_xml (domain->mlp, canon_encoding,
+ xml_locale_name,
+ xml_template_name,
+ xml_its_rules,
+ domain->file_name))
+ exit_status = EXIT_FAILURE;
+ }
else
{
if (msgdomain_write_mo (domain->mlp, domain->domain_name,
@@ -810,6 +954,8 @@ Operation mode:\n"));
--qt Qt mode: generate a Qt .qm file\n"));
printf (_("\
--desktop Desktop Entry mode: generate a .desktop file\n"));
+ printf (_("\
+ --xml XML mode: generate XML file\n"));
printf ("\n");
printf (_("\
Output file location:\n"));
@@ -876,6 +1022,22 @@ The -l, -o, and --template options are mandatory. If -D is specified, input\n\
files are read from the directory instead of the command line arguments.\n"));
printf ("\n");
printf (_("\
+XML mode options:\n"));
+ printf (_("\
+ -l, --locale=LOCALE locale name, either language or language_COUNTRY\n"));
+ printf (_("\
+ -L, --language=NAME recognise the specified XML language\n"));
+ printf (_("\
+ -o, --output-file=FILE write output to specified file\n"));
+ printf (_("\
+ --template=TEMPLATE an XML file used as a template\n"));
+ printf (_("\
+ -d DIRECTORY base directory of .po files\n"));
+ printf (_("\
+The -l, -o, and --template options are mandatory. If -D is specified, input\n\
+files are read from the directory instead of the command line arguments.\n"));
+ printf ("\n");
+ printf (_("\
Input file syntax:\n"));
printf (_("\
-P, --properties-input input files are in Java .properties syntax\n"));
@@ -1063,7 +1225,7 @@ msgfmt_set_domain (default_catalog_reader_ty *this, char *name)
/* If no output file was given, we change it with each 'domain'
directive. */
if (!java_mode && !csharp_mode && !csharp_resources_mode && !tcl_mode
- && !qt_mode && !desktop_mode && output_file_name == NULL)
+ && !qt_mode && !desktop_mode && !xml_mode && output_file_name == NULL)
{
size_t correct;
@@ -1297,35 +1459,30 @@ add_languages (string_list_ty *languages, string_list_ty *desired_languages,
/* Compute the languages list by reading the "LINGUAS" envvar or the
LINGUAS file under DIRECTORY. */
-static string_list_ty *
-get_languages (const char *directory)
+static void
+get_languages (string_list_ty *languages, const char *directory)
{
char *envval;
- string_list_ty *languages;
- string_list_ty *desired_languages = NULL;
- char *linguas_file_name;
+ string_list_ty real_desired_languages, *desired_languages = NULL;
+ char *linguas_file_name = NULL;
struct stat statbuf;
FILE *fp;
size_t line_len = 0;
char *line_buf = NULL;
- languages = string_list_alloc ();
envval = getenv ("LINGUAS");
if (envval)
{
- desired_languages = string_list_alloc ();
- add_languages (desired_languages, NULL, envval, strlen (envval));
+ string_list_init (&real_desired_languages);
+ add_languages (&real_desired_languages, NULL, envval, strlen (envval));
+ desired_languages = &real_desired_languages;
}
linguas_file_name = xconcatenated_filename (directory, "LINGUAS", NULL);
if (stat (linguas_file_name, &statbuf) < 0)
{
error (EXIT_SUCCESS, 0, _("%s does not exist"), linguas_file_name);
- string_list_free (languages);
- if (desired_languages != NULL)
- string_list_free (desired_languages);
- free (linguas_file_name);
- return NULL;
+ goto out;
}
fp = fopen (linguas_file_name, "r");
@@ -1333,11 +1490,7 @@ get_languages (const char *directory)
{
error (EXIT_SUCCESS, 0, _("%s exists but cannot read"),
linguas_file_name);
- string_list_free (languages);
- if (desired_languages != NULL)
- string_list_free (desired_languages);
- free (linguas_file_name);
- return NULL;
+ goto out;
}
while (!feof (fp))
@@ -1367,32 +1520,68 @@ get_languages (const char *directory)
free (line_buf);
fclose (fp);
+
+ out:
if (desired_languages != NULL)
- string_list_free (desired_languages);
+ string_list_destroy (desired_languages);
free (linguas_file_name);
+}
+
+static void
+msgfmt_operand_list_init (msgfmt_operand_list_ty *operands)
+{
+ operands->items = NULL;
+ operands->nitems = 0;
+ operands->nitems_max = 0;
+}
+
+static void
+msgfmt_operand_list_destroy (msgfmt_operand_list_ty *operands)
+{
+ size_t i;
- return languages;
+ for (i = 0; i < operands->nitems; i++)
+ {
+ free (operands->items[i].language);
+ message_list_free (operands->items[i].mlp, 0);
+ }
+ free (operands->items);
+}
+
+static void
+msgfmt_operand_list_append (msgfmt_operand_list_ty *operands,
+ const char *language,
+ message_list_ty *messages)
+{
+ msgfmt_operand_ty *operand;
+
+ if (operands->nitems == operands->nitems_max)
+ {
+ operands->nitems_max = operands->nitems_max * 2 + 1;
+ operands->items = xrealloc (operands->items,
+ sizeof (msgfmt_operand_ty)
+ * operands->nitems_max);
+ }
+
+ operand = &operands->items[operands->nitems++];
+ operand->language = xstrdup (language);
+ operand->mlp = messages;
}
-/* Helper function to support 'bulk' operation mode of --desktop.
- This reads all .po files in DIRECTORY and merges them into a
- .desktop file FILE_NAME. Currently it does not support some
- options available in 'iterative' mode, such as --statistics. */
static int
-msgfmt_desktop_bulk (const char *directory,
- const char *template_file_name,
- hash_table *keywords,
- const char *file_name)
+msgfmt_operand_list_add_from_directory (msgfmt_operand_list_ty *operands,
+ const char *directory)
{
- string_list_ty *languages = NULL;
- message_list_ty **messages = NULL;
+ string_list_ty languages;
void *saved_dir_list;
int retval = 0;
size_t i;
- languages = get_languages (directory);
- if (!languages)
- return EXIT_FAILURE;
+ string_list_init (&languages);
+ get_languages (&languages, directory);
+
+ if (languages.nitems == 0)
+ return 0;
/* Reset the directory search list so only .po files under DIRECTORY
will be read. */
@@ -1400,34 +1589,35 @@ msgfmt_desktop_bulk (const char *directory,
dir_list_append (directory);
/* Read all .po files. */
- messages = XNMALLOC (languages->nitems, message_list_ty *);
- for (i = 0; i < languages->nitems; i++)
+ for (i = 0; i < languages.nitems; i++)
{
- const char *language = languages->item[i];
+ const char *language = languages.item[i];
+ message_list_ty *mlp;
char *input_file_name;
int nerrors;
- current_domain = new_domain (file_name, file_name);
+ current_domain = new_domain (MESSAGE_DOMAIN_DEFAULT,
+ add_mo_suffix (MESSAGE_DOMAIN_DEFAULT));
input_file_name = xconcatenated_filename ("", language, ".po");
read_catalog_file_msgfmt (input_file_name, &input_format_po);
free (input_file_name);
- /* The domain directive is not supported by --desktop mode.
+ /* The domain directive is not supported in the bulk execution mode.
Thus, domain_list should always contain a single domain. */
assert (current_domain == domain_list && domain_list->next == NULL);
- messages[i] = current_domain->mlp;
+ mlp = current_domain->mlp;
free (current_domain);
current_domain = domain_list = NULL;
/* Remove obsolete messages. They were only needed for duplicate
checking. */
- message_list_remove_if_not (messages[i], is_nonobsolete);
+ message_list_remove_if_not (mlp, is_nonobsolete);
/* Perform all kinds of checks: plural expressions, format
strings, ... */
nerrors =
- check_message_list (messages[i],
+ check_message_list (mlp,
/* Untranslated and fuzzy messages have already
been dealt with during parsing, see below in
msgfmt_frob_new_message. */
@@ -1436,38 +1626,92 @@ msgfmt_desktop_bulk (const char *directory,
check_compatibility,
check_accelerators, accelerator_char);
- /* Exit with status 1 on any error. */
+ retval += nerrors;
if (nerrors > 0)
{
error (0, 0,
ngettext ("found %d fatal error", "found %d fatal errors",
nerrors),
nerrors);
- retval = EXIT_FAILURE;
- goto out;
+ continue;
}
/* Convert the messages to Unicode. */
- iconv_message_list (messages[i], NULL, po_charset_utf8, NULL);
+ iconv_message_list (mlp, NULL, po_charset_utf8, NULL);
+
+ msgfmt_operand_list_append (operands, language, mlp);
+ }
+
+ string_list_destroy (&languages);
+ dir_list_restore (saved_dir_list);
+
+ return retval;
+}
+
+/* Helper function to support 'bulk' operation mode of --desktop.
+ This reads all .po files in DIRECTORY and merges them into a
+ .desktop file FILE_NAME. Currently it does not support some
+ options available in 'iterative' mode, such as --statistics. */
+static int
+msgfmt_desktop_bulk (const char *directory,
+ const char *template_file_name,
+ hash_table *keywords,
+ const char *file_name)
+{
+ msgfmt_operand_list_ty operands;
+ int nerrors, status;
+
+ msgfmt_operand_list_init (&operands);
+
+ /* Read all .po files. */
+ nerrors = msgfmt_operand_list_add_from_directory (&operands, directory);
+ if (nerrors > 0)
+ {
+ msgfmt_operand_list_destroy (&operands);
+ return 1;
}
/* Write the messages into .desktop file. */
- if (msgdomain_write_desktop_bulk (languages,
- messages,
- template_file_name,
- keywords,
- file_name))
+ status = msgdomain_write_desktop_bulk (&operands,
+ template_file_name,
+ keywords,
+ file_name);
+
+ msgfmt_operand_list_destroy (&operands);
+
+ return status;
+}
+
+/* Helper function to support 'bulk' operation mode of --xml.
+ This reads all .po files in DIRECTORY and merges them into an
+ XML file FILE_NAME. Currently it does not support some
+ options available in 'iterative' mode, such as --statistics. */
+static int
+msgfmt_xml_bulk (const char *directory,
+ const char *template_file_name,
+ its_rule_list_ty *its_rules,
+ const char *file_name)
+{
+ msgfmt_operand_list_ty operands;
+ int nerrors, status;
+
+ msgfmt_operand_list_init (&operands);
+
+ /* Read all .po files. */
+ nerrors = msgfmt_operand_list_add_from_directory (&operands, directory);
+ if (nerrors > 0)
{
- retval = EXIT_FAILURE;
- goto out;
+ msgfmt_operand_list_destroy (&operands);
+ return 1;
}
- out:
- dir_list_restore (saved_dir_list);
- for (i = 0; i < languages->nitems; i++)
- message_list_free (messages[i], 0);
- free (messages);
- string_list_free (languages);
+ /* Write the messages into .xml file. */
+ status = msgdomain_write_xml_bulk (&operands,
+ template_file_name,
+ its_rules,
+ file_name);
- return retval;
+ msgfmt_operand_list_destroy (&operands);
+
+ return status;
}
diff --git a/gettext-tools/src/msgfmt.cs b/gettext-tools/src/msgfmt.cs
index e2f9e7d..1a97f64 100644
--- a/gettext-tools/src/msgfmt.cs
+++ b/gettext-tools/src/msgfmt.cs
@@ -1,5 +1,5 @@
/* GNU gettext for C#
- * Copyright (C) 2003 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2015 Free Software Foundation, Inc.
* Written by Bruno Haible <bruno@clisp.org>, 2003.
*
* This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgfmt.h b/gettext-tools/src/msgfmt.h
index e61f72c..3651a30 100644
--- a/gettext-tools/src/msgfmt.h
+++ b/gettext-tools/src/msgfmt.h
@@ -1,5 +1,6 @@
/* msgfmt specifics
- Copyright (C) 1995-1998, 2000-2001, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2001, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
@@ -18,10 +19,36 @@
#ifndef _MSGFMT_H
#define _MSGFMT_H
+#include "message.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Be more verbose. Use only 'fprintf' and 'multiline_warning' but not
'error' or 'multiline_error' to emit verbosity messages, because 'error'
and 'multiline_error' during PO file parsing cause the program to exit
with EXIT_FAILURE. See function lex_end(). */
extern int verbose;
+/* Data types for bulk operation mode. */
+typedef struct msgfmt_operand_ty msgfmt_operand_ty;
+struct msgfmt_operand_ty
+{
+ char *language;
+ message_list_ty *mlp;
+};
+
+typedef struct msgfmt_operand_list_ty msgfmt_operand_list_ty;
+struct msgfmt_operand_list_ty
+{
+ msgfmt_operand_ty *items;
+ size_t nitems;
+ size_t nitems_max;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _MSGFMT_H */
diff --git a/gettext-tools/src/msggrep.c b/gettext-tools/src/msggrep.c
index 73ccb94..b0cb87a 100644
--- a/gettext-tools/src/msggrep.c
+++ b/gettext-tools/src/msggrep.c
@@ -1,5 +1,6 @@
/* Extract some translations of a translation catalog.
- Copyright (C) 2001-2007, 2009-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2009-2010, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msginit.c b/gettext-tools/src/msginit.c
index 951aa2e..f85b83c 100644
--- a/gettext-tools/src/msginit.c
+++ b/gettext-tools/src/msginit.c
@@ -1,5 +1,5 @@
/* Initializes a new PO file.
- Copyright (C) 2001-2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
@@ -649,7 +649,7 @@ catalogname_for_locale (const char *locale)
"pa_IN", /* Punjabi India */
"pag_PH", /* Pangasinan Philippines */
"pam_PH", /* Pampanga Philippines */
- "pap_AN", /* Papiamento Netherlands Antilles */
+ "pap_AN", /* Papiamento Netherlands Antilles - this line can be removed in 2018 */
"pbb_CO", /* Páez Colombia */
"pl_PL", /* Polish Poland */
"ps_AF", /* Pashto Afghanistan */
@@ -676,7 +676,6 @@ catalogname_for_locale (const char *locale)
"so_SO", /* Somali Somalia */
"sq_AL", /* Albanian Albania */
"sr_RS", /* Serbian Serbia */
- "sr_YU", /* Serbian Yugoslavia - this line can be removed in 2010 */
"srr_SN", /* Serer Senegal */
"suk_TZ", /* Sukuma Tanzania */
"sus_GN", /* Susu Guinea */
@@ -1333,6 +1332,8 @@ content_transfer_encoding ()
static const char *
plural_forms ()
{
+ const char *gettextcldrdir;
+ char *prog = NULL;
size_t i;
/* Search for a formula depending on the catalogname. */
@@ -1345,6 +1346,85 @@ plural_forms ()
if (strcmp (plural_table[i].lang, language) == 0)
return plural_table[i].value;
+ gettextcldrdir = getenv ("GETTEXTCLDRDIR");
+ if (gettextcldrdir != NULL && gettextcldrdir[0] != '\0')
+ {
+ const char *gettextlibdir;
+ char *dirs[3], *last_dir;
+ char *argv[4];
+ pid_t child;
+ int fd[1];
+ FILE *fp;
+ char *line;
+ size_t linesize;
+ size_t linelen;
+ int exitstatus;
+
+ gettextlibdir = getenv ("GETTEXTLIBDIR");
+ if (gettextlibdir == NULL || gettextlibdir[0] == '\0')
+ gettextlibdir = relocate (LIBDIR "/gettext");
+
+ prog = xconcatenated_filename (gettextlibdir, "cldr-plurals", NULL);
+
+ last_dir = xstrdup (gettextcldrdir);
+ dirs[0] = "common";
+ dirs[1] = "supplemental";
+ dirs[2] = "plurals.xml";
+ for (i = 0; i < SIZEOF (dirs); i++)
+ {
+ char *dir = xconcatenated_filename (last_dir, dirs[i], NULL);
+ free (last_dir);
+ last_dir = dir;
+ }
+
+ /* Call the cldr-plurals command. */
+ argv[0] = "cldr-plurals";
+ argv[1] = (char *) language;
+ argv[2] = last_dir;
+ argv[3] = NULL;
+ child = create_pipe_in (prog, prog, argv, DEV_NULL,
+ false, true, false,
+ fd);
+ free (last_dir);
+ if (child == -1)
+ goto failed;
+
+ /* Retrieve its result. */
+ fp = fdopen (fd[0], "r");
+ if (fp == NULL)
+ {
+ error (0, errno, _("fdopen() failed"));
+ goto failed;
+ }
+
+ line = NULL; linesize = 0;
+ linelen = getline (&line, &linesize, fp);
+ if (linelen == (size_t)(-1))
+ {
+ error (0, 0, _("%s subprocess I/O error"), prog);
+ fclose (fp);
+ goto failed;
+ }
+ if (linelen > 0 && line[linelen - 1] == '\n')
+ line[linelen - 1] = '\0';
+
+ fclose (fp);
+
+ /* Remove zombie process from process list, and retrieve exit status. */
+ exitstatus = wait_subprocess (child, prog, false, false, true, false,
+ NULL);
+ if (exitstatus != 0)
+ {
+ error (0, 0, _("%s subprocess failed with exit code %d"),
+ prog, exitstatus);
+ goto failed;
+ }
+
+ return line;
+ }
+
+ failed:
+ free (prog);
return NULL;
}
diff --git a/gettext-tools/src/msgl-ascii.c b/gettext-tools/src/msgl-ascii.c
index e3ca953..c92e4df 100644
--- a/gettext-tools/src/msgl-ascii.c
+++ b/gettext-tools/src/msgl-ascii.c
@@ -1,5 +1,6 @@
/* Message list test for ASCII character set.
- Copyright (C) 2001-2002, 2005-2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002, 2005-2006, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-ascii.h b/gettext-tools/src/msgl-ascii.h
index fee41a9..b6e09f9 100644
--- a/gettext-tools/src/msgl-ascii.h
+++ b/gettext-tools/src/msgl-ascii.h
@@ -1,5 +1,5 @@
/* Message list test for ASCII character set.
- Copyright (C) 2001-2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-cat.c b/gettext-tools/src/msgl-cat.c
index 0bd58d4..dfedcb6 100644
--- a/gettext-tools/src/msgl-cat.c
+++ b/gettext-tools/src/msgl-cat.c
@@ -1,5 +1,6 @@
/* Message list concatenation and duplicate handling.
- Copyright (C) 2001-2003, 2005-2008, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2008, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
@@ -308,6 +309,8 @@ domain \"%s\" in input file '%s' doesn't contain a header entry with a charset s
tmp->range.min = - INT_MAX;
tmp->range.max = - INT_MAX;
tmp->do_wrap = yes; /* may be set to no later */
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ tmp->do_syntax_check[i] = undecided; /* may be set to yes/no later */
tmp->obsolete = true; /* may be set to false later */
tmp->alternative_count = 0;
tmp->alternative = NULL;
@@ -535,6 +538,8 @@ UTF-8 encoded from the beginning, i.e. already in your source code files.\n"),
tmp->is_format[i] = mp->is_format[i];
tmp->range = mp->range;
tmp->do_wrap = mp->do_wrap;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ tmp->do_syntax_check[i] = mp->do_syntax_check[i];
tmp->prev_msgctxt = mp->prev_msgctxt;
tmp->prev_msgid = mp->prev_msgid;
tmp->prev_msgid_plural = mp->prev_msgid_plural;
@@ -583,6 +588,9 @@ UTF-8 encoded from the beginning, i.e. already in your source code files.\n"),
}
if (tmp->do_wrap == undecided)
tmp->do_wrap = mp->do_wrap;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ if (tmp->do_syntax_check[i] == undecided)
+ tmp->do_syntax_check[i] = mp->do_syntax_check[i];
tmp->obsolete = false;
}
else
@@ -635,6 +643,12 @@ UTF-8 encoded from the beginning, i.e. already in your source code files.\n"),
}
if (mp->do_wrap == no)
tmp->do_wrap = no;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ if (mp->do_syntax_check[i] == yes)
+ tmp->do_syntax_check[i] = yes;
+ else if (mp->do_syntax_check[i] == no
+ && tmp->do_syntax_check[i] == undecided)
+ tmp->do_syntax_check[i] = no;
/* Don't fill tmp->prev_msgid in this case. */
if (!mp->obsolete)
tmp->obsolete = false;
diff --git a/gettext-tools/src/msgl-cat.h b/gettext-tools/src/msgl-cat.h
index 4de35d5..12a9f80 100644
--- a/gettext-tools/src/msgl-cat.h
+++ b/gettext-tools/src/msgl-cat.h
@@ -1,5 +1,5 @@
/* Message list concatenation and duplicate handling.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-charset.c b/gettext-tools/src/msgl-charset.c
index e8deb58..278d270 100644
--- a/gettext-tools/src/msgl-charset.c
+++ b/gettext-tools/src/msgl-charset.c
@@ -1,5 +1,6 @@
/* Message list charset and locale charset handling.
- Copyright (C) 2001-2003, 2005-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2007, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-charset.h b/gettext-tools/src/msgl-charset.h
index 647a394..c673d1d 100644
--- a/gettext-tools/src/msgl-charset.h
+++ b/gettext-tools/src/msgl-charset.h
@@ -1,5 +1,5 @@
/* Message list charset and locale charset handling.
- Copyright (C) 2001-2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-check.c b/gettext-tools/src/msgl-check.c
index d6f4a3d..7934120 100644
--- a/gettext-tools/src/msgl-check.c
+++ b/gettext-tools/src/msgl-check.c
@@ -1,5 +1,6 @@
/* Checking of messages in PO files.
- Copyright (C) 1995-1998, 2000-2008, 2010-2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2008, 2010-2015 Free Software
+ Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
@@ -40,6 +41,10 @@
#include "plural-table.h"
#include "c-strstr.h"
#include "message.h"
+#include "quote.h"
+#include "sentence.h"
+#include "unictype.h"
+#include "unistr.h"
#include "gettext.h"
#define _(str) gettext (str)
@@ -912,3 +917,204 @@ check_message_list (message_list_ty *mlp,
return seen_errors;
}
+
+
+static int
+syntax_check_ellipsis_unicode (const message_ty *mp, const char *msgid)
+{
+ const char *str = msgid;
+ const char *str_limit = str + strlen (msgid);
+ int seen_errors = 0;
+
+ while (str < str_limit)
+ {
+ const char *end, *cp;
+ ucs4_t ending_char;
+
+ end = sentence_end (str, &ending_char);
+
+ /* sentence_end doesn't treat '...' specially. */
+ cp = end - (ending_char == '.' ? 2 : 3);
+ if (cp >= str && memcmp (cp, "...", 3) == 0)
+ {
+ po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false,
+ _("ASCII ellipsis ('...') instead of Unicode"));
+ seen_errors++;
+ }
+
+ str = end + 1;
+ }
+
+ return seen_errors;
+}
+
+
+static int
+syntax_check_space_ellipsis (const message_ty *mp, const char *msgid)
+{
+ const char *str = msgid;
+ const char *str_limit = str + strlen (msgid);
+ int seen_errors = 0;
+
+ while (str < str_limit)
+ {
+ const char *end, *ellipsis = NULL;
+ ucs4_t ending_char;
+
+ end = sentence_end (str, &ending_char);
+
+ if (ending_char == 0x2026)
+ ellipsis = end;
+ else if (ending_char == '.')
+ {
+ /* sentence_end doesn't treat '...' specially. */
+ const char *cp = end - 2;
+ if (cp >= str && memcmp (cp, "...", 3) == 0)
+ ellipsis = cp;
+ }
+ else
+ {
+ /* Look for a '...'. */
+ const char *cp = end - 3;
+ if (cp >= str && memcmp (cp, "...", 3) == 0)
+ ellipsis = cp;
+ else
+ {
+ ucs4_t uc = 0xfffd;
+
+ /* Look for a U+2026. */
+ for (cp = end - 1; cp >= str; cp--)
+ {
+ u8_mbtouc (&uc, (const unsigned char *) cp, ellipsis - cp);
+ if (uc != 0xfffd)
+ break;
+ }
+
+ if (uc == 0x2026)
+ ellipsis = cp;
+ }
+ }
+
+ if (ellipsis)
+ {
+ const char *cp;
+ ucs4_t uc = 0xfffd;
+
+ /* Look at the character before ellipsis. */
+ for (cp = ellipsis - 1; cp >= str; cp--)
+ {
+ u8_mbtouc (&uc, (const unsigned char *) cp, ellipsis - cp);
+ if (uc != 0xfffd)
+ break;
+ }
+
+ if (uc != 0xfffd && uc_is_space (uc))
+ {
+ po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false,
+ _("\
+space before ellipsis found in user visible strings"));
+ seen_errors++;
+ }
+ }
+
+ str = end + 1;
+ }
+
+ return seen_errors;
+}
+
+
+struct callback_arg
+{
+ const message_ty *mp;
+ int seen_errors;
+};
+
+static void
+syntax_check_quote_unicode_callback (char quote, const char *quoted,
+ size_t quoted_length, void *data)
+{
+ struct callback_arg *arg = data;
+
+ switch (quote)
+ {
+ case '"':
+ po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false,
+ _("ASCII double quote used instead of Unicode"));
+ arg->seen_errors++;
+ break;
+
+ case '\'':
+ po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false,
+ _("ASCII single quote used instead of Unicode"));
+ arg->seen_errors++;
+ break;
+
+ default:
+ break;
+ }
+}
+
+static int
+syntax_check_quote_unicode (const message_ty *mp, const char *msgid)
+{
+ struct callback_arg arg;
+
+ arg.mp = mp;
+ arg.seen_errors = 0;
+
+ scan_quoted (msgid, strlen (msgid),
+ syntax_check_quote_unicode_callback, &arg);
+
+ return arg.seen_errors;
+}
+
+
+typedef int (* syntax_check_function) (const message_ty *mp, const char *msgid);
+static const syntax_check_function sc_funcs[NSYNTAXCHECKS] =
+{
+ syntax_check_ellipsis_unicode,
+ syntax_check_space_ellipsis,
+ syntax_check_quote_unicode
+};
+
+/* Perform all syntax checks on a non-obsolete message.
+ Return the number of errors that were seen. */
+static int
+syntax_check_message (const message_ty *mp)
+{
+ int seen_errors = 0;
+ int i;
+
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ {
+ if (mp->do_syntax_check[i] == yes)
+ {
+ seen_errors += sc_funcs[i] (mp, mp->msgid);
+ if (mp->msgid_plural)
+ seen_errors += sc_funcs[i] (mp, mp->msgid_plural);
+ }
+ }
+
+ return seen_errors;
+}
+
+
+/* Perform all syntax checks on a message list.
+ Return the number of errors that were seen. */
+int
+syntax_check_message_list (message_list_ty *mlp)
+{
+ int seen_errors = 0;
+ size_t j;
+
+ for (j = 0; j < mlp->nitems; j++)
+ {
+ message_ty *mp = mlp->item[j];
+
+ if (!is_header (mp))
+ seen_errors += syntax_check_message (mp);
+ }
+
+ return seen_errors;
+}
diff --git a/gettext-tools/src/msgl-check.h b/gettext-tools/src/msgl-check.h
index f03300c..cfb86fb 100644
--- a/gettext-tools/src/msgl-check.h
+++ b/gettext-tools/src/msgl-check.h
@@ -1,5 +1,5 @@
/* Checking of messages in PO files.
- Copyright (C) 2005, 2008, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2008, 2010, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2005.
This program is free software: you can redistribute it and/or modify
@@ -60,6 +60,9 @@ extern int check_message_list (message_list_ty *mlp,
int check_compatibility,
int check_accelerators, char accelerator_char);
+/* Perform all syntax checks on a message list.
+ Return the number of errors that were seen. */
+extern int syntax_check_message_list (message_list_ty *mlp);
#ifdef __cplusplus
}
diff --git a/gettext-tools/src/msgl-english.c b/gettext-tools/src/msgl-english.c
index 69d95a9..6304504 100644
--- a/gettext-tools/src/msgl-english.c
+++ b/gettext-tools/src/msgl-english.c
@@ -1,5 +1,5 @@
/* Message translation initialization for English.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-english.h b/gettext-tools/src/msgl-english.h
index ec77d2a..ce0af6b 100644
--- a/gettext-tools/src/msgl-english.h
+++ b/gettext-tools/src/msgl-english.h
@@ -1,5 +1,5 @@
/* Message translation initialization for English.
- Copyright (C) 2001-2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-equal.c b/gettext-tools/src/msgl-equal.c
index 3c9efad..fd28d01 100644
--- a/gettext-tools/src/msgl-equal.c
+++ b/gettext-tools/src/msgl-equal.c
@@ -1,5 +1,6 @@
/* Message list test for equality.
- Copyright (C) 2001-2002, 2005-2006, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002, 2005-2006, 2008, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-equal.h b/gettext-tools/src/msgl-equal.h
index 6497a7f..07f052e 100644
--- a/gettext-tools/src/msgl-equal.h
+++ b/gettext-tools/src/msgl-equal.h
@@ -1,5 +1,5 @@
/* Message list test for equality.
- Copyright (C) 2001-2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-fsearch.c b/gettext-tools/src/msgl-fsearch.c
index d2aa865..5e087e2 100644
--- a/gettext-tools/src/msgl-fsearch.c
+++ b/gettext-tools/src/msgl-fsearch.c
@@ -1,5 +1,5 @@
/* Fast fuzzy searching among messages.
- Copyright (C) 2006, 2008, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2008, 2011, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2006.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-fsearch.h b/gettext-tools/src/msgl-fsearch.h
index c523d93..825e2a8 100644
--- a/gettext-tools/src/msgl-fsearch.h
+++ b/gettext-tools/src/msgl-fsearch.h
@@ -1,5 +1,5 @@
/* Fast fuzzy searching among messages.
- Copyright (C) 2006, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2008, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2006.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-header.c b/gettext-tools/src/msgl-header.c
index d1dafdb..d5f6a88 100644
--- a/gettext-tools/src/msgl-header.c
+++ b/gettext-tools/src/msgl-header.c
@@ -1,5 +1,5 @@
/* Message list header manipulation.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2007.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-header.h b/gettext-tools/src/msgl-header.h
index f26b1a8..6dc1779 100644
--- a/gettext-tools/src/msgl-header.h
+++ b/gettext-tools/src/msgl-header.h
@@ -1,5 +1,5 @@
/* Message list header manipulation.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2007.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-iconv.c b/gettext-tools/src/msgl-iconv.c
index 958455b..06a961f 100644
--- a/gettext-tools/src/msgl-iconv.c
+++ b/gettext-tools/src/msgl-iconv.c
@@ -1,5 +1,6 @@
/* Message list charset and locale charset handling.
- Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2009, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgl-iconv.h b/gettext-tools/src/msgl-iconv.h
index 5a7fc00..ab61a5b 100644
--- a/gettext-tools/src/msgl-iconv.h
+++ b/gettext-tools/src/msgl-iconv.h
@@ -1,5 +1,6 @@
/* Message list character set conversion.
- Copyright (C) 2001-2003, 2005-2006, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2006, 2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgmerge.c b/gettext-tools/src/msgmerge.c
index d8e02ae..50faf2d 100644
--- a/gettext-tools/src/msgmerge.c
+++ b/gettext-tools/src/msgmerge.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2010, 2012, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
This program is free software: you can redistribute it and/or modify
@@ -1025,8 +1026,9 @@ message_merge (message_ty *def, message_ty *ref, bool force_fuzzy,
char *extended =
(char *) obstack_alloc (&pool,
header_fields[UNKNOWN].len + len + 1);
- memcpy (extended, header_fields[UNKNOWN].string,
- header_fields[UNKNOWN].len);
+ if (header_fields[UNKNOWN].string)
+ memcpy (extended, header_fields[UNKNOWN].string,
+ header_fields[UNKNOWN].len);
memcpy (&extended[header_fields[UNKNOWN].len], cp, len);
extended[header_fields[UNKNOWN].len + len] = '\0';
header_fields[UNKNOWN].string = extended;
@@ -1329,6 +1331,9 @@ message_merge (message_ty *def, message_ty *ref, bool force_fuzzy,
result->do_wrap = ref->do_wrap;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ result->do_syntax_check[i] = ref->do_syntax_check[i];
+
/* Insert previous msgid, commented out with "#|".
Do so only when --previous is specified, for backward compatibility.
Since the "previous msgid" represents the original msgid that led to
diff --git a/gettext-tools/src/msgunfmt.c b/gettext-tools/src/msgunfmt.c
index 1e6dbd2..c5163be 100644
--- a/gettext-tools/src/msgunfmt.c
+++ b/gettext-tools/src/msgunfmt.c
@@ -1,5 +1,6 @@
/* msgunfmt - converts binary .mo files to Uniforum style .po files
- Copyright (C) 1995-1998, 2000-2007, 2009-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2007, 2009-2010, 2012, 2015 Free
+ Software Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgunfmt.cs b/gettext-tools/src/msgunfmt.cs
index 28a66b8..e0e8874 100644
--- a/gettext-tools/src/msgunfmt.cs
+++ b/gettext-tools/src/msgunfmt.cs
@@ -1,5 +1,5 @@
/* GNU gettext for C#
- * Copyright (C) 2003-2004, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2003-2004, 2007, 2015 Free Software Foundation, Inc.
* Written by Bruno Haible <bruno@clisp.org>, 2003.
*
* This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgunfmt.h b/gettext-tools/src/msgunfmt.h
index d1d79ec..fc0a505 100644
--- a/gettext-tools/src/msgunfmt.h
+++ b/gettext-tools/src/msgunfmt.h
@@ -1,5 +1,6 @@
/* msgunfmt specifics
- Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2001, 2015 Free Software Foundation,
+ Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/msgunfmt.tcl b/gettext-tools/src/msgunfmt.tcl
index 11c1d6f..2eadbc5 100644
--- a/gettext-tools/src/msgunfmt.tcl
+++ b/gettext-tools/src/msgunfmt.tcl
@@ -1,5 +1,5 @@
# Reading tcl/msgcat .msg files.
-# Copyright (C) 2002 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2015 Free Software Foundation, Inc.
#
# 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
diff --git a/gettext-tools/src/msguniq.c b/gettext-tools/src/msguniq.c
index 24f4c31..0a81d1e 100644
--- a/gettext-tools/src/msguniq.c
+++ b/gettext-tools/src/msguniq.c
@@ -1,5 +1,6 @@
/* Remove, select or merge duplicate translations.
- Copyright (C) 2001-2007, 2009-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2009-2010, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/open-catalog.c b/gettext-tools/src/open-catalog.c
index 27eed90..ed87010 100644
--- a/gettext-tools/src/open-catalog.c
+++ b/gettext-tools/src/open-catalog.c
@@ -1,5 +1,6 @@
/* open-po - search for .po file along search path list and open for reading
- Copyright (C) 1995-1996, 2000-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 2000-2003, 2005-2009, 2015 Free Software
+ Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/open-catalog.h b/gettext-tools/src/open-catalog.h
index 503371d..282c200 100644
--- a/gettext-tools/src/open-catalog.h
+++ b/gettext-tools/src/open-catalog.h
@@ -1,5 +1,6 @@
/* Opening PO files.
- Copyright (C) 1995-1997, 2000-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1995-1997, 2000-2003, 2006, 2015 Free Software
+ Foundation, Inc.
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
diff --git a/gettext-tools/src/plural-count.c b/gettext-tools/src/plural-count.c
index 3fd8838..802ba5e 100644
--- a/gettext-tools/src/plural-count.c
+++ b/gettext-tools/src/plural-count.c
@@ -1,5 +1,5 @@
/* Plural form count.
- Copyright (C) 2003, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2007, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/plural-count.h b/gettext-tools/src/plural-count.h
index 14eccf9..9b86a17 100644
--- a/gettext-tools/src/plural-count.h
+++ b/gettext-tools/src/plural-count.h
@@ -1,5 +1,5 @@
/* Plural form count.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/plural-distrib.h b/gettext-tools/src/plural-distrib.h
index 4376f9f..d7d2493 100644
--- a/gettext-tools/src/plural-distrib.h
+++ b/gettext-tools/src/plural-distrib.h
@@ -1,5 +1,5 @@
/* Value distribution of plural form expressions.
- Copyright (C) 2001-2008 Free Software Foundation, Inc.
+ Copyright (C) 2001-2008, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2001-2005.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/plural-eval.c b/gettext-tools/src/plural-eval.c
index 6c63d4e..b2ab856 100644
--- a/gettext-tools/src/plural-eval.c
+++ b/gettext-tools/src/plural-eval.c
@@ -1,5 +1,5 @@
/* Expression evaluation for plural form selection.
- Copyright (C) 2000-2003, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2000-2003, 2005, 2015 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/plural-eval.h b/gettext-tools/src/plural-eval.h
index b64c079..e480a9b 100644
--- a/gettext-tools/src/plural-eval.h
+++ b/gettext-tools/src/plural-eval.h
@@ -1,5 +1,5 @@
/* Expression evaluation for plural form selection.
- Copyright (C) 2005-2006 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2005.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/plural-exp.c b/gettext-tools/src/plural-exp.c
index d3f4b5f..eb57ce1 100644
--- a/gettext-tools/src/plural-exp.c
+++ b/gettext-tools/src/plural-exp.c
@@ -1,5 +1,5 @@
/* Expression parsing for plural form selection.
- Copyright (C) 2000-2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2000-2001, 2003, 2015 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/plural-table.c b/gettext-tools/src/plural-table.c
index 556cbcc..25c0bd6 100644
--- a/gettext-tools/src/plural-table.c
+++ b/gettext-tools/src/plural-table.c
@@ -1,5 +1,6 @@
/* Table of known plural form expressions.
- Copyright (C) 2001-2006, 2009-2010 Free Software Foundation, Inc.
+ Copyright (C) 2001-2006, 2009-2010, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/plural-table.h b/gettext-tools/src/plural-table.h
index 6af9bf6..7c82480 100644
--- a/gettext-tools/src/plural-table.h
+++ b/gettext-tools/src/plural-table.h
@@ -1,5 +1,5 @@
/* Table of known plural form expressions.
- Copyright (C) 2001-2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-charset.c b/gettext-tools/src/po-charset.c
index 4c0dcdb..2f8bae4 100644
--- a/gettext-tools/src/po-charset.c
+++ b/gettext-tools/src/po-charset.c
@@ -1,5 +1,5 @@
/* Charset handling while reading PO files.
- Copyright (C) 2001-2007, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2001-2007, 2010, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-charset.h b/gettext-tools/src/po-charset.h
index 65798e7..60484e0 100644
--- a/gettext-tools/src/po-charset.h
+++ b/gettext-tools/src/po-charset.h
@@ -1,5 +1,5 @@
/* Charset handling while reading PO files.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-error.c b/gettext-tools/src/po-error.c
index 067264a..565b9ed 100644
--- a/gettext-tools/src/po-error.c
+++ b/gettext-tools/src/po-error.c
@@ -1,5 +1,5 @@
/* Error handling during reading and writing of PO files.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2004.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-error.h b/gettext-tools/src/po-error.h
index 036a69b..b4eb500 100644
--- a/gettext-tools/src/po-error.h
+++ b/gettext-tools/src/po-error.h
@@ -1,5 +1,5 @@
/* Error handling during reading and writing of PO files.
- Copyright (C) 2004, 2006, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006, 2012, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2004.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-gram-gen.c b/gettext-tools/src/po-gram-gen.c
index 655684e..b3977f5 100644
--- a/gettext-tools/src/po-gram-gen.c
+++ b/gettext-tools/src/po-gram-gen.c
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.2. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison implementation for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
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
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "3.0.2"
+#define YYBISON_VERSION "3.0.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -62,7 +62,7 @@
/* Copy the first part of user declarations. */
-#line 19 "po-gram-gen.y" /* yacc.c:339 */
+#line 20 "po-gram-gen.y" /* yacc.c:339 */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -238,10 +238,10 @@ extern int yydebug;
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE YYSTYPE;
+
union YYSTYPE
{
-#line 143 "po-gram-gen.y" /* yacc.c:355 */
+#line 144 "po-gram-gen.y" /* yacc.c:355 */
struct { char *string; lex_pos_ty pos; bool obsolete; } string;
struct { string_list_ty stringlist; lex_pos_ty pos; bool obsolete; } stringlist;
@@ -253,6 +253,8 @@ union YYSTYPE
#line 255 "po-gram-gen.c" /* yacc.c:355 */
};
+
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
@@ -266,7 +268,7 @@ int yyparse (void);
/* Copy the second part of user declarations. */
-#line 270 "po-gram-gen.c" /* yacc.c:358 */
+#line 272 "po-gram-gen.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -565,10 +567,10 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 168, 168, 170, 171, 172, 173, 178, 186, 194,
- 215, 239, 248, 257, 268, 277, 291, 300, 314, 320,
- 331, 337, 349, 360, 371, 375, 390, 413, 421, 433,
- 441
+ 0, 169, 169, 171, 172, 173, 174, 179, 187, 195,
+ 216, 240, 249, 258, 269, 278, 292, 301, 315, 321,
+ 332, 338, 350, 361, 372, 376, 391, 414, 422, 434,
+ 442
};
#endif
@@ -1368,23 +1370,23 @@ yyreduce:
switch (yyn)
{
case 7:
-#line 179 "po-gram-gen.y" /* yacc.c:1646 */
+#line 180 "po-gram-gen.y" /* yacc.c:1646 */
{
po_callback_comment_dispatcher ((yyvsp[0].string).string);
}
-#line 1376 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1378 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 8:
-#line 187 "po-gram-gen.y" /* yacc.c:1646 */
+#line 188 "po-gram-gen.y" /* yacc.c:1646 */
{
po_callback_domain ((yyvsp[0].string).string);
}
-#line 1384 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1386 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 9:
-#line 195 "po-gram-gen.y" /* yacc.c:1646 */
+#line 196 "po-gram-gen.y" /* yacc.c:1646 */
{
char *string2 = string_list_concat_destroy (&(yyvsp[-2].stringlist).stringlist);
char *string4 = string_list_concat_destroy (&(yyvsp[0].stringlist).stringlist);
@@ -1405,11 +1407,11 @@ yyreduce:
free (string4);
}
}
-#line 1409 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1411 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 10:
-#line 216 "po-gram-gen.y" /* yacc.c:1646 */
+#line 217 "po-gram-gen.y" /* yacc.c:1646 */
{
char *string2 = string_list_concat_destroy (&(yyvsp[-2].stringlist).stringlist);
@@ -1433,11 +1435,11 @@ yyreduce:
free ((yyvsp[0].rhs).rhs.msgstr);
}
}
-#line 1437 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1439 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 11:
-#line 240 "po-gram-gen.y" /* yacc.c:1646 */
+#line 241 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-2].message_intro), (yyvsp[-1].stringlist));
check_obsolete ((yyvsp[-2].message_intro), (yyvsp[0].string));
@@ -1446,11 +1448,11 @@ yyreduce:
string_list_destroy (&(yyvsp[-1].stringlist).stringlist);
free ((yyvsp[0].string).string);
}
-#line 1450 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1452 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 12:
-#line 249 "po-gram-gen.y" /* yacc.c:1646 */
+#line 250 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-2].message_intro), (yyvsp[-1].stringlist));
check_obsolete ((yyvsp[-2].message_intro), (yyvsp[0].rhs));
@@ -1459,22 +1461,22 @@ yyreduce:
string_list_destroy (&(yyvsp[-1].stringlist).stringlist);
free ((yyvsp[0].rhs).rhs.msgstr);
}
-#line 1463 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1465 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 13:
-#line 258 "po-gram-gen.y" /* yacc.c:1646 */
+#line 259 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].message_intro), (yyvsp[0].stringlist));
po_gram_error_at_line (&(yyvsp[-1].message_intro).pos, _("missing 'msgstr' section"));
free_message_intro ((yyvsp[-1].message_intro));
string_list_destroy (&(yyvsp[0].stringlist).stringlist);
}
-#line 1474 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1476 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 14:
-#line 269 "po-gram-gen.y" /* yacc.c:1646 */
+#line 270 "po-gram-gen.y" /* yacc.c:1646 */
{
(yyval.message_intro).prev_ctxt = NULL;
(yyval.message_intro).prev_id = NULL;
@@ -1483,11 +1485,11 @@ yyreduce:
(yyval.message_intro).pos = (yyvsp[0].string).pos;
(yyval.message_intro).obsolete = (yyvsp[0].string).obsolete;
}
-#line 1487 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1489 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 15:
-#line 278 "po-gram-gen.y" /* yacc.c:1646 */
+#line 279 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].prev), (yyvsp[0].string));
(yyval.message_intro).prev_ctxt = (yyvsp[-1].prev).ctxt;
@@ -1497,11 +1499,11 @@ yyreduce:
(yyval.message_intro).pos = (yyvsp[0].string).pos;
(yyval.message_intro).obsolete = (yyvsp[0].string).obsolete;
}
-#line 1501 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1503 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 16:
-#line 292 "po-gram-gen.y" /* yacc.c:1646 */
+#line 293 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].string), (yyvsp[0].stringlist));
(yyval.prev).ctxt = (yyvsp[-1].string).string;
@@ -1510,11 +1512,11 @@ yyreduce:
(yyval.prev).pos = (yyvsp[-1].string).pos;
(yyval.prev).obsolete = (yyvsp[-1].string).obsolete;
}
-#line 1514 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1516 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 17:
-#line 301 "po-gram-gen.y" /* yacc.c:1646 */
+#line 302 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-2].string), (yyvsp[-1].stringlist));
check_obsolete ((yyvsp[-2].string), (yyvsp[0].string));
@@ -1524,21 +1526,21 @@ yyreduce:
(yyval.prev).pos = (yyvsp[-2].string).pos;
(yyval.prev).obsolete = (yyvsp[-2].string).obsolete;
}
-#line 1528 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1530 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 18:
-#line 315 "po-gram-gen.y" /* yacc.c:1646 */
+#line 316 "po-gram-gen.y" /* yacc.c:1646 */
{
(yyval.string).string = NULL;
(yyval.string).pos = (yyvsp[0].pos).pos;
(yyval.string).obsolete = (yyvsp[0].pos).obsolete;
}
-#line 1538 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1540 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 19:
-#line 321 "po-gram-gen.y" /* yacc.c:1646 */
+#line 322 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-2].pos), (yyvsp[-1].stringlist));
check_obsolete ((yyvsp[-2].pos), (yyvsp[0].pos));
@@ -1546,21 +1548,21 @@ yyreduce:
(yyval.string).pos = (yyvsp[0].pos).pos;
(yyval.string).obsolete = (yyvsp[0].pos).obsolete;
}
-#line 1550 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1552 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 20:
-#line 332 "po-gram-gen.y" /* yacc.c:1646 */
+#line 333 "po-gram-gen.y" /* yacc.c:1646 */
{
(yyval.string).string = NULL;
(yyval.string).pos = (yyvsp[0].pos).pos;
(yyval.string).obsolete = (yyvsp[0].pos).obsolete;
}
-#line 1560 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1562 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 21:
-#line 338 "po-gram-gen.y" /* yacc.c:1646 */
+#line 339 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-2].pos), (yyvsp[-1].stringlist));
check_obsolete ((yyvsp[-2].pos), (yyvsp[0].pos));
@@ -1568,11 +1570,11 @@ yyreduce:
(yyval.string).pos = (yyvsp[0].pos).pos;
(yyval.string).obsolete = (yyvsp[0].pos).obsolete;
}
-#line 1572 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1574 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 22:
-#line 350 "po-gram-gen.y" /* yacc.c:1646 */
+#line 351 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].pos), (yyvsp[0].stringlist));
plural_counter = 0;
@@ -1580,30 +1582,30 @@ yyreduce:
(yyval.string).pos = (yyvsp[-1].pos).pos;
(yyval.string).obsolete = (yyvsp[-1].pos).obsolete;
}
-#line 1584 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1586 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 23:
-#line 361 "po-gram-gen.y" /* yacc.c:1646 */
+#line 362 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].pos), (yyvsp[0].stringlist));
(yyval.string).string = string_list_concat_destroy (&(yyvsp[0].stringlist).stringlist);
(yyval.string).pos = (yyvsp[-1].pos).pos;
(yyval.string).obsolete = (yyvsp[-1].pos).obsolete;
}
-#line 1595 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1597 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 24:
-#line 372 "po-gram-gen.y" /* yacc.c:1646 */
+#line 373 "po-gram-gen.y" /* yacc.c:1646 */
{
(yyval.rhs) = (yyvsp[0].rhs);
}
-#line 1603 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1605 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 25:
-#line 376 "po-gram-gen.y" /* yacc.c:1646 */
+#line 377 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].rhs), (yyvsp[0].rhs));
(yyval.rhs).rhs.msgstr = XNMALLOC ((yyvsp[-1].rhs).rhs.msgstr_len + (yyvsp[0].rhs).rhs.msgstr_len, char);
@@ -1615,11 +1617,11 @@ yyreduce:
(yyval.rhs).pos = (yyvsp[-1].rhs).pos;
(yyval.rhs).obsolete = (yyvsp[-1].rhs).obsolete;
}
-#line 1619 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1621 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 26:
-#line 391 "po-gram-gen.y" /* yacc.c:1646 */
+#line 392 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-4].pos), (yyvsp[-3].pos));
check_obsolete ((yyvsp[-4].pos), (yyvsp[-2].number));
@@ -1638,11 +1640,11 @@ yyreduce:
(yyval.rhs).pos = (yyvsp[-4].pos).pos;
(yyval.rhs).obsolete = (yyvsp[-4].pos).obsolete;
}
-#line 1642 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1644 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 27:
-#line 414 "po-gram-gen.y" /* yacc.c:1646 */
+#line 415 "po-gram-gen.y" /* yacc.c:1646 */
{
string_list_init (&(yyval.stringlist).stringlist);
string_list_append (&(yyval.stringlist).stringlist, (yyvsp[0].string).string);
@@ -1650,11 +1652,11 @@ yyreduce:
(yyval.stringlist).pos = (yyvsp[0].string).pos;
(yyval.stringlist).obsolete = (yyvsp[0].string).obsolete;
}
-#line 1654 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1656 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 28:
-#line 422 "po-gram-gen.y" /* yacc.c:1646 */
+#line 423 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].stringlist), (yyvsp[0].string));
(yyval.stringlist).stringlist = (yyvsp[-1].stringlist).stringlist;
@@ -1663,11 +1665,11 @@ yyreduce:
(yyval.stringlist).pos = (yyvsp[-1].stringlist).pos;
(yyval.stringlist).obsolete = (yyvsp[-1].stringlist).obsolete;
}
-#line 1667 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1669 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 29:
-#line 434 "po-gram-gen.y" /* yacc.c:1646 */
+#line 435 "po-gram-gen.y" /* yacc.c:1646 */
{
string_list_init (&(yyval.stringlist).stringlist);
string_list_append (&(yyval.stringlist).stringlist, (yyvsp[0].string).string);
@@ -1675,11 +1677,11 @@ yyreduce:
(yyval.stringlist).pos = (yyvsp[0].string).pos;
(yyval.stringlist).obsolete = (yyvsp[0].string).obsolete;
}
-#line 1679 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1681 "po-gram-gen.c" /* yacc.c:1646 */
break;
case 30:
-#line 442 "po-gram-gen.y" /* yacc.c:1646 */
+#line 443 "po-gram-gen.y" /* yacc.c:1646 */
{
check_obsolete ((yyvsp[-1].stringlist), (yyvsp[0].string));
(yyval.stringlist).stringlist = (yyvsp[-1].stringlist).stringlist;
@@ -1688,11 +1690,11 @@ yyreduce:
(yyval.stringlist).pos = (yyvsp[-1].stringlist).pos;
(yyval.stringlist).obsolete = (yyvsp[-1].stringlist).obsolete;
}
-#line 1692 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1694 "po-gram-gen.c" /* yacc.c:1646 */
break;
-#line 1696 "po-gram-gen.c" /* yacc.c:1646 */
+#line 1698 "po-gram-gen.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
diff --git a/gettext-tools/src/po-gram-gen.h b/gettext-tools/src/po-gram-gen.h
index 3f20e75..97089df 100644
--- a/gettext-tools/src/po-gram-gen.h
+++ b/gettext-tools/src/po-gram-gen.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.2. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
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
@@ -79,10 +79,10 @@ extern int yydebug;
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE YYSTYPE;
+
union YYSTYPE
{
-#line 143 "po-gram-gen.y" /* yacc.c:1909 */
+#line 144 "po-gram-gen.y" /* yacc.c:1909 */
struct { char *string; lex_pos_ty pos; bool obsolete; } string;
struct { string_list_ty stringlist; lex_pos_ty pos; bool obsolete; } stringlist;
@@ -94,6 +94,8 @@ union YYSTYPE
#line 96 "po-gram-gen.h" /* yacc.c:1909 */
};
+
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
diff --git a/gettext-tools/src/po-gram-gen.y b/gettext-tools/src/po-gram-gen.y
index 8f888bd..0a34068 100644
--- a/gettext-tools/src/po-gram-gen.y
+++ b/gettext-tools/src/po-gram-gen.y
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1996, 1998, 2000-2001, 2003, 2005-2006, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2000-2001, 2003, 2005-2006, 2012, 2015
+ Free Software Foundation, Inc.
This file was written by Peter Miller <pmiller@agso.gov.au>
diff --git a/gettext-tools/src/po-gram-gen2.h b/gettext-tools/src/po-gram-gen2.h
index 36e9f4b..683ccbf 100644
--- a/gettext-tools/src/po-gram-gen2.h
+++ b/gettext-tools/src/po-gram-gen2.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.2. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C
- Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
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
@@ -79,10 +79,10 @@ extern DLL_VARIABLE int po_gram_debug;
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE YYSTYPE;
+
union YYSTYPE
{
-#line 143 "po-gram-gen.y" /* yacc.c:1909 */
+#line 144 "po-gram-gen.y" /* yacc.c:1909 */
struct { char *string; lex_pos_ty pos; bool obsolete; } string;
struct { string_list_ty stringlist; lex_pos_ty pos; bool obsolete; } stringlist;
@@ -94,6 +94,8 @@ union YYSTYPE
#line 96 "po-gram-gen.h" /* yacc.c:1909 */
};
+
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
#endif
diff --git a/gettext-tools/src/po-gram.h b/gettext-tools/src/po-gram.h
index 0e2d079..4c8787e 100644
--- a/gettext-tools/src/po-gram.h
+++ b/gettext-tools/src/po-gram.h
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995, 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2002-2003, 2006, 2015 Free Software Foundation,
+ Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/po-lex.c b/gettext-tools/src/po-lex.c
index 3bf5449..a48f59a 100644
--- a/gettext-tools/src/po-lex.c
+++ b/gettext-tools/src/po-lex.c
@@ -1,5 +1,5 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1999, 2000-2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 1995-2009, 2011, 2015 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>.
Multibyte character handling by Bruno Haible <haible@clisp.cons.org>.
diff --git a/gettext-tools/src/po-lex.h b/gettext-tools/src/po-lex.h
index da05f38..257e61a 100644
--- a/gettext-tools/src/po-lex.h
+++ b/gettext-tools/src/po-lex.h
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2006, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2006, 2012, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/po-time.c b/gettext-tools/src/po-time.c
index dd357f1..5147389 100644
--- a/gettext-tools/src/po-time.c
+++ b/gettext-tools/src/po-time.c
@@ -1,5 +1,6 @@
/* PO/POT file timestamps.
- Copyright (C) 1995-1998, 2000-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2006, 2015 Free Software
+ Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-time.h b/gettext-tools/src/po-time.h
index 846dea0..4c63006 100644
--- a/gettext-tools/src/po-time.h
+++ b/gettext-tools/src/po-time.h
@@ -1,5 +1,5 @@
/* PO/POT file timestamps.
- Copyright (C) 2001-2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-xerror.c b/gettext-tools/src/po-xerror.c
index 8a889d8..f58d2bd 100644
--- a/gettext-tools/src/po-xerror.c
+++ b/gettext-tools/src/po-xerror.c
@@ -1,5 +1,5 @@
/* Error handling during reading and writing of PO files.
- Copyright (C) 2005-2007 Free Software Foundation, Inc.
+ Copyright (C) 2005-2007, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2005.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/po-xerror.h b/gettext-tools/src/po-xerror.h
index 521ec3f..0493de9 100644
--- a/gettext-tools/src/po-xerror.h
+++ b/gettext-tools/src/po-xerror.h
@@ -1,5 +1,5 @@
/* Error handling during reading and writing of PO files.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2005.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/pos.h b/gettext-tools/src/pos.h
index 684986e..9c57290 100644
--- a/gettext-tools/src/pos.h
+++ b/gettext-tools/src/pos.h
@@ -1,5 +1,6 @@
/* Source file positions.
- Copyright (C) 1995-1998, 2000-2001 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2001, 2015 Free Software Foundation,
+ Inc.
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
diff --git a/gettext-tools/src/project-id b/gettext-tools/src/project-id
index e60c8e3..103f91f 100755
--- a/gettext-tools/src/project-id
+++ b/gettext-tools/src/project-id
@@ -1,7 +1,7 @@
#!/bin/sh
# Prints a package's identification PACKAGE VERSION or PACKAGE.
#
-# Copyright (C) 2001-2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001-2003, 2005, 2015 Free Software Foundation, Inc.
#
# 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
diff --git a/gettext-tools/src/quote.h b/gettext-tools/src/quote.h
new file mode 100644
index 0000000..df8cde2
--- /dev/null
+++ b/gettext-tools/src/quote.h
@@ -0,0 +1,142 @@
+/* Handle quoted segments of a string.
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ Written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _QUOTE_H
+#define _QUOTE_H
+
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static void
+scan_quoted (const char *input, size_t length,
+ void (* callback) (char quote, const char *quoted,
+ size_t quoted_length,
+ void *data),
+ void *data)
+{
+ const char *p, *start, *end;
+ bool seen_opening;
+
+ /* START shall point to the beginning of a quoted segment, END
+ points to the end of the entire input string. */
+ start = input;
+ end = &input[length - 1];
+
+ /* True if we have seen a character which could be an opening
+ quotation mark. Note that we can't determine if it is really an
+ opening quotation mark until we see a closing quotation mark. */
+ seen_opening = false;
+
+ for (p = start; p <= end; p++)
+ {
+ switch (*p)
+ {
+ case '"':
+ if (seen_opening)
+ {
+ if (*start == '"')
+ {
+ if (p == start + 1)
+ /* Consider "" as "". */
+ callback ('\0', "\"\"", 2, data);
+ else
+ /* "..." */
+ callback ('"', start + 1, p - (start + 1), data);
+
+ start = p + 1;
+ seen_opening = false;
+ }
+ }
+ else
+ {
+ callback ('\0', start, p - start, data);
+ start = p;
+ seen_opening = true;
+ }
+ break;
+
+ case '`':
+ if (seen_opening)
+ {
+ if (*start == '`')
+ {
+ callback ('\0', start, p - start, data);
+ start = p;
+ }
+ }
+ else
+ {
+ callback ('\0', start, p - start, data);
+ start = p;
+ seen_opening = true;
+ }
+ break;
+
+ case '\'':
+ if (seen_opening)
+ {
+ if (/* `...' */
+ *start == '`'
+ /* '...', where
+ - The left quote is preceded by a space, and the
+ right quote is followed by a space.
+ - The left quote is preceded by a space, and the
+ right quote is at the end of line.
+ - The left quote is at the beginning of the line, and
+ the right quote is followed by a space. */
+ || (*start == '\''
+ && (((start > input && *(start - 1) == ' ')
+ && (p == end || *(p + 1) == '\n' || *(p + 1) == ' '))
+ || ((start == input || *(start - 1) == '\n')
+ && p < end && *(p + 1) == ' '))))
+ {
+ callback ('\'', start + 1, p - (start + 1), data);
+ start = p + 1;
+ }
+ else
+ {
+ callback ('\0', start, p - start, data);
+ start = p;
+ }
+ seen_opening = false;
+ }
+ else if (p == input || *(p - 1) == '\n' || *(p - 1) == ' ')
+ {
+ callback ('\0', start, p - start, data);
+ start = p;
+ seen_opening = true;
+ }
+ break;
+ }
+ }
+
+ /* Copy the rest. */
+ if (p > start)
+ callback ('\0', start, p - start, data);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _QUOTE_H */
diff --git a/gettext-tools/src/read-catalog-abstract.c b/gettext-tools/src/read-catalog-abstract.c
index d4e98ee..eaa624b 100644
--- a/gettext-tools/src/read-catalog-abstract.c
+++ b/gettext-tools/src/read-catalog-abstract.c
@@ -1,5 +1,6 @@
/* Reading PO files, abstract class.
- Copyright (C) 1995-1996, 1998, 2000-2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2000-2009, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
@@ -262,7 +263,8 @@ po_callback_comment_special (const char *s)
void
po_parse_comment_special (const char *s,
bool *fuzzyp, enum is_format formatp[NFORMATS],
- struct argument_range *rangep, enum is_wrap *wrapp)
+ struct argument_range *rangep, enum is_wrap *wrapp,
+ enum is_syntax_check scp[NSYNTAXCHECKS])
{
size_t i;
@@ -272,6 +274,8 @@ po_parse_comment_special (const char *s,
rangep->min = -1;
rangep->max = -1;
*wrapp = undecided;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ scp[i] = undecided;
while (*s != '\0')
{
@@ -405,6 +409,36 @@ po_parse_comment_special (const char *s,
continue;
}
+ /* Accept syntax check description. */
+ if (len >= 6 && memcmp (t + len - 6, "-check", 6) == 0)
+ {
+ const char *p;
+ size_t n;
+ enum is_syntax_check value;
+
+ p = t;
+ n = len - 6;
+
+ if (n >= 3 && memcmp (p, "no-", 3) == 0)
+ {
+ p += 3;
+ n -= 3;
+ value = no;
+ }
+ else
+ value = yes;
+
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ if (strlen (syntax_check_name[i]) == n
+ && memcmp (syntax_check_name[i], p, n) == 0)
+ {
+ scp[i] = value;
+ break;
+ }
+ if (i < NSYNTAXCHECKS)
+ continue;
+ }
+
/* Unknown special comment marker. It may have been generated
from a future xgettext version. Ignore it. */
}
diff --git a/gettext-tools/src/read-catalog-abstract.h b/gettext-tools/src/read-catalog-abstract.h
index c3fc84f..7f6dbfa 100644
--- a/gettext-tools/src/read-catalog-abstract.h
+++ b/gettext-tools/src/read-catalog-abstract.h
@@ -1,5 +1,6 @@
/* Reading PO files, abstract class.
- Copyright (C) 1995-1996, 1998, 2000-2003, 2005-2006, 2008-2009, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2000-2003, 2005-2006, 2008-2009, 2012,
+ 2015 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
@@ -184,7 +185,8 @@ extern void po_callback_comment_dispatcher (const char *s);
extern void po_parse_comment_special (const char *s, bool *fuzzyp,
enum is_format formatp[NFORMATS],
struct argument_range *rangep,
- enum is_wrap *wrapp);
+ enum is_wrap *wrapp,
+ enum is_syntax_check scp[NSYNTAXCHECKS]);
#ifdef __cplusplus
diff --git a/gettext-tools/src/read-catalog.c b/gettext-tools/src/read-catalog.c
index 4642249..8a26581 100644
--- a/gettext-tools/src/read-catalog.c
+++ b/gettext-tools/src/read-catalog.c
@@ -1,5 +1,6 @@
/* Reading PO files.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2015 Free
+ Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
This program is free software: you can redistribute it and/or modify
@@ -105,6 +106,8 @@ default_constructor (abstract_catalog_reader_ty *that)
this->range.min = -1;
this->range.max = -1;
this->do_wrap = undecided;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ this->do_syntax_check[i] = undecided;
}
@@ -172,6 +175,8 @@ default_copy_comment_state (default_catalog_reader_ty *this, message_ty *mp)
mp->is_format[i] = this->is_format[i];
mp->range = this->range;
mp->do_wrap = this->do_wrap;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ mp->do_syntax_check[i] = this->do_syntax_check[i];
}
@@ -205,6 +210,8 @@ default_reset_comment_state (default_catalog_reader_ty *this)
this->range.min = -1;
this->range.max = -1;
this->do_wrap = undecided;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ this->do_syntax_check[i] = undecided;
}
@@ -299,7 +306,7 @@ default_comment_special (abstract_catalog_reader_ty *that, const char *s)
default_catalog_reader_ty *this = (default_catalog_reader_ty *) that;
po_parse_comment_special (s, &this->is_fuzzy, this->is_format, &this->range,
- &this->do_wrap);
+ &this->do_wrap, this->do_syntax_check);
}
diff --git a/gettext-tools/src/read-catalog.h b/gettext-tools/src/read-catalog.h
index f567d78..f50bcb0 100644
--- a/gettext-tools/src/read-catalog.h
+++ b/gettext-tools/src/read-catalog.h
@@ -1,5 +1,6 @@
/* Reading PO files.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2015 Free
+ Software Foundation, Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>.
This program is free software: you can redistribute it and/or modify
@@ -113,6 +114,7 @@ struct default_catalog_reader_class_ty
enum is_format is_format[NFORMATS]; \
struct argument_range range; \
enum is_wrap do_wrap; \
+ enum is_syntax_check do_syntax_check[NSYNTAXCHECKS]; \
typedef struct default_catalog_reader_ty default_catalog_reader_ty;
struct default_catalog_reader_ty
diff --git a/gettext-tools/src/read-csharp.c b/gettext-tools/src/read-csharp.c
index df5ca83..c2b3879 100644
--- a/gettext-tools/src/read-csharp.c
+++ b/gettext-tools/src/read-csharp.c
@@ -1,5 +1,6 @@
/* Reading C# satellite assemblies.
- Copyright (C) 2003-2004, 2006-2008, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2003-2004, 2006-2008, 2011, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-csharp.h b/gettext-tools/src/read-csharp.h
index f8b66b3..3e03ccf 100644
--- a/gettext-tools/src/read-csharp.h
+++ b/gettext-tools/src/read-csharp.h
@@ -1,5 +1,5 @@
/* Reading C# satellite assemblies.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-desktop.c b/gettext-tools/src/read-desktop.c
index 8f9243b..0de123c 100644
--- a/gettext-tools/src/read-desktop.c
+++ b/gettext-tools/src/read-desktop.c
@@ -1,5 +1,6 @@
/* Reading Desktop Entry files.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
+ Free Software Foundation, Inc.
This file was written by Daiki Ueno <ueno@gnu.org>.
This program is free software: you can redistribute it and/or modify
@@ -271,16 +272,13 @@ desktop_lex (token_ty *tp)
break;
}
/* Skip until newline. */
- if (c != '\n')
+ while (c != '\n' && c != EOF)
{
- for (;;)
- {
- if (c == '\n' || c == EOF)
- break;
- if (!c_isspace (c))
- non_blank = true;
- c = phase2_getc ();
- }
+ c = phase2_getc ();
+ if (c == EOF)
+ break;
+ if (!c_isspace (c))
+ non_blank = true;
}
if (non_blank)
po_xerror (PO_SEVERITY_WARNING, NULL,
diff --git a/gettext-tools/src/read-desktop.h b/gettext-tools/src/read-desktop.h
index 19ad8d8..eebd681 100644
--- a/gettext-tools/src/read-desktop.h
+++ b/gettext-tools/src/read-desktop.h
@@ -1,5 +1,6 @@
/* Reading Desktop Entry files.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
+ Free Software Foundation, Inc.
This file was written by Daiki Ueno <ueno@gnu.org>.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-java.c b/gettext-tools/src/read-java.c
index bc6f2f4..1e1cce0 100644
--- a/gettext-tools/src/read-java.c
+++ b/gettext-tools/src/read-java.c
@@ -1,5 +1,6 @@
/* Reading Java ResourceBundles.
- Copyright (C) 2001-2003, 2006-2008, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006-2008, 2011, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-java.h b/gettext-tools/src/read-java.h
index 6b4d037..169263b 100644
--- a/gettext-tools/src/read-java.h
+++ b/gettext-tools/src/read-java.h
@@ -1,5 +1,5 @@
/* Reading Java ResourceBundles.
- Copyright (C) 2001-2002 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-mo.c b/gettext-tools/src/read-mo.c
index b97bbad..c3bfb22 100644
--- a/gettext-tools/src/read-mo.c
+++ b/gettext-tools/src/read-mo.c
@@ -1,5 +1,6 @@
/* Reading binary .mo files.
- Copyright (C) 1995-1998, 2000-2007 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2007, 2015 Free Software Foundation,
+ Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
@@ -149,6 +150,7 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset,
nls_uint32 s_offset;
/* Compute the length. */
+ s_offset = get_uint32 (bfp, offset);
length = 0;
for (i = 4; ; i += 8)
{
@@ -158,9 +160,14 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset,
nls_uint32 ss_length;
nls_uint32 ss_offset;
size_t ss_end;
+ size_t s_end;
size_t n;
+ s_end = xsum (s_offset, segsize);
+ if (size_overflow_p (s_end) || s_end > bfp->size)
+ error (EXIT_FAILURE, 0, _("file \"%s\" is truncated"), bfp->filename);
length += segsize;
+ s_offset += segsize;
if (sysdepref == SEGMENTS_END)
break;
@@ -175,7 +182,7 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset,
ss_end = xsum (ss_offset, ss_length);
if (size_overflow_p (ss_end) || ss_end > bfp->size)
error (EXIT_FAILURE, 0, _("file \"%s\" is truncated"), bfp->filename);
- if (!(ss_length > 0 && bfp->data[ss_offset + ss_length - 1] == '\0'))
+ if (!(ss_length > 0 && bfp->data[ss_end - 1] == '\0'))
{
char location[30];
sprintf (location, "sysdep_segment[%u]", (unsigned int) sysdepref);
@@ -198,11 +205,8 @@ get_sysdep_string (const struct binary_mo_file *bfp, size_t offset,
nls_uint32 sysdep_segment_offset;
nls_uint32 ss_length;
nls_uint32 ss_offset;
- size_t s_end = xsum (s_offset, segsize);
size_t n;
- if (size_overflow_p (s_end) || s_end > bfp->size)
- error (EXIT_FAILURE, 0, _("file \"%s\" is truncated"), bfp->filename);
memcpy (p, bfp->data + s_offset, segsize);
p += segsize;
s_offset += segsize;
diff --git a/gettext-tools/src/read-mo.h b/gettext-tools/src/read-mo.h
index c8e976c..d5f8f58 100644
--- a/gettext-tools/src/read-mo.h
+++ b/gettext-tools/src/read-mo.h
@@ -1,5 +1,6 @@
/* Reading binary .mo files.
- Copyright (C) 1995-1998, 2000-2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2015 Free Software Foundation,
+ Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-po.c b/gettext-tools/src/read-po.c
index 04f1b74..71eebc2 100644
--- a/gettext-tools/src/read-po.c
+++ b/gettext-tools/src/read-po.c
@@ -1,5 +1,6 @@
/* Reading PO files.
- Copyright (C) 1995-1996, 1998, 2000-2006 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2000-2006, 2015 Free Software
+ Foundation, Inc.
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
diff --git a/gettext-tools/src/read-po.h b/gettext-tools/src/read-po.h
index e426eaa..aa9c173 100644
--- a/gettext-tools/src/read-po.h
+++ b/gettext-tools/src/read-po.h
@@ -1,5 +1,5 @@
/* Reading PO files.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2006.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-properties.c b/gettext-tools/src/read-properties.c
index 0c64730..a4919a4 100644
--- a/gettext-tools/src/read-properties.c
+++ b/gettext-tools/src/read-properties.c
@@ -1,5 +1,6 @@
/* Reading Java .properties files.
- Copyright (C) 2003, 2005-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2007, 2009, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-properties.h b/gettext-tools/src/read-properties.h
index 8ac7852..bf2279b 100644
--- a/gettext-tools/src/read-properties.h
+++ b/gettext-tools/src/read-properties.h
@@ -1,5 +1,5 @@
/* Reading Java .properties files.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-resources.c b/gettext-tools/src/read-resources.c
index a5eb8eb..d60394e 100644
--- a/gettext-tools/src/read-resources.c
+++ b/gettext-tools/src/read-resources.c
@@ -1,5 +1,6 @@
/* Reading C# .resources files.
- Copyright (C) 2003, 2006-2008, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2008, 2011, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-resources.h b/gettext-tools/src/read-resources.h
index b3c6076..58dccef 100644
--- a/gettext-tools/src/read-resources.h
+++ b/gettext-tools/src/read-resources.h
@@ -1,5 +1,5 @@
/* Reading C# .resources files.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-stringtable.c b/gettext-tools/src/read-stringtable.c
index 27b8860..62073c4 100644
--- a/gettext-tools/src/read-stringtable.c
+++ b/gettext-tools/src/read-stringtable.c
@@ -1,5 +1,6 @@
/* Reading NeXTstep/GNUstep .strings files.
- Copyright (C) 2003, 2005-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2007, 2009, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-stringtable.h b/gettext-tools/src/read-stringtable.h
index d254434..6c3e069 100644
--- a/gettext-tools/src/read-stringtable.h
+++ b/gettext-tools/src/read-stringtable.h
@@ -1,5 +1,5 @@
/* Reading NeXTstep/GNUstep .strings files.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-tcl.c b/gettext-tools/src/read-tcl.c
index 039dcfb..4191864 100644
--- a/gettext-tools/src/read-tcl.c
+++ b/gettext-tools/src/read-tcl.c
@@ -1,5 +1,6 @@
/* Reading tcl/msgcat .msg files.
- Copyright (C) 2002-2003, 2005-2008, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2008, 2011, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/read-tcl.h b/gettext-tools/src/read-tcl.h
index a2c2d9e..d66624d 100644
--- a/gettext-tools/src/read-tcl.h
+++ b/gettext-tools/src/read-tcl.h
@@ -1,5 +1,5 @@
/* Reading tcl/msgcat .msg files.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/recode-sr-latin.c b/gettext-tools/src/recode-sr-latin.c
index 25b88f6..44a2f49 100644
--- a/gettext-tools/src/recode-sr-latin.c
+++ b/gettext-tools/src/recode-sr-latin.c
@@ -1,5 +1,6 @@
/* Recode Serbian text from Cyrillic to Latin script.
- Copyright (C) 2006-2007, 2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2006-2007, 2010, 2012, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <bruno@clisp.org>, 2006.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/sentence.c b/gettext-tools/src/sentence.c
new file mode 100644
index 0000000..0a4883e
--- /dev/null
+++ b/gettext-tools/src/sentence.c
@@ -0,0 +1,194 @@
+/* Sentence handling.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+ Written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "sentence.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "unistr.h"
+
+
+/* The minimal number of white spaces which should follow after the
+ end of sentence. */
+int sentence_end_required_spaces = 1;
+
+/* This function works in a similar way to 'forward-sentence' in
+ Emacs, which basically does a regular expression matching of:
+
+ [.?!\u2026]
+ []"'\u201d)}]*
+ \($\|[ \u00a0]$\|\t\|[ \u00a0]\{REQUIRED_SPACES\}\)
+
+ Since we are lacking a regular expression routine capable of
+ Unicode (though gnulib-lib/lib/regex.c provides a locale-dependent
+ version, we would rather avoid depending on it), apply a manually
+ constructed DFA, which consists of 8 states where 4 of them are a
+ terminal. */
+const char *
+sentence_end (const char *string, ucs4_t *ending_charp)
+{
+ const char *str = string;
+ const char *str_limit = string + strlen (str);
+ /* States of the DFA, 0 to 7, where 3, 5, 6, and 7 are a terminal. */
+ int state = 0;
+ /* Previous character before an end marker. */
+ ucs4_t ending_char = 0xfffd;
+ /* Possible starting position of the match, and the next starting
+ position if the current match fails. */
+ const char *match_start = NULL, *match_next = NULL;
+ /* Number of spaces. */
+ int spaces = 0;
+
+ while (str <= str_limit)
+ {
+ ucs4_t uc;
+ size_t length;
+
+ length = u8_mbtouc (&uc, (const unsigned char *) str, str_limit - str);
+
+ if (state == 0)
+ {
+ switch (uc)
+ {
+ case '.': case '?': case '!': case 0x2026:
+ state = 1;
+ match_start = str;
+ match_next = str + length;
+ ending_char = uc;
+ spaces = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ str += length;
+ continue;
+ }
+
+ if (state == 1)
+ {
+ switch (uc)
+ {
+ case ']': case '"': case '\'': case ')': case '}': case 0x201d:
+ state = 2;
+ break;
+
+ case '\0': case '\n':
+ /* State 3. */
+ *ending_charp = ending_char;
+ return match_start;
+
+ case ' ': case 0x00a0:
+ if (++spaces == sentence_end_required_spaces)
+ {
+ /* State 7. */
+ *ending_charp = ending_char;
+ return match_start;
+ }
+ state = 4;
+ break;
+
+ case '\t':
+ /* State 5. */
+ *ending_charp = ending_char;
+ return match_start;
+
+ default:
+ str = match_next;
+ state = 0;
+ continue;
+ }
+
+ str += length;
+ continue;
+ }
+
+ if (state == 2)
+ {
+ switch (uc)
+ {
+ case ']': case '"': case '\'': case ')': case '}': case 0x201d:
+ break;
+
+ case '\0': case '\n':
+ /* State 3. */
+ *ending_charp = ending_char;
+ return match_start;
+
+ case ' ': case 0x00a0:
+ if (++spaces == sentence_end_required_spaces)
+ {
+ /* State 7. */
+ *ending_charp = ending_char;
+ return match_start;
+ }
+ state = 4;
+ break;
+
+ case '\t':
+ /* State 5. */
+ *ending_charp = ending_char;
+ return match_start;
+
+ default:
+ state = 0;
+ str = match_next;
+ continue;
+ }
+
+ str += length;
+ continue;
+ }
+
+ if (state == 4)
+ {
+ switch (uc)
+ {
+ case '\0': case '\n':
+ /* State 6. */
+ *ending_charp = ending_char;
+ return match_start;
+
+ case ' ': case 0x00a0:
+ if (++spaces == sentence_end_required_spaces)
+ {
+ /* State 7. */
+ *ending_charp = ending_char;
+ return match_start;
+ }
+ break;
+
+ default:
+ state = 0;
+ str = match_next;
+ continue;
+ }
+
+ str += length;
+ continue;
+ }
+ }
+
+ *ending_charp = 0xfffd;
+ return str_limit;
+}
diff --git a/gettext-tools/src/sentence.h b/gettext-tools/src/sentence.h
new file mode 100644
index 0000000..02fdc16
--- /dev/null
+++ b/gettext-tools/src/sentence.h
@@ -0,0 +1,42 @@
+/* Sentence handling.
+ Copyright (C) 2015 Free Software Foundation, Inc.
+ Written by Daiki Ueno <ueno@gnu.org>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _SENTENCE_H
+#define _SENTENCE_H
+
+#include "unitypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The minimal number of white spaces which should follow after the
+ end of sentence. */
+extern DLL_VARIABLE int sentence_end_required_spaces;
+
+/* Locate the position of a sentence end marker (a period, a question
+ mark, etc) in a null-terminated string STR. If there is no
+ sentence end marker found in STR, return a pointer to the null byte
+ at the end of STR. ENDING_CHARP is a return location of the end
+ marker character. */
+extern const char *sentence_end (const char *string, ucs4_t *ending_charp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SENTENCE_H */
diff --git a/gettext-tools/src/str-list.c b/gettext-tools/src/str-list.c
index 3f929c2..0e3a9ff 100644
--- a/gettext-tools/src/str-list.c
+++ b/gettext-tools/src/str-list.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995, 1998, 2000-2004, 2006, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1998, 2000-2004, 2006, 2009, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/str-list.h b/gettext-tools/src/str-list.h
index 5b7b75d..0758171 100644
--- a/gettext-tools/src/str-list.h
+++ b/gettext-tools/src/str-list.h
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1996, 1998, 2000-2004, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2000-2004, 2009, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/urlget.c b/gettext-tools/src/urlget.c
index f3243e1..482144c 100644
--- a/gettext-tools/src/urlget.c
+++ b/gettext-tools/src/urlget.c
@@ -1,5 +1,6 @@
/* Get the contents of an URL.
- Copyright (C) 2001-2003, 2005-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2010, 2012, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/user-email.sh.in b/gettext-tools/src/user-email.sh.in
index 5a35405..d5b5e49 100644
--- a/gettext-tools/src/user-email.sh.in
+++ b/gettext-tools/src/user-email.sh.in
@@ -1,7 +1,7 @@
#!/bin/sh
# Prints the user's email address, with confirmation from the user.
#
-# Copyright (C) 2001-2003, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2001-2003, 2005, 2015 Free Software Foundation, Inc.
#
# 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
diff --git a/gettext-tools/src/write-catalog.c b/gettext-tools/src/write-catalog.c
index bab8c36..4649efa 100644
--- a/gettext-tools/src/write-catalog.c
+++ b/gettext-tools/src/write-catalog.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2008, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2008, 2012, 2015 Free Software
+ Foundation, Inc.
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
diff --git a/gettext-tools/src/write-catalog.h b/gettext-tools/src/write-catalog.h
index 804592c..7cb18b8 100644
--- a/gettext-tools/src/write-catalog.h
+++ b/gettext-tools/src/write-catalog.h
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2003, 2006, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2006, 2008, 2015 Free Software
+ Foundation, Inc.
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
diff --git a/gettext-tools/src/write-csharp.c b/gettext-tools/src/write-csharp.c
index 047361a..dd757ed 100644
--- a/gettext-tools/src/write-csharp.c
+++ b/gettext-tools/src/write-csharp.c
@@ -1,5 +1,5 @@
/* Writing C# satellite assemblies.
- Copyright (C) 2003-2010 Free Software Foundation, Inc.
+ Copyright (C) 2003-2010, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-csharp.h b/gettext-tools/src/write-csharp.h
index 55b71fb..509f8c1 100644
--- a/gettext-tools/src/write-csharp.h
+++ b/gettext-tools/src/write-csharp.h
@@ -1,5 +1,5 @@
/* Writing C# satellite assemblies.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-desktop.c b/gettext-tools/src/write-desktop.c
index dd3fb60..6cf1db7 100644
--- a/gettext-tools/src/write-desktop.c
+++ b/gettext-tools/src/write-desktop.c
@@ -1,5 +1,6 @@
/* Writing Desktop Entry files.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
+ Free Software Foundation, Inc.
This file was written by Daiki Ueno <ueno@gnu.org>.
This program is free software: you can redistribute it and/or modify
@@ -42,8 +43,7 @@ typedef struct msgfmt_desktop_reader_ty msgfmt_desktop_reader_ty;
struct msgfmt_desktop_reader_ty
{
DESKTOP_READER_TY
- string_list_ty *languages;
- message_list_ty **messages;
+ msgfmt_operand_list_ty *operands;
hash_table *keywords;
FILE *output_file;
};
@@ -77,13 +77,12 @@ msgfmt_desktop_handle_pair (desktop_reader_ty *reader,
char *unescaped = desktop_unescape_string (value, is_list);
size_t i;
- for (i = 0; i < msgfmt_reader->languages->nitems; i++)
+ for (i = 0; i < msgfmt_reader->operands->nitems; i++)
{
- const char *language = msgfmt_reader->languages->item[i];
- message_list_ty *mlp = msgfmt_reader->messages[i];
+ msgfmt_operand_ty *operand = &msgfmt_reader->operands->items[i];
message_ty *mp;
- mp = message_list_search (mlp, NULL, unescaped);
+ mp = message_list_search (operand->mlp, NULL, unescaped);
if (mp && *mp->msgstr != '\0')
{
char *escaped;
@@ -91,7 +90,7 @@ msgfmt_desktop_handle_pair (desktop_reader_ty *reader,
escaped = desktop_escape_string (mp->msgstr, is_list);
fprintf (msgfmt_reader->output_file,
"%s[%s]=%s\n",
- key, language, escaped);
+ key, operand->language, escaped);
free (escaped);
}
}
@@ -137,8 +136,7 @@ desktop_reader_class_ty msgfmt_methods =
};
int
-msgdomain_write_desktop_bulk (string_list_ty *languages,
- message_list_ty **messages,
+msgdomain_write_desktop_bulk (msgfmt_operand_list_ty *operands,
const char *template_file_name,
hash_table *keywords,
const char *file_name)
@@ -150,8 +148,7 @@ msgdomain_write_desktop_bulk (string_list_ty *languages,
reader = desktop_reader_alloc (&msgfmt_methods);
msgfmt_reader = (msgfmt_desktop_reader_ty *) reader;
- msgfmt_reader->languages = languages;
- msgfmt_reader->messages = messages;
+ msgfmt_reader->operands = operands;
msgfmt_reader->keywords = keywords;
if (strcmp (file_name, "-") == 0)
@@ -162,8 +159,7 @@ msgdomain_write_desktop_bulk (string_list_ty *languages,
if (msgfmt_reader->output_file == NULL)
{
desktop_reader_free (reader);
- error (EXIT_SUCCESS,
- errno, _("error while opening \"%s\" for writing"),
+ error (0, errno, _("error while opening \"%s\" for writing"),
file_name);
return 1;
}
@@ -173,8 +169,7 @@ msgdomain_write_desktop_bulk (string_list_ty *languages,
if (template_file == NULL)
{
desktop_reader_free (reader);
- error (EXIT_SUCCESS,
- errno, _("error while opening \"%s\" for reading"),
+ error (0, errno, _("error while opening \"%s\" for reading"),
template_file_name);
return 1;
}
@@ -183,8 +178,11 @@ msgdomain_write_desktop_bulk (string_list_ty *languages,
/* Make sure nothing went wrong. */
if (fwriteerror (msgfmt_reader->output_file))
- error (EXIT_FAILURE, errno, _("error while writing \"%s\" file"),
- file_name);
+ {
+ error (0, errno, _("error while writing \"%s\" file"),
+ file_name);
+ return 1;
+ }
desktop_reader_free (reader);
@@ -199,27 +197,20 @@ msgdomain_write_desktop (message_list_ty *mlp,
hash_table *keywords,
const char *file_name)
{
- string_list_ty *languages;
- message_list_ty **messages;
- int retval;
+ msgfmt_operand_ty operand;
+ msgfmt_operand_list_ty operands;
/* Convert the messages to Unicode. */
iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL);
- languages = string_list_alloc ();
- string_list_append (languages, locale_name);
-
- messages = XNMALLOC (1, message_list_ty *);
- messages[0] = mlp;
-
- retval = msgdomain_write_desktop_bulk (languages,
- messages,
- template_file_name,
- keywords,
- file_name);
-
- string_list_free (languages);
- free (messages);
+ /* Create a single-element operands and run the bulk operation on it. */
+ operand.language = (char *) locale_name;
+ operand.mlp = mlp;
+ operands.nitems = 1;
+ operands.items = &operand;
- return retval;
+ return msgdomain_write_desktop_bulk (&operands,
+ template_file_name,
+ keywords,
+ file_name);
}
diff --git a/gettext-tools/src/write-desktop.h b/gettext-tools/src/write-desktop.h
index 028b441..d6408e2 100644
--- a/gettext-tools/src/write-desktop.h
+++ b/gettext-tools/src/write-desktop.h
@@ -1,5 +1,6 @@
/* Reading Desktop Entry files.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
+ Free Software Foundation, Inc.
This file was written by Daiki Ueno <ueno@gnu.org>.
This program is free software: you can redistribute it and/or modify
@@ -18,7 +19,7 @@
#ifndef _WRITE_DESKTOP_H
#define _WRITE_DESKTOP_H
-#include "message.h"
+#include "msgfmt.h"
#ifdef __cplusplus
extern "C" {
@@ -37,8 +38,7 @@ extern int
const char *file_name);
extern int
- msgdomain_write_desktop_bulk (string_list_ty *languages,
- message_list_ty **messages,
+ msgdomain_write_desktop_bulk (msgfmt_operand_list_ty *operands,
const char *template_file_name,
hash_table *keywords,
const char *file_name);
diff --git a/gettext-tools/src/write-java.c b/gettext-tools/src/write-java.c
index 9cf4054..a21c002 100644
--- a/gettext-tools/src/write-java.c
+++ b/gettext-tools/src/write-java.c
@@ -1,5 +1,6 @@
/* Writing Java ResourceBundles.
- Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2010, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-java.h b/gettext-tools/src/write-java.h
index 4249edb..2bebc1f 100644
--- a/gettext-tools/src/write-java.h
+++ b/gettext-tools/src/write-java.h
@@ -1,5 +1,5 @@
/* Writing Java ResourceBundles.
- Copyright (C) 2001-2003 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-mo.c b/gettext-tools/src/write-mo.c
index ce27415..92dbbe4 100644
--- a/gettext-tools/src/write-mo.c
+++ b/gettext-tools/src/write-mo.c
@@ -1,5 +1,6 @@
/* Writing binary .mo files.
- Copyright (C) 1995-1998, 2000-2007 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2007, 2015 Free Software Foundation,
+ Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-mo.h b/gettext-tools/src/write-mo.h
index b1ea8ea..249ed58 100644
--- a/gettext-tools/src/write-mo.h
+++ b/gettext-tools/src/write-mo.h
@@ -1,5 +1,6 @@
/* Writing binary .mo files.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2015 Free Software
+ Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-po.c b/gettext-tools/src/write-po.c
index d49a95f..ec413d4 100644
--- a/gettext-tools/src/write-po.c
+++ b/gettext-tools/src/write-po.c
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2010, 2012, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
@@ -400,7 +401,7 @@ message_print_comment_filepos (const message_ty *mp, ostream_t stream,
else
sprintf (buffer, ":%ld", (long) pp->line_number);
len = strlen (cp) + strlen (buffer) + 1;
- if (column > 2 && column + len >= page_width)
+ if (column > 2 && column + len > page_width)
{
ostream_write_str (stream, "\n#:");
column = 2;
diff --git a/gettext-tools/src/write-po.h b/gettext-tools/src/write-po.h
index 9a243bf..ee8313a 100644
--- a/gettext-tools/src/write-po.h
+++ b/gettext-tools/src/write-po.h
@@ -1,5 +1,6 @@
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1998, 2000-2003, 2006, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2006, 2008, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/write-properties.c b/gettext-tools/src/write-properties.c
index 8b6dcee..4aaf923 100644
--- a/gettext-tools/src/write-properties.c
+++ b/gettext-tools/src/write-properties.c
@@ -1,5 +1,5 @@
/* Writing Java .properties files.
- Copyright (C) 2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-properties.h b/gettext-tools/src/write-properties.h
index 9f614b5..b29154e 100644
--- a/gettext-tools/src/write-properties.h
+++ b/gettext-tools/src/write-properties.h
@@ -1,5 +1,5 @@
/* Writing Java .properties files.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-qt.c b/gettext-tools/src/write-qt.c
index 50b96b7..42b2d84 100644
--- a/gettext-tools/src/write-qt.c
+++ b/gettext-tools/src/write-qt.c
@@ -1,5 +1,6 @@
/* Writing Qt .qm files.
- Copyright (C) 2003, 2005-2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2007, 2009, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-qt.h b/gettext-tools/src/write-qt.h
index 2b36da2..d83622a 100644
--- a/gettext-tools/src/write-qt.h
+++ b/gettext-tools/src/write-qt.h
@@ -1,5 +1,5 @@
/* Writing Qt .qm files.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-resources.c b/gettext-tools/src/write-resources.c
index 6759c1b..2fa7e48 100644
--- a/gettext-tools/src/write-resources.c
+++ b/gettext-tools/src/write-resources.c
@@ -1,5 +1,6 @@
/* Writing C# .resources files.
- Copyright (C) 2003, 2005, 2007-2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005, 2007-2009, 2011, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-resources.h b/gettext-tools/src/write-resources.h
index 7512f0f..2508816 100644
--- a/gettext-tools/src/write-resources.h
+++ b/gettext-tools/src/write-resources.h
@@ -1,5 +1,5 @@
/* Writing C# .resources files.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-stringtable.c b/gettext-tools/src/write-stringtable.c
index 34e171f..8846ac7 100644
--- a/gettext-tools/src/write-stringtable.c
+++ b/gettext-tools/src/write-stringtable.c
@@ -1,5 +1,5 @@
/* Writing NeXTstep/GNUstep .strings files.
- Copyright (C) 2003, 2006-2008 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2008, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-stringtable.h b/gettext-tools/src/write-stringtable.h
index 3130467..4e60dc2 100644
--- a/gettext-tools/src/write-stringtable.h
+++ b/gettext-tools/src/write-stringtable.h
@@ -1,5 +1,5 @@
/* Writing NeXTstep/GNUstep .strings files.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-tcl.c b/gettext-tools/src/write-tcl.c
index db582c6..1439431 100644
--- a/gettext-tools/src/write-tcl.c
+++ b/gettext-tools/src/write-tcl.c
@@ -1,5 +1,6 @@
/* Writing tcl/msgcat .msg files.
- Copyright (C) 2002-2003, 2005, 2007-2009 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005, 2007-2009, 2015 Free Software
+ Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-tcl.h b/gettext-tools/src/write-tcl.h
index e6a3dce..b10aa16 100644
--- a/gettext-tools/src/write-tcl.h
+++ b/gettext-tools/src/write-tcl.h
@@ -1,5 +1,5 @@
/* Writing tcl/msgcat .msg files.
- Copyright (C) 2002-2003 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/write-xml.c b/gettext-tools/src/write-xml.c
new file mode 100644
index 0000000..38e3195
--- /dev/null
+++ b/gettext-tools/src/write-xml.c
@@ -0,0 +1,107 @@
+/* Writing XML files.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
+ Free Software Foundation, Inc.
+ This file was written by Daiki Ueno <ueno@gnu.org>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "write-xml.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "error.h"
+#include "msgl-iconv.h"
+#include "po-charset.h"
+#include "read-catalog.h"
+#include "read-po.h"
+#include "fwriteerror.h"
+#include "xalloc.h"
+#include "gettext.h"
+
+#define _(str) gettext (str)
+
+int
+msgdomain_write_xml_bulk (msgfmt_operand_list_ty *operands,
+ const char *template_file_name,
+ its_rule_list_ty *its_rules,
+ const char *file_name)
+{
+ its_merge_context_ty *context;
+ size_t i;
+ FILE *fp;
+
+ if (strcmp (file_name, "-") == 0)
+ fp = stdout;
+ else
+ {
+ fp = fopen (file_name, "wb");
+ if (fp == NULL)
+ {
+ error (0, errno, _("cannot create output file \"%s\""),
+ file_name);
+ return 1;
+ }
+ }
+
+ context = its_merge_context_alloc (its_rules, template_file_name);
+ for (i = 0; i < operands->nitems; i++)
+ its_merge_context_merge (context,
+ operands->items[i].language,
+ operands->items[i].mlp);
+ its_merge_context_write (context, fp);
+ its_merge_context_free (context);
+
+ /* Make sure nothing went wrong. */
+ if (fwriteerror (fp))
+ {
+ error (0, errno, _("error while writing \"%s\" file"),
+ file_name);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+msgdomain_write_xml (message_list_ty *mlp,
+ const char *canon_encoding,
+ const char *locale_name,
+ const char *template_file_name,
+ its_rule_list_ty *its_rules,
+ const char *file_name)
+{
+ msgfmt_operand_ty operand;
+ msgfmt_operand_list_ty operands;
+
+ /* Convert the messages to Unicode. */
+ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL);
+
+ /* Create a single-element operands and run the bulk operation on it. */
+ operand.language = (char *) locale_name;
+ operand.mlp = mlp;
+ operands.nitems = 1;
+ operands.items = &operand;
+
+ return msgdomain_write_xml_bulk (&operands,
+ template_file_name,
+ its_rules,
+ file_name);
+}
diff --git a/gettext-tools/src/write-xml.h b/gettext-tools/src/write-xml.h
new file mode 100644
index 0000000..e627789
--- /dev/null
+++ b/gettext-tools/src/write-xml.h
@@ -0,0 +1,52 @@
+/* Reading XML files.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2014-2015
+ Free Software Foundation, Inc.
+ This file was written by Daiki Ueno <ueno@gnu.org>.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef _WRITE_XML_H
+#define _WRITE_XML_H
+
+#include "its.h"
+#include "msgfmt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write an XML file. mlp is a list containing the messages
+ to be output. locale_name is the locale name. template_file_name
+ is the template file. file_name is the output file. Return 0 if
+ ok, nonzero on error. */
+extern int
+ msgdomain_write_xml (message_list_ty *mlp,
+ const char *canon_encoding,
+ const char *locale_name,
+ const char *template_file_name,
+ its_rule_list_ty *its_rules,
+ const char *file_name);
+
+extern int
+ msgdomain_write_xml_bulk (msgfmt_operand_list_ty *operands,
+ const char *template_file_name,
+ its_rule_list_ty *its_rules,
+ const char *file_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _WRITE_XML_H */
diff --git a/gettext-tools/src/x-appdata.h b/gettext-tools/src/x-appdata.h
new file mode 100644
index 0000000..6171673
--- /dev/null
+++ b/gettext-tools/src/x-appdata.h
@@ -0,0 +1,42 @@
+/* xgettext AppData file backend.
+ Copyright (C) 2002-2003, 2006, 2013, 2015 Free Software Foundation,
+ Inc.
+ Written by Philip Withnall <philip.withnall@collabora.co.uk>, 2015.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+
+#include <stdio.h>
+
+#include "message.h"
+#include "xgettext.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* The scanner is implemented as ITS rules, in its/appdata.its. */
+
+#define EXTENSIONS_APPDATA \
+ { "appdata.xml", NULL }, \
+
+#define SCANNERS_APPDATA \
+ { "appdata", NULL, NULL, NULL, NULL, NULL }, \
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gettext-tools/src/x-awk.c b/gettext-tools/src/x-awk.c
index 6a6a9dc..648befe 100644
--- a/gettext-tools/src/x-awk.c
+++ b/gettext-tools/src/x-awk.c
@@ -1,5 +1,6 @@
/* xgettext awk backend.
- Copyright (C) 2002-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
diff --git a/gettext-tools/src/x-awk.h b/gettext-tools/src/x-awk.h
index 642c0e2..b0c1448 100644
--- a/gettext-tools/src/x-awk.h
+++ b/gettext-tools/src/x-awk.h
@@ -1,5 +1,5 @@
/* xgettext awk backend.
- Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
@@ -29,6 +29,8 @@ extern "C" {
#define EXTENSIONS_AWK \
{ "awk", "awk" }, \
+ { "gawk", "awk" }, \
+ { "twjr", "awk" }, \
#define SCANNERS_AWK \
{ "awk", extract_awk, \
diff --git a/gettext-tools/src/x-c.c b/gettext-tools/src/x-c.c
index 001cfd9..68e9f5d 100644
--- a/gettext-tools/src/x-c.c
+++ b/gettext-tools/src/x-c.c
@@ -1,5 +1,6 @@
/* xgettext C/C++/ObjectiveC backend.
- Copyright (C) 1995-1998, 2000-2009, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2009, 2012, 2015 Free Software
+ Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
@@ -143,6 +144,14 @@ x_objc_keyword (const char *name)
add_keyword (name, &objc_keywords);
}
+static bool additional_keywords_kde;
+
+void
+activate_additional_keywords_kde ()
+{
+ additional_keywords_kde = true;
+}
+
/* Finish initializing the keywords hash tables.
Called after argument processing, before each file is processed. */
static void
@@ -166,6 +175,50 @@ init_keywords ()
x_c_keyword ("dnpgettext:2c,3,4");
x_c_keyword ("dcnpgettext:2c,3,4");
+ if (additional_keywords_kde)
+ {
+ x_c_keyword ("i18n:1");
+ x_c_keyword ("i18nc:1c,2");
+ x_c_keyword ("i18np:1,2");
+ x_c_keyword ("i18ncp:1c,2,3");
+ x_c_keyword ("i18nd:2");
+ x_c_keyword ("i18ndc:2c,3");
+ x_c_keyword ("i18ndp:2,3");
+ x_c_keyword ("i18ndcp:2c,3,4");
+ x_c_keyword ("ki18n:1");
+ x_c_keyword ("ki18nc:1c,2");
+ x_c_keyword ("ki18np:1,2");
+ x_c_keyword ("ki18ncp:1c,2,3");
+ x_c_keyword ("ki18nd:2");
+ x_c_keyword ("ki18ndc:2c,3");
+ x_c_keyword ("ki18ndp:2,3");
+ x_c_keyword ("ki18ndcp:2c,3,4");
+ x_c_keyword ("I18N_NOOP:1");
+ x_c_keyword ("I18NC_NOOP:1c,2");
+ x_c_keyword ("I18N_NOOP2:1c,2");
+ x_c_keyword ("I18N_NOOP2_NOSTRIP:1c,2");
+ x_c_keyword ("xi18n:1");
+ x_c_keyword ("xi18nc:1c,2");
+ x_c_keyword ("xi18np:1,2");
+ x_c_keyword ("xi18ncp:1c,2,3");
+ x_c_keyword ("xi18nd:2");
+ x_c_keyword ("xi18ndc:2c,3");
+ x_c_keyword ("xi18ndp:2,3");
+ x_c_keyword ("xi18ndcp:2c,3,4");
+ x_c_keyword ("kxi18n:1");
+ x_c_keyword ("kxi18nc:1c,2");
+ x_c_keyword ("kxi18np:1,2");
+ x_c_keyword ("kxi18ncp:1c,2,3");
+ x_c_keyword ("kxi18nd:2");
+ x_c_keyword ("kxi18ndc:2c,3");
+ x_c_keyword ("kxi18ndp:2,3");
+ x_c_keyword ("kxi18ndcp:2c,3,4");
+ x_c_keyword ("XI18N_NOOP:1");
+ x_c_keyword ("XI18NC_NOOP:1c,2");
+ x_c_keyword ("XI18N_NOOP2:1c,2");
+ x_c_keyword ("XI18N_NOOP2_NOSTRIP:1c,2");
+ }
+
x_objc_keyword ("gettext");
x_objc_keyword ("dgettext:2");
x_objc_keyword ("dcgettext:2");
@@ -449,6 +502,50 @@ init_flag_table_gcc_internal ()
#endif
}
+void
+init_flag_table_kde ()
+{
+ xgettext_record_flag ("i18n:1:kde-format");
+ xgettext_record_flag ("i18nc:2:kde-format");
+ xgettext_record_flag ("i18np:1:kde-format");
+ xgettext_record_flag ("i18ncp:2:kde-format");
+ xgettext_record_flag ("i18nd:2:kde-format");
+ xgettext_record_flag ("i18ndc:3:kde-format");
+ xgettext_record_flag ("i18ndp:2:kde-format");
+ xgettext_record_flag ("i18ndcp:3:kde-format");
+ xgettext_record_flag ("ki18n:1:kde-format");
+ xgettext_record_flag ("ki18nc:2:kde-format");
+ xgettext_record_flag ("ki18np:1:kde-format");
+ xgettext_record_flag ("ki18ncp:2:kde-format");
+ xgettext_record_flag ("ki18nd:2:kde-format");
+ xgettext_record_flag ("ki18ndc:3:kde-format");
+ xgettext_record_flag ("ki18ndp:2:kde-format");
+ xgettext_record_flag ("ki18ndcp:3:kde-format");
+ xgettext_record_flag ("I18N_NOOP:1:kde-format");
+ xgettext_record_flag ("I18NC_NOOP:2:kde-format");
+ xgettext_record_flag ("I18N_NOOP2:2:kde-format");
+ xgettext_record_flag ("I18N_NOOP2_NOSTRIP:2:kde-format");
+ xgettext_record_flag ("xi18n:1:kde-kuit-format");
+ xgettext_record_flag ("xi18nc:2:kde-kuit-format");
+ xgettext_record_flag ("xi18np:1:kde-kuit-format");
+ xgettext_record_flag ("xi18ncp:2:kde-kuit-format");
+ xgettext_record_flag ("xi18nd:2:kde-kuit-format");
+ xgettext_record_flag ("xi18ndc:3:kde-kuit-format");
+ xgettext_record_flag ("xi18ndp:2:kde-kuit-format");
+ xgettext_record_flag ("xi18ndcp:3:kde-kuit-format");
+ xgettext_record_flag ("kxi18n:1:kde-kuit-format");
+ xgettext_record_flag ("kxi18nc:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18np:1:kde-kuit-format");
+ xgettext_record_flag ("kxi18ncp:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18nd:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18ndc:3:kde-kuit-format");
+ xgettext_record_flag ("kxi18ndp:2:kde-kuit-format");
+ xgettext_record_flag ("kxi18ndcp:3:kde-kuit-format");
+ xgettext_record_flag ("XI18N_NOOP:1:kde-kuit-format");
+ xgettext_record_flag ("XI18NC_NOOP:2:kde-kuit-format");
+ xgettext_record_flag ("XI18N_NOOP2:2:kde-kuit-format");
+ xgettext_record_flag ("XI18N_NOOP2_NOSTRIP:2:kde-kuit-format");
+}
/* ======================== Reading of characters. ======================== */
@@ -829,6 +926,9 @@ phase4_ungetc (int c)
/* True if ObjectiveC extensions are recognized. */
static bool objc_extensions;
+/* True if C++ extensions are recognized. */
+static bool cxx_extensions;
+
enum token_type_ty
{
token_type_character_constant, /* 'x' */
@@ -855,6 +955,7 @@ struct token_ty
char *string; /* for token_type_name, token_type_string_literal */
refcounted_string_list_ty *comment; /* for token_type_string_literal,
token_type_objc_special */
+ enum literalstring_escape_type escape; /* for token_type_string_literal */
long number;
int line_number;
};
@@ -884,13 +985,16 @@ literalstring_parse (const char *string, lex_pos_ty *pos,
logical_file_name,
line_number);
- for (p = string; *p != '\0'; p++)
+ for (p = string; ; )
{
- int c;
+ int c = *p++;
+
+ if (c == '\0')
+ break;
- if (*p != '\\')
+ if (c != '\\')
{
- mixed_string_buffer_append_char (bp, *p);
+ mixed_string_buffer_append_char (bp, c);
continue;
}
@@ -900,7 +1004,9 @@ literalstring_parse (const char *string, lex_pos_ty *pos,
continue;
}
- c = *++p;
+ c = *p++;
+ if (c == '\0')
+ break;
if (type & LET_ANSI_C)
switch (c)
@@ -940,7 +1046,9 @@ literalstring_parse (const char *string, lex_pos_ty *pos,
continue;
case 'x':
- c = *++p;
+ c = *p++;
+ if (c == '\0')
+ break;
switch (c)
{
default:
@@ -956,26 +1064,26 @@ literalstring_parse (const char *string, lex_pos_ty *pos,
{
int n;
- for (n = 0; ; ++p)
+ for (n = 0; ; c = *p++)
{
- switch (*p)
+ switch (c)
{
default:
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- n = n * 16 + *p - '0';
+ n = n * 16 + c - '0';
continue;
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F':
- n = n * 16 + 10 + *p - 'A';
+ n = n * 16 + 10 + c - 'A';
continue;
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f':
- n = n * 16 + 10 + *p - 'a';
+ n = n * 16 + 10 + c - 'a';
continue;
}
break;
@@ -996,7 +1104,7 @@ literalstring_parse (const char *string, lex_pos_ty *pos,
for (n = 0, j = 0; j < 3; ++j)
{
n = n * 8 + c - '0';
- c = *++p;
+ c = *p++;
switch (c)
{
default:
@@ -1021,23 +1129,24 @@ literalstring_parse (const char *string, lex_pos_ty *pos,
case 'U': case 'u':
{
unsigned char buf[8];
- int length = c == 'u' ? 4 : 8;
+ int prefix = c;
+ int length = prefix == 'u' ? 4 : 8;
int n, j;
for (n = 0, j = 0; j < length; j++)
{
- int c1 = *++p;
-
- if (c1 >= '0' && c1 <= '9')
- n = (n << 4) + (c1 - '0');
- else if (c1 >= 'A' && c1 <= 'F')
- n = (n << 4) + (c1 - 'A' + 10);
- else if (c1 >= 'a' && c1 <= 'f')
- n = (n << 4) + (c1 - 'a' + 10);
+ c = *p++;
+
+ if (c >= '0' && c <= '9')
+ n = (n << 4) + (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ n = (n << 4) + (c - 'A' + 10);
+ else if (c >= 'a' && c <= 'f')
+ n = (n << 4) + (c - 'a' + 10);
else
break;
- buf[j] = c1;
+ buf[j] = c;
}
if (j == length)
@@ -1059,7 +1168,7 @@ warning: invalid Unicode character"));
int i;
mixed_string_buffer_append_char (bp, '\\');
- mixed_string_buffer_append_char (bp, c);
+ mixed_string_buffer_append_char (bp, prefix);
for (i = 0; i < j; i++)
mixed_string_buffer_append_char (bp, buf[i]);
@@ -1070,6 +1179,9 @@ warning: invalid Unicode character"));
continue;
}
+ if (c == '\0')
+ break;
+
mixed_string_buffer_append_char (bp, c);
}
@@ -1098,6 +1210,9 @@ phase5_get (token_ty *tp)
int c;
int last_was_backslash;
bool raw_expected = false;
+ int delimiter_left_end;
+ int delimiter_right_start;
+ int last_rparen;
if (phase5_pushback_length)
{
@@ -1177,10 +1292,14 @@ phase5_get (token_ty *tp)
continue;
default:
- /* Recognize C++ string literals prefixed by R, u8, u8R,
- u, uR, U, UR, L, or LR. It is defined in ISO/IEC
- 9899:2011 2.14.5. Since gettext's argument is a byte
- sequence, we are only interested in u8, R, and u8R. */
+ /* Recognize string literals prefixed by R, u8, u8R, u,
+ uR, U, UR, L, or LR. It is defined in the C standard
+ ISO/IEC 9899:201x and the C++ standard ISO/IEC
+ 14882:2011. The raw string literals prefixed by R,
+ u8R, uR, UR, or LR are only valid in C++.
+
+ Since gettext's argument is a byte sequence, we are
+ only interested in u8, R, and u8R. */
if (c == '"')
{
bool is_prefix = false;
@@ -1188,8 +1307,11 @@ phase5_get (token_ty *tp)
switch (buffer[0])
{
case 'R':
- if (bufpos == 1)
- is_prefix = true;
+ if (cxx_extensions && bufpos == 1)
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
break;
case 'u':
if (bufpos == 1)
@@ -1198,30 +1320,39 @@ phase5_get (token_ty *tp)
switch (buffer[1])
{
case 'R':
- if (bufpos == 2)
- is_prefix = true;
+ if (cxx_extensions && bufpos == 2)
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
break;
case '8':
- if (bufpos == 2
- || (bufpos == 3 && buffer[2] == 'R'))
+ if (bufpos == 2)
is_prefix = true;
+ else if (cxx_extensions
+ && bufpos == 3 && buffer[2] == 'R')
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
break;
}
break;
case 'U':
case 'L':
- if (bufpos == 1
- || (bufpos == 2 && buffer[1] == 'R'))
+ if (bufpos == 1)
is_prefix = true;
+ else if (cxx_extensions
+ && bufpos == 2 && buffer[1] == 'R')
+ {
+ is_prefix = true;
+ raw_expected = true;
+ }
break;
}
if (is_prefix)
- {
- raw_expected = buffer[bufpos - 1] == 'R';
- bufpos = 0;
- goto string;
- }
+ goto string;
}
phase4_ungetc (c);
break;
@@ -1362,11 +1493,14 @@ phase5_get (token_ty *tp)
let the compiler complain about the argument not matching the
prototype. Just pretend it won't happen. */
last_was_backslash = false;
+ delimiter_left_end = -1;
+ delimiter_right_start = -1;
+ last_rparen = -1;
bufpos = 0;
for (;;)
{
c = phase3_getc ();
- if (last_was_backslash)
+ if (last_was_backslash && !raw_expected)
{
last_was_backslash = false;
if (bufpos >= bufmax)
@@ -1383,7 +1517,14 @@ phase5_get (token_ty *tp)
last_was_backslash = true;
/* FALLTHROUGH */
default:
- if (c == '\n' && !raw_expected)
+ if (raw_expected)
+ {
+ if (c == '(' && delimiter_left_end < 0)
+ delimiter_left_end = bufpos;
+ else if (c == ')' && delimiter_left_end >= 0)
+ last_rparen = bufpos;
+ }
+ else if (c == '\n')
{
error_with_progname = false;
error (0, 0,
@@ -1393,18 +1534,35 @@ phase5_get (token_ty *tp)
phase3_ungetc ('\n');
break;
}
- else
+ if (bufpos >= bufmax)
{
- if (bufpos >= bufmax)
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos++] = c;
+ continue;
+
+ case '"':
+ if (raw_expected && delimiter_left_end >= 0)
+ {
+ if (last_rparen < 0
+ || delimiter_left_end != bufpos - (last_rparen + 1)
+ || strncmp (buffer, buffer + last_rparen + 1,
+ delimiter_left_end) != 0)
{
- bufmax = 2 * bufmax + 10;
- buffer = xrealloc (buffer, bufmax);
+ if (bufpos >= bufmax)
+ {
+ bufmax = 2 * bufmax + 10;
+ buffer = xrealloc (buffer, bufmax);
+ }
+ buffer[bufpos++] = c;
+ continue;
}
- buffer[bufpos++] = c;
- continue;
+ delimiter_right_start = last_rparen;
}
+ break;
- case EOF: case '"':
+ case EOF:
break;
}
break;
@@ -1418,13 +1576,7 @@ phase5_get (token_ty *tp)
if (raw_expected)
{
- char *delimiter_left_end;
- char *delimiter_right_start;
-
- if (!(delimiter_left_end = strchr (buffer, '('))
- || !(delimiter_right_start = strrchr (buffer, ')'))
- || strncmp (buffer, delimiter_right_start + 1,
- (delimiter_left_end - buffer)) != 0)
+ if (delimiter_left_end < 0 || delimiter_right_start < 0)
{
error_with_progname = false;
error (0, 0, _("%s:%d: warning: unterminated string literal"),
@@ -1433,15 +1585,17 @@ phase5_get (token_ty *tp)
}
else
{
- *delimiter_right_start = '\0';
+ buffer[delimiter_right_start] = '\0';
tp->type = token_type_string_literal;
- tp->string = xstrdup (delimiter_left_end + 1);
+ tp->string = xstrdup (&buffer[delimiter_left_end + 1]);
+ tp->escape = LET_NONE;
tp->comment = add_reference (savable_comment);
return;
}
}
tp->type = token_type_string_literal;
tp->string = xstrdup (buffer);
+ tp->escape = LET_ANSI_C | LET_UNICODE;
tp->comment = add_reference (savable_comment);
return;
}
@@ -1695,6 +1849,7 @@ phase8a_get (token_ty *tp)
tp->string = new_string;
tp->comment = add_reference (savable_comment);
tp->type = token_type_string_literal;
+ tp->escape = LET_ANSI_C | LET_UNICODE;
}
}
@@ -1775,7 +1930,10 @@ phase8c_unget (token_ty *tp)
/* 8. Concatenate adjacent string literals to form single string
literals (because we don't expand macros, there are a few things we
- will miss). */
+ will miss).
+
+ FIXME: handle the case when the string literals have different
+ tp->escape setting. */
static void
phase8_get (token_ty *tp)
@@ -1832,6 +1990,9 @@ struct xgettext_token_ty
char *string;
/* This field is used only for xgettext_token_type_string_literal. */
+ enum literalstring_escape_type escape;
+
+ /* This field is used only for xgettext_token_type_string_literal. */
refcounted_string_list_ty *comment;
/* These fields are only for
@@ -1906,6 +2067,7 @@ x_c_lex (xgettext_token_ty *tp)
tp->type = xgettext_token_type_string_literal;
tp->string = token.string;
+ tp->escape = token.escape;
tp->comment = token.comment;
tp->pos.file_name = logical_file_name;
tp->pos.line_number = token.line_number;
@@ -2067,7 +2229,7 @@ extract_parenthesized (message_list_ty *mlp,
const char *encoding;
string = literalstring_parse (token.string, &token.pos,
- LET_ANSI_C | LET_UNICODE);
+ token.escape);
free (token.string);
token.string = string;
@@ -2094,7 +2256,7 @@ extract_parenthesized (message_list_ty *mlp,
token.pos.file_name,
token.pos.line_number,
token.comment,
- LET_ANSI_C | LET_UNICODE);
+ token.escape);
drop_reference (token.comment);
next_context_iter = null_context_list_iterator;
selectorcall_context_iter = null_context_list_iterator;
@@ -2160,6 +2322,18 @@ extract_c (FILE *f,
msgdomain_list_ty *mdlp)
{
objc_extensions = false;
+ cxx_extensions = false;
+ extract_whole_file (f, real_filename, logical_filename, flag_table, mdlp);
+}
+
+void
+extract_cxx (FILE *f,
+ const char *real_filename, const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp)
+{
+ objc_extensions = false;
+ cxx_extensions = true;
extract_whole_file (f, real_filename, logical_filename, flag_table, mdlp);
}
@@ -2170,5 +2344,6 @@ extract_objc (FILE *f,
msgdomain_list_ty *mdlp)
{
objc_extensions = true;
+ cxx_extensions = false;
extract_whole_file (f, real_filename, logical_filename, flag_table, mdlp);
}
diff --git a/gettext-tools/src/x-c.h b/gettext-tools/src/x-c.h
index 64e4953..9dc82b0 100644
--- a/gettext-tools/src/x-c.h
+++ b/gettext-tools/src/x-c.h
@@ -1,5 +1,6 @@
/* xgettext C/C++/ObjectiveC backend.
- Copyright (C) 2001-2003, 2006, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2009, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
@@ -45,7 +46,7 @@ extern "C" {
&flag_table_c, \
&formatstring_c, NULL, \
&literalstring_c }, \
- { "C++", extract_c, \
+ { "C++", extract_cxx, \
&flag_table_c, \
&formatstring_c, NULL, \
&literalstring_c }, \
@@ -58,11 +59,16 @@ extern "C" {
&formatstring_gcc_internal, &formatstring_gfc_internal, \
&literalstring_c }, \
-/* Scan a C/C++ file and add its translatable strings to mdlp. */
+/* Scan a C file and add its translatable strings to mdlp. */
extern void extract_c (FILE *fp, const char *real_filename,
const char *logical_filename,
flag_context_list_table_ty *flag_table,
msgdomain_list_ty *mdlp);
+/* Scan a C++ file and add its translatable strings to mdlp. */
+extern void extract_cxx (FILE *fp, const char *real_filename,
+ const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp);
/* Scan an ObjectiveC file and add its translatable strings to mdlp. */
extern void extract_objc (FILE *fp, const char *real_filename,
const char *logical_filename,
@@ -79,9 +85,12 @@ extern void x_objc_keyword (const char *name);
extern void x_c_trigraphs (void);
+extern void activate_additional_keywords_kde (void);
+
extern void init_flag_table_c (void);
extern void init_flag_table_objc (void);
extern void init_flag_table_gcc_internal (void);
+extern void init_flag_table_kde (void);
extern struct literalstring_parser literalstring_c;
diff --git a/gettext-tools/src/x-csharp.c b/gettext-tools/src/x-csharp.c
index 5091c3b..8bb87d4 100644
--- a/gettext-tools/src/x-csharp.c
+++ b/gettext-tools/src/x-csharp.c
@@ -1,5 +1,6 @@
/* xgettext C# backend.
- Copyright (C) 2003, 2005-2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2009, 2011, 2015 Free Software Foundation,
+ Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-csharp.h b/gettext-tools/src/x-csharp.h
index de37789..e3c6173 100644
--- a/gettext-tools/src/x-csharp.h
+++ b/gettext-tools/src/x-csharp.h
@@ -1,5 +1,5 @@
/* xgettext C# backend.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-desktop.c b/gettext-tools/src/x-desktop.c
index 320266e..e4ce5b3 100644
--- a/gettext-tools/src/x-desktop.c
+++ b/gettext-tools/src/x-desktop.c
@@ -1,5 +1,5 @@
/* xgettext Desktop Entry backend.
- Copyright (C) 2014 Free Software Foundation, Inc.
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
This file was written by Daiki Ueno <ueno@gnu.org>, 2014.
diff --git a/gettext-tools/src/x-desktop.h b/gettext-tools/src/x-desktop.h
index d24f174..a5c954b 100644
--- a/gettext-tools/src/x-desktop.h
+++ b/gettext-tools/src/x-desktop.h
@@ -1,5 +1,5 @@
/* xgettext Desktop Entry backend.
- Copyright (C) 2014 Free Software Foundation, Inc.
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
Written by Daiki Ueno <ueno@gnu.org>, 2014.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-elisp.c b/gettext-tools/src/x-elisp.c
index 50c3d55..bbe7121 100644
--- a/gettext-tools/src/x-elisp.c
+++ b/gettext-tools/src/x-elisp.c
@@ -1,5 +1,6 @@
/* xgettext Emacs Lisp backend.
- Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2001-2002.
diff --git a/gettext-tools/src/x-elisp.h b/gettext-tools/src/x-elisp.h
index f939957..618a495 100644
--- a/gettext-tools/src/x-elisp.h
+++ b/gettext-tools/src/x-elisp.h
@@ -1,5 +1,5 @@
/* xgettext Emacs Lisp backend.
- Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-glade.c b/gettext-tools/src/x-glade.c
deleted file mode 100644
index eebce00..0000000
--- a/gettext-tools/src/x-glade.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/* xgettext glade backend.
- Copyright (C) 2002-2003, 2005-2009, 2013 Free Software Foundation, Inc.
-
- This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
-
- 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 <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-/* Specification. */
-#include "x-glade.h"
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "message.h"
-#include "xgettext.h"
-#include "error.h"
-#include "xerror.h"
-#include "xvasprintf.h"
-#include "basename.h"
-#include "progname.h"
-#include "xalloc.h"
-#include "hash.h"
-#include "po-charset.h"
-#include "gettext.h"
-#include "libexpat-compat.h"
-
-#define _(s) gettext(s)
-
-
-/* Glade is an XML based format with three variants. The syntax for
- each format is defined as follows.
-
- - Glade 1
- Some example files are contained in libglade-0.16.
-
- - Glade 2
- See http://library.gnome.org/devel/libglade/unstable/libglade-dtd.html
-
- - GtkBuilder
- See https://developer.gnome.org/gtk3/stable/GtkBuilder.html#BUILDER-UI */
-
-
-/* ====================== Keyword set customization. ====================== */
-
-/* If true extract all strings. */
-static bool extract_all = false;
-
-/* The keywords correspond to the translatable elements in Glade 1.
- For Glade 2 and GtkBuilder, translatable content is determined by
- the translatable="..." attribute, thus those keywords are not used. */
-static hash_table keywords;
-static bool default_keywords = true;
-
-
-void
-x_glade_extract_all ()
-{
- extract_all = true;
-}
-
-
-void
-x_glade_keyword (const char *name)
-{
- if (name == NULL)
- default_keywords = false;
- else
- {
- if (keywords.table == NULL)
- hash_init (&keywords, 100);
-
- hash_insert_entry (&keywords, name, strlen (name), NULL);
- }
-}
-
-/* Finish initializing the keywords hash table.
- Called after argument processing, before each file is processed. */
-static void
-init_keywords ()
-{
- if (default_keywords)
- {
- /* When adding new keywords here, also update the documentation in
- xgettext.texi! */
- x_glade_keyword ("label");
- x_glade_keyword ("title");
- x_glade_keyword ("text");
- x_glade_keyword ("format");
- x_glade_keyword ("copyright");
- x_glade_keyword ("comments");
- x_glade_keyword ("preview_text");
- x_glade_keyword ("tooltip");
- default_keywords = false;
- }
-}
-
-
-
-/* ============================= XML parsing. ============================= */
-
-#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
-
-/* Accumulator for the extracted messages. */
-static message_list_ty *mlp;
-
-/* Logical filename, used to label the extracted messages. */
-static char *logical_file_name;
-
-/* XML parser. */
-static XML_Parser parser;
-
-struct element_state
-{
- bool extract_string;
- bool extract_context; /* used by Glade 2 */
- char *extracted_comment; /* used by Glade 2 or GtkBuilder */
- char *extracted_context; /* used by GtkBuilder */
- int lineno;
- char *buffer;
- size_t bufmax;
- size_t buflen;
-};
-static struct element_state *stack;
-static size_t stack_size;
-
-/* Ensures stack_size >= size. */
-static void
-ensure_stack_size (size_t size)
-{
- if (size > stack_size)
- {
- stack_size = 2 * stack_size;
- if (stack_size < size)
- stack_size = size;
- stack =
- (struct element_state *)
- xrealloc (stack, stack_size * sizeof (struct element_state));
- }
-}
-
-static size_t stack_depth;
-
-/* Parser logic for each Glade compatible file format. */
-struct element_parser
-{
- void (*start_element) (struct element_state *p, const char *name,
- const char **attributes);
- void (*end_element) (struct element_state *p, const char *name);
-};
-static struct element_parser *element_parser;
-
-static void
-start_element_null (struct element_state *p, const char *name,
- const char **attributes)
-{
-}
-
-static void
-end_element_null (struct element_state *p, const char *name)
-{
-}
-
-static void
-start_element_glade1 (struct element_state *p, const char *name,
- const char **attributes)
-{
- void *hash_result;
-
- /* In Glade 1, a few specific elements are translatable without
- --extract-all option. */
- p->extract_string = extract_all;
- if (!p->extract_string)
- p->extract_string =
- (hash_find_entry (&keywords, name, strlen (name), &hash_result) == 0);
-}
-
-static void
-end_element_glade1 (struct element_state *p, const char *name)
-{
- lex_pos_ty pos;
-
- pos.file_name = logical_file_name;
- pos.line_number = p->lineno;
-
- if (p->buffer != NULL)
- {
- remember_a_message (mlp, NULL, p->buffer,
- null_context, &pos,
- p->extracted_comment, savable_comment);
- p->buffer = NULL;
- }
-}
-
-static void
-start_element_glade2 (struct element_state *p, const char *name,
- const char **attributes)
-{
- /* In Glade 2, all <property> and <atkproperty> elements are translatable
- that have the attribute translatable="yes".
- See <http://library.gnome.org/devel/libglade/unstable/libglade-dtd.html>.
- The translator comment is found in the attribute comments="...".
- See <http://live.gnome.org/TranslationProject/DevGuidelines/Use comments>.
- If the element has the attribute context="yes", the content of
- the element is in the form "msgctxt|msgid". */
- if (strcmp (name, "property") == 0 || strcmp (name, "atkproperty") == 0)
- {
- bool has_translatable = false;
- bool has_context = false;
- const char *extracted_comment = NULL;
- const char **attp = attributes;
- while (*attp != NULL)
- {
- if (strcmp (attp[0], "translatable") == 0)
- has_translatable = (strcmp (attp[1], "yes") == 0);
- else if (strcmp (attp[0], "comments") == 0)
- extracted_comment = attp[1];
- else if (strcmp (attp[0], "context") == 0)
- has_context = (strcmp (attp[1], "yes") == 0);
- attp += 2;
- }
- p->extract_string = has_translatable;
- p->extract_context = has_context;
- p->extracted_comment =
- (has_translatable && extracted_comment != NULL
- ? xstrdup (extracted_comment)
- : NULL);
- }
-
- /* In Glade 2, the attribute description="..." of <atkaction>
- element is also translatable. */
- if (strcmp (name, "atkaction") == 0)
- {
- const char **attp = attributes;
- while (*attp != NULL)
- {
- if (strcmp (attp[0], "description") == 0)
- {
- if (strcmp (attp[1], "") != 0)
- {
- lex_pos_ty pos;
-
- pos.file_name = logical_file_name;
- pos.line_number = XML_GetCurrentLineNumber (parser);
-
- remember_a_message (mlp, NULL, xstrdup (attp[1]),
- null_context, &pos,
- NULL, savable_comment);
- }
- break;
- }
- attp += 2;
- }
- }
-}
-
-static void
-end_element_glade2 (struct element_state *p, const char *name)
-{
- lex_pos_ty pos;
- char *msgid = NULL;
- char *msgctxt = NULL;
-
- pos.file_name = logical_file_name;
- pos.line_number = p->lineno;
-
- if (p->extract_context)
- {
- char *separator = strchr (p->buffer, '|');
-
- if (separator == NULL)
- {
- error_with_progname = false;
- error_at_line (0, 0,
- pos.file_name,
- pos.line_number,
- _("\
-Missing context for the string extracted from '%s' element"),
- name);
- error_with_progname = true;
- }
- else
- {
- *separator = '\0';
- msgid = xstrdup (separator + 1);
- msgctxt = xstrdup (p->buffer);
- }
- }
- else
- {
- msgid = p->buffer;
- p->buffer = NULL;
- }
-
- if (msgid != NULL)
- remember_a_message (mlp, msgctxt, msgid,
- null_context, &pos,
- p->extracted_comment, savable_comment);
-}
-
-static void
-start_element_gtkbuilder (struct element_state *p, const char *name,
- const char **attributes)
-{
- /* In GtkBuilder (used by Glade 3), all elements are translatable
- that have the attribute translatable="yes".
- See <https://developer.gnome.org/gtk3/stable/GtkBuilder.html#BUILDER-UI>.
- The translator comment is found in the attribute comments="..."
- and context is found in the attribute context="...". */
- bool has_translatable = false;
- const char *extracted_comment = NULL;
- const char *extracted_context = NULL;
- const char **attp = attributes;
- while (*attp != NULL)
- {
- if (strcmp (attp[0], "translatable") == 0)
- has_translatable = (strcmp (attp[1], "yes") == 0);
- else if (strcmp (attp[0], "comments") == 0)
- extracted_comment = attp[1];
- else if (strcmp (attp[0], "context") == 0)
- extracted_context = attp[1];
- attp += 2;
- }
- p->extract_string = has_translatable;
- p->extracted_comment =
- (has_translatable && extracted_comment != NULL
- ? xstrdup (extracted_comment)
- : NULL);
- p->extracted_context =
- (has_translatable && extracted_context != NULL
- ? xstrdup (extracted_context)
- : NULL);
-}
-
-static void
-end_element_gtkbuilder (struct element_state *p, const char *name)
-{
- lex_pos_ty pos;
-
- pos.file_name = logical_file_name;
- pos.line_number = p->lineno;
-
- if (p->buffer != NULL)
- {
- remember_a_message (mlp, p->extracted_context, p->buffer,
- null_context, &pos,
- p->extracted_comment, savable_comment);
- p->buffer = NULL;
- p->extracted_context = NULL;
- }
-}
-
-static struct element_parser element_parser_null =
-{
- start_element_null,
- end_element_null
-};
-
-static struct element_parser element_parser_glade1 =
-{
- start_element_glade1,
- end_element_glade1
-};
-
-static struct element_parser element_parser_glade2 =
-{
- start_element_glade2,
- end_element_glade2
-};
-
-static struct element_parser element_parser_gtkbuilder =
-{
- start_element_gtkbuilder,
- end_element_gtkbuilder
-};
-
-/* Callback called when <element> is seen. */
-static void
-start_element_handler (void *userData, const char *name,
- const char **attributes)
-{
- struct element_state *p;
-
- if (!stack_depth)
- {
- if (strcmp (name, "GTK-Interface") == 0)
- element_parser = &element_parser_glade1;
- else if (strcmp (name, "glade-interface") == 0)
- element_parser = &element_parser_glade2;
- else if (strcmp (name, "interface") == 0)
- element_parser = &element_parser_gtkbuilder;
- else
- {
- element_parser = &element_parser_null;
- error_with_progname = false;
- error_at_line (0, 0,
- logical_file_name,
- XML_GetCurrentLineNumber (parser),
- _("\
-The root element <%s> is not allowed in a valid Glade file"),
- name);
- error_with_progname = true;
- }
- }
-
- /* Increase stack depth. */
- stack_depth++;
- ensure_stack_size (stack_depth + 1);
-
- /* Don't extract a string for the containing element. */
- stack[stack_depth - 1].extract_string = false;
-
- p = &stack[stack_depth];
- p->extract_string = false;
- p->extract_context = false;
- p->extracted_comment = NULL;
- p->extracted_context = NULL;
-
- element_parser->start_element (p, name, attributes);
-
- p->lineno = XML_GetCurrentLineNumber (parser);
- p->buffer = NULL;
- p->bufmax = 0;
- p->buflen = 0;
- if (!p->extract_string)
- savable_comment_reset ();
-}
-
-/* Callback called when </element> is seen. */
-static void
-end_element_handler (void *userData, const char *name)
-{
- struct element_state *p = &stack[stack_depth];
-
- /* Actually extract string. */
- if (p->extract_string)
- {
- /* Don't extract the empty string. */
- if (p->buflen > 0)
- {
- if (p->buflen == p->bufmax)
- p->buffer = (char *) xrealloc (p->buffer, p->buflen + 1);
- p->buffer[p->buflen] = '\0';
-
- element_parser->end_element (p, name);
- }
- }
-
- /* Free memory for this stack level. */
- if (p->extracted_comment != NULL)
- free (p->extracted_comment);
- if (p->extracted_context != NULL)
- free (p->extracted_context);
- if (p->buffer != NULL)
- free (p->buffer);
-
- /* Decrease stack depth. */
- stack_depth--;
-
- savable_comment_reset ();
-}
-
-/* Callback called when some text is seen. */
-static void
-character_data_handler (void *userData, const char *s, int len)
-{
- struct element_state *p = &stack[stack_depth];
-
- /* Accumulate character data. */
- if (len > 0)
- {
- if (p->buflen + len > p->bufmax)
- {
- p->bufmax = 2 * p->bufmax;
- if (p->bufmax < p->buflen + len)
- p->bufmax = p->buflen + len;
- p->buffer = (char *) xrealloc (p->buffer, p->bufmax);
- }
- memcpy (p->buffer + p->buflen, s, len);
- p->buflen += len;
- }
-}
-
-/* Callback called when some comment text is seen. */
-static void
-comment_handler (void *userData, const char *data)
-{
- /* Split multiline comment into lines, and remove leading and trailing
- whitespace. */
- char *copy = xstrdup (data);
- char *p;
- char *q;
-
- for (p = copy; (q = strchr (p, '\n')) != NULL; p = q + 1)
- {
- while (p[0] == ' ' || p[0] == '\t')
- p++;
- while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
- q--;
- *q = '\0';
- savable_comment_add (p);
- }
- q = p + strlen (p);
- while (p[0] == ' ' || p[0] == '\t')
- p++;
- while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
- q--;
- *q = '\0';
- savable_comment_add (p);
- free (copy);
-}
-
-
-static void
-do_extract_glade (FILE *fp,
- const char *real_filename, const char *logical_filename,
- msgdomain_list_ty *mdlp)
-{
- mlp = mdlp->item[0]->messages;
-
- /* expat feeds us strings in UTF-8 encoding. */
- xgettext_current_source_encoding = po_charset_utf8;
-
- logical_file_name = xstrdup (logical_filename);
-
- init_keywords ();
-
- parser = XML_ParserCreate (NULL);
- if (parser == NULL)
- error (EXIT_FAILURE, 0, _("memory exhausted"));
-
- XML_SetElementHandler (parser, start_element_handler, end_element_handler);
- XML_SetCharacterDataHandler (parser, character_data_handler);
- XML_SetCommentHandler (parser, comment_handler);
-
- stack_depth = 0;
- element_parser = &element_parser_null;
-
- while (!feof (fp))
- {
- char buf[4096];
- int count = fread (buf, 1, sizeof buf, fp);
-
- if (count == 0)
- {
- if (ferror (fp))
- error (EXIT_FAILURE, errno, _("\
-error while reading \"%s\""), real_filename);
- /* EOF reached. */
- break;
- }
-
- if (XML_Parse (parser, buf, count, 0) == 0)
- error (EXIT_FAILURE, 0, _("%s:%lu:%lu: %s"), logical_filename,
- (unsigned long) XML_GetCurrentLineNumber (parser),
- (unsigned long) XML_GetCurrentColumnNumber (parser) + 1,
- XML_ErrorString (XML_GetErrorCode (parser)));
- }
-
- if (XML_Parse (parser, NULL, 0, 1) == 0)
- error (EXIT_FAILURE, 0, _("%s:%lu:%lu: %s"), logical_filename,
- (unsigned long) XML_GetCurrentLineNumber (parser),
- (unsigned long) XML_GetCurrentColumnNumber (parser) + 1,
- XML_ErrorString (XML_GetErrorCode (parser)));
-
- XML_ParserFree (parser);
-
- /* Close scanner. */
- logical_file_name = NULL;
- parser = NULL;
-}
-
-#endif
-
-void
-extract_glade (FILE *fp,
- const char *real_filename, const char *logical_filename,
- flag_context_list_table_ty *flag_table,
- msgdomain_list_ty *mdlp)
-{
-#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
- if (LIBEXPAT_AVAILABLE ())
- do_extract_glade (fp, real_filename, logical_filename, mdlp);
- else
-#endif
- {
- multiline_error (xstrdup (""),
- xasprintf (_("\
-Language \"glade\" is not supported. %s relies on expat.\n\
-This version was built without expat.\n"),
- basename (program_name)));
- exit (EXIT_FAILURE);
- }
-}
diff --git a/gettext-tools/src/x-glade.h b/gettext-tools/src/x-glade.h
index f212d2b..fda5876 100644
--- a/gettext-tools/src/x-glade.h
+++ b/gettext-tools/src/x-glade.h
@@ -1,5 +1,5 @@
/* xgettext glade backend.
- Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
@@ -27,25 +27,16 @@ extern "C" {
#endif
-#define EXTENSIONS_GLADE \
- { "glade", "glade" }, \
- { "glade2", "glade" }, \
- { "ui", "glade" }, \
-
-#define SCANNERS_GLADE \
- { "glade", extract_glade, NULL, NULL, NULL, NULL }, \
-
-/* Scan a glade XML file and add its translatable strings to mdlp. */
-extern void extract_glade (FILE *fp, const char *real_filename,
- const char *logical_filename,
- flag_context_list_table_ty *flag_table,
- msgdomain_list_ty *mdlp);
+/* The scanner is implemented as ITS rules, in its/glade[12].its and
+ its/gtkbuilder.its. */
+#define EXTENSIONS_GLADE \
+ { "glade", NULL }, \
+ { "glade2", NULL }, \
+ { "ui", NULL }, \
-/* Handling of options specific to this language. */
-
-extern void x_glade_extract_all (void);
-extern void x_glade_keyword (const char *name);
+#define SCANNERS_GLADE \
+ { "glade", NULL, NULL, NULL, NULL, NULL }, \
#ifdef __cplusplus
diff --git a/gettext-tools/src/x-gsettings.c b/gettext-tools/src/x-gsettings.c
deleted file mode 100644
index 14a2584..0000000
--- a/gettext-tools/src/x-gsettings.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/* xgettext GSettings schema file backend.
- Copyright (C) 2002-2003, 2005-2009, 2013 Free Software Foundation, Inc.
-
- This file was written by Daiki Ueno <ueno@gnu.org>, 2013.
-
- 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 <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-/* Specification. */
-#include "x-gsettings.h"
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "message.h"
-#include "xgettext.h"
-#include "error.h"
-#include "xerror.h"
-#include "xvasprintf.h"
-#include "basename.h"
-#include "progname.h"
-#include "xalloc.h"
-#include "hash.h"
-#include "po-charset.h"
-#include "gettext.h"
-#include "libexpat-compat.h"
-
-#define _(s) gettext(s)
-
-
-/* GSettings schema file is an XML based format.
- The syntax is defined in glib/gio/gschema.dtd and:
- https://developer.gnome.org/gio/unstable/GSettings.html */
-
-
-/* ====================== Keyword set customization. ====================== */
-
-/* If true extract all strings. */
-static bool extract_all = false;
-
-
-/* ============================= XML parsing. ============================= */
-
-#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
-
-/* Accumulator for the extracted messages. */
-static message_list_ty *mlp;
-
-/* Logical filename, used to label the extracted messages. */
-static char *logical_file_name;
-
-/* XML parser. */
-static XML_Parser parser;
-
-enum whitespace_type_ty
-{
- none,
- normalize,
- strip
-};
-typedef enum whitespace_type_ty whitespace_type_ty;
-
-struct element_state
-{
- bool extract_string;
- whitespace_type_ty whitespace;
- char *extracted_context;
- int lineno;
- char *buffer;
- size_t bufmax;
- size_t buflen;
-};
-static struct element_state *stack;
-static size_t stack_size;
-
-static char *
-normalize_whitespace (const char *text, whitespace_type_ty whitespace)
-{
- if (whitespace == none)
- return xstrdup (text);
- else
- {
- char *result, *p;
-
- /* Strip whitespaces at the beginning/end of the text. */
- result = xstrdup (text + strspn (text, " \t\n"));
- for (p = result + strlen (result);
- p > result && (*p == '\0' || *p == ' ' || *p == '\t' || *p == '\n');
- p--)
- ;
- if (p > result)
- *++p = '\0';
-
- /* Normalize whitespaces within the text. */
- if (whitespace == normalize)
- {
- char *end = result + strlen (result);
- for (p = result; *p != '\0';)
- {
- size_t len = strspn (p, " \t\n");
- if (len > 0)
- {
- *p = ' ';
- memmove (p + 1, p + len, end - (p + len));
- end -= len - 1;
- *end = '\0';
- p++;
- }
- p += strcspn (p, " \t\n");
- }
- }
- return result;
- }
-}
-
-/* Ensures stack_size >= size. */
-static void
-ensure_stack_size (size_t size)
-{
- if (size > stack_size)
- {
- stack_size = 2 * stack_size;
- if (stack_size < size)
- stack_size = size;
- stack =
- (struct element_state *)
- xrealloc (stack, stack_size * sizeof (struct element_state));
- }
-}
-
-static size_t stack_depth;
-
-/* Callback called when <element> is seen. */
-static void
-start_element_handler (void *userData, const char *name,
- const char **attributes)
-{
- struct element_state *p;
-
- /* Increase stack depth. */
- stack_depth++;
- ensure_stack_size (stack_depth + 1);
-
- /* Don't extract a string for the containing element. */
- stack[stack_depth - 1].extract_string = false;
-
- p = &stack[stack_depth];
- p->extract_string = extract_all;
- p->extracted_context = NULL;
-
- if (!p->extract_string)
- {
- bool has_translatable = false;
- whitespace_type_ty whitespace = none;
- const char *extracted_context = NULL;
- if (strcmp (name, "summary") == 0 || strcmp (name, "description") == 0)
- {
- has_translatable = true;
- whitespace = normalize;
- }
- else if (strcmp (name, "default") == 0)
- {
- const char *extracted_l10n = NULL;
- const char **attp = attributes;
- while (*attp != NULL)
- {
- if (strcmp (attp[0], "context") == 0)
- extracted_context = attp[1];
- else if (strcmp (attp[0], "l10n") == 0)
- extracted_l10n = attp[1];
- attp += 2;
- }
- if (extracted_l10n != NULL)
- {
- has_translatable = true;
- whitespace = strip;
- }
- }
- p->extract_string = has_translatable;
- p->whitespace = whitespace;
- p->extracted_context =
- (has_translatable && extracted_context != NULL
- ? xstrdup (extracted_context)
- : NULL);
- }
-
- p->lineno = XML_GetCurrentLineNumber (parser);
- p->buffer = NULL;
- p->bufmax = 0;
- p->buflen = 0;
- if (!p->extract_string)
- savable_comment_reset ();
-}
-
-/* Callback called when </element> is seen. */
-static void
-end_element_handler (void *userData, const char *name)
-{
- struct element_state *p = &stack[stack_depth];
-
- /* Actually extract string. */
- if (p->extract_string)
- {
- /* Don't extract the empty string. */
- if (p->buflen > 0)
- {
- lex_pos_ty pos;
-
- if (p->buflen == p->bufmax)
- p->buffer = (char *) xrealloc (p->buffer, p->buflen + 1);
- p->buffer[p->buflen] = '\0';
-
- pos.file_name = logical_file_name;
- pos.line_number = p->lineno;
-
- if (p->buffer != NULL)
- {
- remember_a_message (mlp, p->extracted_context,
- normalize_whitespace (p->buffer,
- p->whitespace),
- null_context, &pos,
- NULL, savable_comment);
- p->extracted_context = NULL;
- }
- }
- }
-
- /* Free memory for this stack level. */
- if (p->extracted_context != NULL)
- free (p->extracted_context);
- if (p->buffer != NULL)
- free (p->buffer);
-
- /* Decrease stack depth. */
- stack_depth--;
-
- savable_comment_reset ();
-}
-
-/* Callback called when some text is seen. */
-static void
-character_data_handler (void *userData, const char *s, int len)
-{
- struct element_state *p = &stack[stack_depth];
-
- /* Accumulate character data. */
- if (len > 0)
- {
- if (p->buflen + len > p->bufmax)
- {
- p->bufmax = 2 * p->bufmax;
- if (p->bufmax < p->buflen + len)
- p->bufmax = p->buflen + len;
- p->buffer = (char *) xrealloc (p->buffer, p->bufmax);
- }
- memcpy (p->buffer + p->buflen, s, len);
- p->buflen += len;
- }
-}
-
-/* Callback called when some comment text is seen. */
-static void
-comment_handler (void *userData, const char *data)
-{
- /* Split multiline comment into lines, and remove leading and trailing
- whitespace. */
- char *copy = xstrdup (data);
- char *p;
- char *q;
-
- for (p = copy; (q = strchr (p, '\n')) != NULL; p = q + 1)
- {
- while (p[0] == ' ' || p[0] == '\t')
- p++;
- while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
- q--;
- *q = '\0';
- savable_comment_add (p);
- }
- q = p + strlen (p);
- while (p[0] == ' ' || p[0] == '\t')
- p++;
- while (q > p && (q[-1] == ' ' || q[-1] == '\t'))
- q--;
- *q = '\0';
- savable_comment_add (p);
- free (copy);
-}
-
-
-static void
-do_extract_gsettings (FILE *fp,
- const char *real_filename, const char *logical_filename,
- msgdomain_list_ty *mdlp)
-{
- mlp = mdlp->item[0]->messages;
-
- /* expat feeds us strings in UTF-8 encoding. */
- xgettext_current_source_encoding = po_charset_utf8;
-
- logical_file_name = xstrdup (logical_filename);
-
- parser = XML_ParserCreate (NULL);
- if (parser == NULL)
- error (EXIT_FAILURE, 0, _("memory exhausted"));
-
- XML_SetElementHandler (parser, start_element_handler, end_element_handler);
- XML_SetCharacterDataHandler (parser, character_data_handler);
- XML_SetCommentHandler (parser, comment_handler);
-
- stack_depth = 0;
-
- while (!feof (fp))
- {
- char buf[4096];
- int count = fread (buf, 1, sizeof buf, fp);
-
- if (count == 0)
- {
- if (ferror (fp))
- error (EXIT_FAILURE, errno, _("\
-error while reading \"%s\""), real_filename);
- /* EOF reached. */
- break;
- }
-
- if (XML_Parse (parser, buf, count, 0) == 0)
- error (EXIT_FAILURE, 0, _("%s:%lu:%lu: %s"), logical_filename,
- (unsigned long) XML_GetCurrentLineNumber (parser),
- (unsigned long) XML_GetCurrentColumnNumber (parser) + 1,
- XML_ErrorString (XML_GetErrorCode (parser)));
- }
-
- if (XML_Parse (parser, NULL, 0, 1) == 0)
- error (EXIT_FAILURE, 0, _("%s:%lu:%lu: %s"), logical_filename,
- (unsigned long) XML_GetCurrentLineNumber (parser),
- (unsigned long) XML_GetCurrentColumnNumber (parser) + 1,
- XML_ErrorString (XML_GetErrorCode (parser)));
-
- XML_ParserFree (parser);
-
- /* Close scanner. */
- logical_file_name = NULL;
- parser = NULL;
-}
-
-#endif
-
-void
-extract_gsettings (FILE *fp,
- const char *real_filename, const char *logical_filename,
- flag_context_list_table_ty *flag_table,
- msgdomain_list_ty *mdlp)
-{
-#if DYNLOAD_LIBEXPAT || HAVE_LIBEXPAT
- if (LIBEXPAT_AVAILABLE ())
- do_extract_gsettings (fp, real_filename, logical_filename, mdlp);
- else
-#endif
- {
- multiline_error (xstrdup (""),
- xasprintf (_("\
-Language \"gsettings\" is not supported. %s relies on expat.\n\
-This version was built without expat.\n"),
- basename (program_name)));
- exit (EXIT_FAILURE);
- }
-}
diff --git a/gettext-tools/src/x-gsettings.h b/gettext-tools/src/x-gsettings.h
index b06016d..00b968c 100644
--- a/gettext-tools/src/x-gsettings.h
+++ b/gettext-tools/src/x-gsettings.h
@@ -1,5 +1,6 @@
/* xgettext GSettings schema file backend.
- Copyright (C) 2002-2003, 2006, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2013, 2015 Free Software Foundation,
+ Inc.
Written by Daiki Ueno <ueno@gnu.org>, 2013.
This program is free software: you can redistribute it and/or modify
@@ -27,17 +28,13 @@ extern "C" {
#endif
-#define EXTENSIONS_GSETTINGS \
- { "gschema.xml", "gsettings" }, \
+/* The scanner is implemented as ITS rules, in its/gsettings.its. */
-#define SCANNERS_GSETTINGS \
- { "gsettings", extract_gsettings, NULL, NULL, NULL, NULL }, \
+#define EXTENSIONS_GSETTINGS \
+ { "gschema.xml", NULL }, \
-/* Scan a gsettings XML file and add its translatable strings to mdlp. */
-extern void extract_gsettings (FILE *fp, const char *real_filename,
- const char *logical_filename,
- flag_context_list_table_ty *flag_table,
- msgdomain_list_ty *mdlp);
+#define SCANNERS_GSETTINGS \
+ { "gsettings", NULL, NULL, NULL, NULL, NULL }, \
#ifdef __cplusplus
diff --git a/gettext-tools/src/x-java.c b/gettext-tools/src/x-java.c
index 58c1ad7..3bc75fe 100644
--- a/gettext-tools/src/x-java.c
+++ b/gettext-tools/src/x-java.c
@@ -1,5 +1,5 @@
/* xgettext Java backend.
- Copyright (C) 2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-java.h b/gettext-tools/src/x-java.h
index 49f2af9..2719c42 100644
--- a/gettext-tools/src/x-java.h
+++ b/gettext-tools/src/x-java.h
@@ -1,5 +1,5 @@
/* xgettext Java backend.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Tommy Johansson <tommy.johansson@kanalen.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-javascript.c b/gettext-tools/src/x-javascript.c
index 35c9a9e..bc4d4c8 100644
--- a/gettext-tools/src/x-javascript.c
+++ b/gettext-tools/src/x-javascript.c
@@ -1,5 +1,6 @@
/* xgettext JavaScript backend.
- Copyright (C) 2002-2003, 2005-2009, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2009, 2013, 2015 Free Software
+ Foundation, Inc.
This file was written by Andreas Stricker <andy@knitter.ch>, 2010
It's based on x-python from Bruno Haible.
diff --git a/gettext-tools/src/x-javascript.h b/gettext-tools/src/x-javascript.h
index a2f6418..5d2d980 100644
--- a/gettext-tools/src/x-javascript.h
+++ b/gettext-tools/src/x-javascript.h
@@ -1,5 +1,6 @@
/* xgettext JavaScript backend.
- Copyright (C) 2002-2003, 2006, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2013, 2015 Free Software Foundation,
+ Inc.
This file was written by Andreas Stricker <andy@knitter.ch>, 2010.
It's based on x-python from Bruno Haible.
diff --git a/gettext-tools/src/x-librep.c b/gettext-tools/src/x-librep.c
index c91d22a..a515f29 100644
--- a/gettext-tools/src/x-librep.c
+++ b/gettext-tools/src/x-librep.c
@@ -1,5 +1,6 @@
/* xgettext librep backend.
- Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2001.
diff --git a/gettext-tools/src/x-librep.h b/gettext-tools/src/x-librep.h
index 5747db1..129a6c3 100644
--- a/gettext-tools/src/x-librep.h
+++ b/gettext-tools/src/x-librep.h
@@ -1,5 +1,5 @@
/* xgettext librep backend.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-lisp.c b/gettext-tools/src/x-lisp.c
index 20d88a2..0d3a1c4 100644
--- a/gettext-tools/src/x-lisp.c
+++ b/gettext-tools/src/x-lisp.c
@@ -1,5 +1,6 @@
/* xgettext Lisp backend.
- Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2001.
diff --git a/gettext-tools/src/x-lisp.h b/gettext-tools/src/x-lisp.h
index 97b593d..e9d0a0b 100644
--- a/gettext-tools/src/x-lisp.h
+++ b/gettext-tools/src/x-lisp.h
@@ -1,5 +1,5 @@
/* xgettext Lisp backend.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-lua.c b/gettext-tools/src/x-lua.c
index 9fcc20d..5050838 100644
--- a/gettext-tools/src/x-lua.c
+++ b/gettext-tools/src/x-lua.c
@@ -1,5 +1,5 @@
/* xgettext Lua backend.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2015 Free Software Foundation, Inc.
This file was written by Ľubomír Remák <lubomirr@lubomirr.eu>, 2012.
diff --git a/gettext-tools/src/x-lua.h b/gettext-tools/src/x-lua.h
index 3161638..7af3525 100644
--- a/gettext-tools/src/x-lua.h
+++ b/gettext-tools/src/x-lua.h
@@ -1,5 +1,5 @@
/* xgettext Lua backend.
- Copyright (C) 2011 Free Software Foundation, Inc.
+ Copyright (C) 2011, 2015 Free Software Foundation, Inc.
Written by Ľubomír Remák <lubomirrk@lubomirr.eu>, 2011
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-perl.c b/gettext-tools/src/x-perl.c
index 571f6de..396b7b5 100644
--- a/gettext-tools/src/x-perl.c
+++ b/gettext-tools/src/x-perl.c
@@ -1,5 +1,5 @@
/* xgettext Perl backend.
- Copyright (C) 2002-2010 Free Software Foundation, Inc.
+ Copyright (C) 2002-2010, 2015 Free Software Foundation, Inc.
This file was written by Guido Flohr <guido@imperia.net>, 2002-2010.
diff --git a/gettext-tools/src/x-perl.h b/gettext-tools/src/x-perl.h
index 8e140e9..4f7a2b3 100644
--- a/gettext-tools/src/x-perl.h
+++ b/gettext-tools/src/x-perl.h
@@ -1,5 +1,6 @@
/* xgettext Perl backend.
- Copyright (C) 2002-2003, 2006, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2010, 2015 Free Software Foundation,
+ Inc.
Written by Guido Flohr <guido@imperia.net>, 2002-2003
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-php.c b/gettext-tools/src/x-php.c
index 74b8ece..ac5cf96 100644
--- a/gettext-tools/src/x-php.c
+++ b/gettext-tools/src/x-php.c
@@ -1,5 +1,6 @@
/* xgettext PHP backend.
- Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2010, 2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <bruno@clisp.org>, 2002.
diff --git a/gettext-tools/src/x-php.h b/gettext-tools/src/x-php.h
index 79442b4..0d13fee 100644
--- a/gettext-tools/src/x-php.h
+++ b/gettext-tools/src/x-php.h
@@ -1,5 +1,5 @@
/* xgettext PHP backend.
- Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-po.c b/gettext-tools/src/x-po.c
index 89824e2..65d8cc0 100644
--- a/gettext-tools/src/x-po.c
+++ b/gettext-tools/src/x-po.c
@@ -1,5 +1,6 @@
/* xgettext PO and JavaProperties backends.
- Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2015 Free
+ Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
diff --git a/gettext-tools/src/x-po.h b/gettext-tools/src/x-po.h
index 0d350d8..e76d77b 100644
--- a/gettext-tools/src/x-po.h
+++ b/gettext-tools/src/x-po.h
@@ -1,5 +1,5 @@
/* xgettext PO backend.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-properties.h b/gettext-tools/src/x-properties.h
index fd16ab3..0935466 100644
--- a/gettext-tools/src/x-properties.h
+++ b/gettext-tools/src/x-properties.h
@@ -1,5 +1,5 @@
/* xgettext JavaProperties backend.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-python.c b/gettext-tools/src/x-python.c
index d781ef2..8122c34 100644
--- a/gettext-tools/src/x-python.c
+++ b/gettext-tools/src/x-python.c
@@ -1,5 +1,6 @@
/* xgettext Python backend.
- Copyright (C) 2002-2003, 2005-2013 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
diff --git a/gettext-tools/src/x-python.h b/gettext-tools/src/x-python.h
index f7861fb..57d379d 100644
--- a/gettext-tools/src/x-python.h
+++ b/gettext-tools/src/x-python.h
@@ -1,5 +1,5 @@
/* xgettext Python backend.
- Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-rst.c b/gettext-tools/src/x-rst.c
index 8b5a26a..f673299 100644
--- a/gettext-tools/src/x-rst.c
+++ b/gettext-tools/src/x-rst.c
@@ -1,5 +1,6 @@
/* xgettext RST backend.
- Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2001.
diff --git a/gettext-tools/src/x-rst.h b/gettext-tools/src/x-rst.h
index 6507d0d..a6ac552 100644
--- a/gettext-tools/src/x-rst.h
+++ b/gettext-tools/src/x-rst.h
@@ -1,5 +1,5 @@
/* xgettext RST backend.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-scheme.c b/gettext-tools/src/x-scheme.c
index e8cfe84..abbe0e5 100644
--- a/gettext-tools/src/x-scheme.c
+++ b/gettext-tools/src/x-scheme.c
@@ -1,5 +1,5 @@
/* xgettext Scheme backend.
- Copyright (C) 2004-2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2004-2009, 2011, 2015 Free Software Foundation, Inc.
This file was written by Bruno Haible <bruno@clisp.org>, 2004-2005.
diff --git a/gettext-tools/src/x-scheme.h b/gettext-tools/src/x-scheme.h
index a159ab1..039979f 100644
--- a/gettext-tools/src/x-scheme.h
+++ b/gettext-tools/src/x-scheme.h
@@ -1,5 +1,5 @@
/* xgettext Scheme backend.
- Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2004.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-sh.c b/gettext-tools/src/x-sh.c
index 9a0614f..3746a9a 100644
--- a/gettext-tools/src/x-sh.c
+++ b/gettext-tools/src/x-sh.c
@@ -1,5 +1,5 @@
/* xgettext sh backend.
- Copyright (C) 2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005-2009, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-sh.h b/gettext-tools/src/x-sh.h
index d235751..a31eeff 100644
--- a/gettext-tools/src/x-sh.h
+++ b/gettext-tools/src/x-sh.h
@@ -1,5 +1,5 @@
/* xgettext sh backend.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-smalltalk.c b/gettext-tools/src/x-smalltalk.c
index c3f9699..9c079cc 100644
--- a/gettext-tools/src/x-smalltalk.c
+++ b/gettext-tools/src/x-smalltalk.c
@@ -1,5 +1,6 @@
/* xgettext Smalltalk backend.
- Copyright (C) 2002-2003, 2005-2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2009, 2011, 2015 Free Software
+ Foundation, Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
diff --git a/gettext-tools/src/x-smalltalk.h b/gettext-tools/src/x-smalltalk.h
index 10767d9..9061f29 100644
--- a/gettext-tools/src/x-smalltalk.h
+++ b/gettext-tools/src/x-smalltalk.h
@@ -1,5 +1,5 @@
/* xgettext Smalltalk backend.
- Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-stringtable.h b/gettext-tools/src/x-stringtable.h
index 57df745..2c519e8 100644
--- a/gettext-tools/src/x-stringtable.h
+++ b/gettext-tools/src/x-stringtable.h
@@ -1,5 +1,5 @@
/* xgettext NXStringTable backend.
- Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-tcl.c b/gettext-tools/src/x-tcl.c
index 37dd19e..905d55c 100644
--- a/gettext-tools/src/x-tcl.c
+++ b/gettext-tools/src/x-tcl.c
@@ -1,5 +1,6 @@
/* xgettext Tcl backend.
- Copyright (C) 2002-2003, 2005-2009 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2009, 2015 Free Software Foundation,
+ Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2002.
diff --git a/gettext-tools/src/x-tcl.h b/gettext-tools/src/x-tcl.h
index 1dc5412..00f6fc5 100644
--- a/gettext-tools/src/x-tcl.h
+++ b/gettext-tools/src/x-tcl.h
@@ -1,5 +1,5 @@
/* xgettext Tcl Lisp backend.
- Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2002.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/x-vala.c b/gettext-tools/src/x-vala.c
index 4806b36..4e53b50 100644
--- a/gettext-tools/src/x-vala.c
+++ b/gettext-tools/src/x-vala.c
@@ -1,5 +1,5 @@
/* xgettext Vala backend.
- Copyright (C) 2013 Free Software Foundation, Inc.
+ Copyright (C) 2013, 2015 Free Software Foundation, Inc.
This file was written by Daiki Ueno <ueno@gnu.org>, 2013.
diff --git a/gettext-tools/src/x-vala.h b/gettext-tools/src/x-vala.h
index 9eb730b..fcd0cfb 100644
--- a/gettext-tools/src/x-vala.h
+++ b/gettext-tools/src/x-vala.h
@@ -1,5 +1,6 @@
/* xgettext Vala backend.
- Copyright (C) 2002-2003, 2006, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2006, 2013, 2015 Free Software Foundation,
+ Inc.
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
diff --git a/gettext-tools/src/x-ycp.c b/gettext-tools/src/x-ycp.c
index ff8642b..62ab94d 100644
--- a/gettext-tools/src/x-ycp.c
+++ b/gettext-tools/src/x-ycp.c
@@ -1,5 +1,6 @@
/* xgettext YCP backend.
- Copyright (C) 2001-2003, 2005-2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2009, 2011, 2015 Free Software
+ Foundation, Inc.
This file was written by Bruno Haible <haible@clisp.cons.org>, 2001.
diff --git a/gettext-tools/src/x-ycp.h b/gettext-tools/src/x-ycp.h
index 78cc853..3ecb097 100644
--- a/gettext-tools/src/x-ycp.h
+++ b/gettext-tools/src/x-ycp.h
@@ -1,5 +1,5 @@
/* xgettext YCP backend.
- Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2006, 2015 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c
index 28d28a0..314d35c 100644
--- a/gettext-tools/src/xgettext.c
+++ b/gettext-tools/src/xgettext.c
@@ -1,5 +1,6 @@
/* Extracts strings from C source file to Uniforum style .po file.
- Copyright (C) 1995-1998, 2000-2012 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2015 Free Software Foundation,
+ Inc.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
This program is free software: you can redistribute it and/or modify
@@ -28,6 +29,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
+#include <sys/stat.h>
#include <locale.h>
#include <limits.h>
@@ -58,6 +60,8 @@
#include "po-charset.h"
#include "msgl-iconv.h"
#include "msgl-ascii.h"
+#include "msgl-check.h"
+#include "po-xerror.h"
#include "po-time.h"
#include "write-catalog.h"
#include "write-po.h"
@@ -66,7 +70,10 @@
#include "color.h"
#include "format.h"
#include "propername.h"
+#include "sentence.h"
#include "unistr.h"
+#include "its.h"
+#include "locating-rule.h"
#include "gettext.h"
/* A convenience macro. I don't like writing gettext() every time. */
@@ -85,6 +92,7 @@
#include "x-java.h"
#include "x-properties.h"
#include "x-csharp.h"
+#include "x-appdata.h"
#include "x-awk.h"
#include "x-ycp.h"
#include "x-tcl.h"
@@ -100,6 +108,10 @@
#include "x-desktop.h"
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+#define ENDOF(a) ((a) + SIZEOF(a))
+
+
/* If nonzero add all comments immediately preceding one of the keywords. */
static bool add_all_comments = false;
@@ -179,6 +191,9 @@ static bool recognize_format_kde;
/* If true, recognize Boost format strings. */
static bool recognize_format_boost;
+/* Syntax checks enabled by default. */
+static enum is_syntax_check default_syntax_check[NSYNTAXCHECKS];
+
/* Canonicalized encoding name for all input files. */
const char *xgettext_global_source_encoding;
@@ -197,6 +212,17 @@ const char *xgettext_current_source_encoding;
iconv_t xgettext_current_source_iconv;
#endif
+static locating_rule_list_ty *its_locating_rules;
+
+#define ITS_ROOT_UNTRANSLATABLE \
+ "<its:rules xmlns:its=\"http://www.w3.org/2005/11/its\"" \
+ " version=\"2.0\">" \
+ " <its:translateRule selector=\"/*\" translate=\"no\"/>" \
+ "</its:rules>"
+
+/* If nonzero add comments used by itstool. */
+static bool add_itstool_comments = false;
+
/* Long options. */
static const struct option long_options[] =
{
@@ -204,6 +230,7 @@ static const struct option long_options[] =
{ "add-location", optional_argument, NULL, 'n' },
{ "boost", no_argument, NULL, CHAR_MAX + 11 },
{ "c++", no_argument, NULL, 'C' },
+ { "check", required_argument, NULL, CHAR_MAX + 17 },
{ "color", optional_argument, NULL, CHAR_MAX + 14 },
{ "copyright-holder", required_argument, NULL, CHAR_MAX + 1 },
{ "debug", no_argument, &do_debug, 1 },
@@ -219,6 +246,8 @@ static const struct option long_options[] =
{ "from-code", required_argument, NULL, CHAR_MAX + 3 },
{ "help", no_argument, NULL, 'h' },
{ "indent", no_argument, NULL, 'i' },
+ { "its", required_argument, NULL, CHAR_MAX + 20 },
+ { "itstool", no_argument, NULL, CHAR_MAX + 19 },
{ "join-existing", no_argument, NULL, 'j' },
{ "kde", no_argument, NULL, CHAR_MAX + 10 },
{ "keyword", optional_argument, NULL, 'k' },
@@ -236,6 +265,7 @@ static const struct option long_options[] =
{ "package-version", required_argument, NULL, CHAR_MAX + 13 },
{ "properties-output", no_argument, NULL, CHAR_MAX + 6 },
{ "qt", no_argument, NULL, CHAR_MAX + 9 },
+ { "sentence-end", required_argument, NULL, CHAR_MAX + 18 },
{ "sort-by-file", no_argument, NULL, 'F' },
{ "sort-output", no_argument, NULL, 's' },
{ "strict", no_argument, NULL, 'S' },
@@ -278,6 +308,9 @@ static void usage (int status)
static void read_exclusion_file (char *file_name);
static void extract_from_file (const char *file_name, extractor_ty extractor,
msgdomain_list_ty *mdlp);
+static void extract_from_xml_file (const char *file_name,
+ its_rule_list_ty *rules,
+ msgdomain_list_ty *mdlp);
static message_ty *construct_header (void);
static void finalize_header (msgdomain_list_ty *mdlp);
static extractor_ty language_to_extractor (const char *name);
@@ -296,6 +329,8 @@ main (int argc, char *argv[])
bool some_additional_keywords = false;
bool sort_by_msgid = false;
bool sort_by_filepos = false;
+ char *its_dirs[2] = { NULL, NULL };
+ char *explicit_its_filename = NULL;
const char *file_name;
const char *files_from = NULL;
string_list_ty *file_list;
@@ -328,6 +363,7 @@ main (int argc, char *argv[])
init_flag_table_c ();
init_flag_table_objc ();
init_flag_table_gcc_internal ();
+ init_flag_table_kde ();
init_flag_table_sh ();
init_flag_table_python ();
init_flag_table_lisp ();
@@ -346,7 +382,7 @@ main (int argc, char *argv[])
init_flag_table_vala ();
while ((optchar = getopt_long (argc, argv,
- "ac::Cd:D:eEf:Fhijk::l:L:m::M::no:p:sTVw:x:",
+ "ac::Cd:D:eEf:Fhijk::l:L:m::M::no:p:sTVw:W:x:",
long_options, NULL)) != EOF)
switch (optchar)
{
@@ -367,7 +403,6 @@ main (int argc, char *argv[])
x_tcl_extract_all ();
x_perl_extract_all ();
x_php_extract_all ();
- x_glade_extract_all ();
x_lua_extract_all ();
x_javascript_extract_all ();
x_vala_extract_all ();
@@ -447,7 +482,6 @@ main (int argc, char *argv[])
x_tcl_keyword (optarg);
x_perl_keyword (optarg);
x_php_keyword (optarg);
- x_glade_keyword (optarg);
x_lua_keyword (optarg);
x_javascript_keyword (optarg);
x_vala_keyword (optarg);
@@ -575,6 +609,7 @@ main (int argc, char *argv[])
case CHAR_MAX + 10: /* --kde */
recognize_format_kde = true;
+ activate_additional_keywords_kde ();
break;
case CHAR_MAX + 11: /* --boost */
@@ -602,6 +637,34 @@ main (int argc, char *argv[])
message_print_style_filepos (filepos_comment_none);
break;
+ case CHAR_MAX + 17: /* --check */
+ if (strcmp (optarg, "ellipsis-unicode") == 0)
+ default_syntax_check[sc_ellipsis_unicode] = yes;
+ else if (strcmp (optarg, "space-ellipsis") == 0)
+ default_syntax_check[sc_space_ellipsis] = yes;
+ else if (strcmp (optarg, "quote-unicode") == 0)
+ default_syntax_check[sc_quote_unicode] = yes;
+ else
+ error (EXIT_FAILURE, 0, _("syntax check '%s' unknown"), optarg);
+ break;
+
+ case CHAR_MAX + 18: /* --sentence-end */
+ if (strcmp (optarg, "single-space") == 0)
+ sentence_end_required_spaces = 1;
+ else if (strcmp (optarg, "double-space") == 0)
+ sentence_end_required_spaces = 2;
+ else
+ error (EXIT_FAILURE, 0, _("sentence end type '%s' unknown"), optarg);
+ break;
+
+ case CHAR_MAX + 20: /* --its */
+ explicit_its_filename = optarg;
+ break;
+
+ case CHAR_MAX + 19: /* --itstool */
+ add_itstool_comments = true;
+ break;
+
default:
usage (EXIT_FAILURE);
/* NOTREACHED */
@@ -662,6 +725,36 @@ xgettext cannot work without keywords to look for"));
usage (EXIT_FAILURE);
}
+ {
+ const char *gettextdatadir;
+ char *versioned_gettextdatadir;
+
+ /* Make it possible to override the locator file location. This
+ is necessary for running the testsuite before "make
+ install". */
+ gettextdatadir = getenv ("GETTEXTDATADIR");
+ if (gettextdatadir == NULL || gettextdatadir[0] == '\0')
+ gettextdatadir = relocate (GETTEXTDATADIR);
+
+ its_dirs[0] = xconcatenated_filename (gettextdatadir, "its", NULL);
+
+ versioned_gettextdatadir =
+ xasprintf ("%s%s", relocate (GETTEXTDATADIR), PACKAGE_SUFFIX);
+ its_dirs[1] = xconcatenated_filename (versioned_gettextdatadir, "its",
+ NULL);
+ free (versioned_gettextdatadir);
+
+ its_locating_rules = locating_rule_list_alloc ();
+ for (i = 0; i < SIZEOF (its_dirs); i++)
+ locating_rule_list_add_from_directory (its_locating_rules, its_dirs[i]);
+ }
+
+ /* Explicit ITS file selection and language specification are
+ mutually exclusive. */
+ if (explicit_its_filename != NULL && language != NULL)
+ error (EXIT_FAILURE, 0, _("%s and %s are mutually exclusive"),
+ "--its", "--language");
+
/* Determine extractor from language. */
if (language != NULL)
extractor = language_to_extractor (language);
@@ -760,18 +853,27 @@ This version was built without iconv()."),
{
const char *filename;
extractor_ty this_file_extractor;
+ its_rule_list_ty *its_rules = NULL;
filename = file_list->item[i];
if (extractor.func)
this_file_extractor = extractor;
+ else if (explicit_its_filename != NULL)
+ {
+ its_rules = its_rule_list_alloc ();
+ if (!its_rule_list_add_from_file (its_rules,
+ explicit_its_filename))
+ {
+ error (EXIT_FAILURE, 0, _("\
+warning: ITS rule file '%s' does not exist"), explicit_its_filename);
+ }
+ }
else
{
+ const char *language_from_extension = NULL;
const char *base;
char *reduced;
- const char *extension;
- const char *language;
- const char *p;
base = strrchr (filename, '/');
if (!base)
@@ -783,39 +885,106 @@ This version was built without iconv()."),
&& memcmp (reduced + strlen (reduced) - 3, ".in", 3) == 0)
reduced[strlen (reduced) - 3] = '\0';
- /* Work out what the file extension is. */
- language = NULL;
- p = reduced + strlen (reduced);
- for (; p > reduced && language == NULL; p--)
+ /* If no language is specified with -L, deduce it the extension. */
+ if (language == NULL)
{
- if (*p == '.')
+ const char *p;
+
+ /* Work out what the file extension is. */
+ p = reduced + strlen (reduced);
+ for (; p > reduced && language_from_extension == NULL; p--)
{
- extension = p + 1;
+ if (*p == '.')
+ {
+ const char *extension = p + 1;
- /* Derive the language from the extension, and the extractor
- function from the language. */
- language = extension_to_language (extension);
+ /* Derive the language from the extension, and
+ the extractor function from the language. */
+ language_from_extension =
+ extension_to_language (extension);
+ }
}
}
- if (language == NULL)
+ /* If language is not determined from the file name
+ extension, check ITS locating rules. */
+ if (language_from_extension == NULL
+ && strcmp (filename, "-") != 0)
{
- extension = strrchr (reduced, '.');
- if (extension == NULL)
- extension = "";
- else
- extension++;
- error (0, 0, _("\
+ const char *its_basename;
+
+ its_basename = locating_rule_list_locate (its_locating_rules,
+ filename,
+ language);
+
+ if (its_basename != NULL)
+ {
+ size_t j;
+
+ its_rules = its_rule_list_alloc ();
+
+ /* If the ITS file is identified by the name,
+ set the root element untranslatable. */
+ if (language != NULL)
+ its_rule_list_add_from_string (its_rules,
+ ITS_ROOT_UNTRANSLATABLE);
+
+ for (j = 0; j < SIZEOF (its_dirs); j++)
+ {
+ char *its_filename =
+ xconcatenated_filename (its_dirs[j], its_basename,
+ NULL);
+ struct stat statbuf;
+ bool ok = false;
+
+ if (stat (its_filename, &statbuf) == 0)
+ ok = its_rule_list_add_from_file (its_rules,
+ its_filename);
+ free (its_filename);
+ if (ok)
+ break;
+ }
+ if (j == SIZEOF (its_dirs))
+ {
+ error (0, 0, _("\
+warning: ITS rule file '%s' does not exist; check your gettext installation"),
+ its_basename);
+ its_rule_list_free (its_rules);
+ its_rules = NULL;
+ }
+ }
+ }
+
+ if (its_rules == NULL)
+ {
+ if (language_from_extension == NULL)
+ {
+ const char *extension = strrchr (reduced, '.');
+ if (extension == NULL)
+ extension = "";
+ else
+ extension++;
+ error (0, 0, _("\
warning: file '%s' extension '%s' is unknown; will try C"), filename, extension);
- language = "C";
+ language_from_extension = "C";
+ }
+
+ this_file_extractor =
+ language_to_extractor (language_from_extension);
}
- this_file_extractor = language_to_extractor (language);
free (reduced);
}
- /* Extract the strings from the file. */
- extract_from_file (filename, this_file_extractor, mdlp);
+ if (its_rules != NULL)
+ {
+ /* Extract the strings from the file, using ITS. */
+ extract_from_xml_file (filename, its_rules, mdlp);
+ its_rule_list_free (its_rules);
+ }
+ else
+ /* Extract the strings from the file. */
+ extract_from_file (filename, this_file_extractor, mdlp);
}
string_list_free (file_list);
@@ -836,9 +1005,33 @@ warning: file '%s' extension '%s' is unknown; will try C"), filename, extension)
else if (sort_by_msgid)
msgdomain_list_sort_by_msgid (mdlp);
+ /* Check syntax of messages. */
+ {
+ int nerrors = 0;
+
+ for (i = 0; i < mdlp->nitems; i++)
+ {
+ message_list_ty *mlp = mdlp->item[i]->messages;
+ nerrors = syntax_check_message_list (mlp);
+ }
+
+ /* Exit with status 1 on any error. */
+ if (nerrors > 0)
+ error (EXIT_FAILURE, 0,
+ ngettext ("found %d fatal error", "found %d fatal errors",
+ nerrors),
+ nerrors);
+ }
+
/* Write the PO file. */
msgdomain_list_print (mdlp, file_name, output_syntax, force_po, do_debug);
+ if (its_locating_rules)
+ locating_rule_list_free (its_locating_rules);
+
+ for (i = 0; i < SIZEOF (its_dirs); i++)
+ free (its_dirs[i]);
+
exit (EXIT_SUCCESS);
}
@@ -921,6 +1114,14 @@ Operation mode:\n"));
preceding keyword lines in output file\n\
-c, --add-comments place all comment blocks preceding keyword lines\n\
in output file\n"));
+ printf (_("\
+ --check=NAME perform syntax check on messages\n\
+ (ellipsis-unicode, space-ellipsis,\n\
+ quote-unicode)\n"));
+ printf (_("\
+ --sentence-end=TYPE type describing the end of sentence\n\
+ (single-space, which is the default, \n\
+ or double-space)\n"));
printf ("\n");
printf (_("\
Language specific options:\n"));
@@ -993,6 +1194,10 @@ Output details:\n"));
printf (_("\
--stringtable-output write out a NeXTstep/GNUstep .strings file\n"));
printf (_("\
+ --its=FILE apply ITS rules from FILE\n"));
+ printf (_("\
+ --itstool write out itstool comments\n"));
+ printf (_("\
-w, --width=NUMBER set output page width\n"));
printf (_("\
--no-wrap do not break long message lines, longer than\n\
@@ -1644,8 +1849,8 @@ xgettext_record_flag (const char *optionstring)
flag += 5;
}
- /* Unlike po_parse_comment_special(), we don't accept "fuzzy" or "wrap"
- here - it has no sense. */
+ /* 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)
{
@@ -1810,6 +2015,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,
@@ -2049,6 +2259,65 @@ extract_from_file (const char *file_name, extractor_ty extractor,
free (real_file_name);
}
+static message_ty *
+xgettext_its_extract_callback (message_list_ty *mlp,
+ const char *msgctxt,
+ const char *msgid,
+ lex_pos_ty *pos,
+ const char *extracted_comment,
+ const char *marker,
+ enum its_whitespace_type_ty whitespace)
+{
+ message_ty *message;
+
+ message = remember_a_message (mlp,
+ msgctxt == NULL ? NULL : xstrdup (msgctxt),
+ xstrdup (msgid),
+ null_context, pos,
+ extracted_comment, NULL);
+
+ if (add_itstool_comments)
+ {
+ char *dot = xasprintf ("(itstool) path: %s", marker);
+ message_comment_dot_append (message, dot);
+ free (dot);
+
+ if (whitespace == ITS_WHITESPACE_PRESERVE)
+ message->do_wrap = no;
+ }
+
+ return message;
+}
+
+static void
+extract_from_xml_file (const char *file_name,
+ its_rule_list_ty *rules,
+ msgdomain_list_ty *mdlp)
+{
+ char *logical_file_name;
+ char *real_file_name;
+ FILE *fp = xgettext_open (file_name, &logical_file_name, &real_file_name);
+
+ /* The default encoding for XML is UTF-8. It can be overridden by
+ an XML declaration in the XML file itself, not through the
+ --from-code option. */
+ xgettext_current_source_encoding = po_charset_utf8;
+
+#if HAVE_ICONV
+ xgettext_current_source_iconv = xgettext_global_source_iconv;
+#endif
+
+ its_rule_list_extract (rules, fp, real_file_name, logical_file_name,
+ NULL,
+ mdlp,
+ xgettext_its_extract_callback);
+
+ if (fp != stdin)
+ fclose (fp);
+ free (logical_file_name);
+ free (real_file_name);
+}
+
/* Error message about non-ASCII character in a specific lexical context. */
@@ -2238,6 +2507,7 @@ remember_a_message (message_list_ty *mlp, char *msgctxt, char *msgid,
enum is_format is_format[NFORMATS];
struct argument_range range;
enum is_wrap do_wrap;
+ enum is_syntax_check do_syntax_check[NSYNTAXCHECKS];
message_ty *mp;
char *msgstr;
size_t i;
@@ -2264,6 +2534,8 @@ remember_a_message (message_list_ty *mlp, char *msgctxt, char *msgid,
range.min = -1;
range.max = -1;
do_wrap = undecided;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ do_syntax_check[i] = undecided;
if (msgctxt != NULL)
CONVERT_STRING (msgctxt, lc_string);
@@ -2297,6 +2569,8 @@ meta information, not the empty string.\n")));
for (i = 0; i < NFORMATS; i++)
is_format[i] = mp->is_format[i];
do_wrap = mp->do_wrap;
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ do_syntax_check[i] = mp->do_syntax_check[i];
}
else
{
@@ -2327,7 +2601,7 @@ meta information, not the empty string.\n")));
/* The string before the comment tag. For example, If "** TRANSLATORS:"
is seen and the comment tag is "TRANSLATORS:",
then comment_tag_prefix is set to "** ". */
- const char *comment_tag_prefix = NULL;
+ const char *comment_tag_prefix = "";
size_t comment_tag_prefix_length = 0;
nitems_before = (mp->comment_dot != NULL ? mp->comment_dot->nitems : 0);
@@ -2376,12 +2650,13 @@ meta information, not the empty string.\n")));
enum is_format tmp_format[NFORMATS];
struct argument_range tmp_range;
enum is_wrap tmp_wrap;
+ enum is_syntax_check tmp_syntax_check[NSYNTAXCHECKS];
bool interesting;
t += strlen ("xgettext:");
po_parse_comment_special (t, &tmp_fuzzy, tmp_format, &tmp_range,
- &tmp_wrap);
+ &tmp_wrap, tmp_syntax_check);
interesting = false;
for (i = 0; i < NFORMATS; i++)
@@ -2400,6 +2675,12 @@ meta information, not the empty string.\n")));
do_wrap = tmp_wrap;
interesting = true;
}
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ if (tmp_syntax_check[i] != undecided)
+ {
+ do_syntax_check[i] = tmp_syntax_check[i];
+ interesting = true;
+ }
/* If the "xgettext:" marker was followed by an interesting
keyword, and we updated our is_format/do_wrap variables,
@@ -2477,7 +2758,19 @@ 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 kde-format when it's known to
+ be a kde-kuit-format string. */
+ && !(i == format_kde
+ && possible_format_p (is_format[format_kde_kuit]))
+ /* Avoid flagging a string as kde-kuit-format when it's
+ known to be a kde-format string. Note that this relies
+ on the fact that format_kde < format_kde_kuit, so a
+ string will be marked as kde-format if both are
+ undecided. */
+ && !(i == format_kde_kuit
+ && possible_format_p (is_format[format_kde])))
{
struct formatstring_parser *parser = formatstring_parsers[i];
char *invalid_reason = NULL;
@@ -2525,6 +2818,14 @@ meta information, not the empty string.\n")));
mp->do_wrap = do_wrap == no ? no : yes; /* By default we wrap. */
+ for (i = 0; i < NSYNTAXCHECKS; i++)
+ {
+ if (do_syntax_check[i] == undecided)
+ do_syntax_check[i] = default_syntax_check[i] == yes ? yes : no;
+
+ mp->do_syntax_check[i] = do_syntax_check[i];
+ }
+
/* Warn about the use of non-reorderable format strings when the programming
language also provides reorderable format strings. */
warn_format_string (is_format, mp->msgid, pos, "msgid");
@@ -2604,7 +2905,19 @@ 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 kde-format when it's known
+ to be a kde-kuit-format string. */
+ && !(i == format_kde
+ && possible_format_p (mp->is_format[format_kde_kuit]))
+ /* Avoid flagging a string as kde-kuit-format when it's
+ known to be a kde-format string. Note that this relies
+ on the fact that format_kde < format_kde_kuit, so a
+ string will be marked as kde-format if both are
+ undecided. */
+ && !(i == format_kde_kuit
+ && possible_format_p (mp->is_format[format_kde])))
{
struct formatstring_parser *parser = formatstring_parsers[i];
char *invalid_reason = NULL;
@@ -3457,9 +3770,10 @@ Content-Transfer-Encoding: 8bit\n",
comment = xasprintf ("\
SOME DESCRIPTIVE TITLE.\n\
Copyright (C) YEAR %s\n\
-This file is distributed under the same license as the PACKAGE package.\n\
+This file is distributed under the same license as the %s package.\n\
FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n",
- copyright_holder);
+ copyright_holder,
+ package_name != NULL ? package_name : "PACKAGE");
else
comment = xstrdup ("\
SOME DESCRIPTIVE TITLE.\n\
@@ -3555,10 +3869,6 @@ finalize_header (msgdomain_list_ty *mdlp)
}
-#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
-#define ENDOF(a) ((a) + SIZEOF(a))
-
-
static extractor_ty
language_to_extractor (const char *name)
{
@@ -3600,6 +3910,7 @@ language_to_extractor (const char *name)
SCANNERS_VALA
SCANNERS_GSETTINGS
SCANNERS_DESKTOP
+ SCANNERS_APPDATA
/* Here may follow more languages and their scanners: pike, etc...
Make sure new scanners honor the --exclude-file option. */
};
@@ -3632,6 +3943,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)
@@ -3689,6 +4001,7 @@ extension_to_language (const char *extension)
EXTENSIONS_VALA
EXTENSIONS_GSETTINGS
EXTENSIONS_DESKTOP
+ EXTENSIONS_APPDATA
/* Here may follow more file extensions... */
};
diff --git a/gettext-tools/src/xgettext.h b/gettext-tools/src/xgettext.h
index c852ae3..167fcd3 100644
--- a/gettext-tools/src/xgettext.h
+++ b/gettext-tools/src/xgettext.h
@@ -1,5 +1,6 @@
/* xgettext common functions.
- Copyright (C) 2001-2003, 2005-2006, 2008-2009, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2006, 2008-2009, 2011, 2015 Free
+ Software Foundation, Inc.
Written by Peter Miller <millerp@canb.auug.org.au>
and Bruno Haible <haible@clisp.cons.org>, 2001.