From e26b846fe273243b446cc02a027cc1a715734d1f Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 16 May 2016 17:08:09 +0900 Subject: msgfmt, xgettext: Respect XDG_DATA_DIRS Suggested in https://savannah.gnu.org/bugs/?47123 * autogen.sh (GNULIB_MODULES_TOOLS_FOR_SRC): Add 'xmemdup0'. * gettext-tools/gnulib-lib/.gitignore: Ignore files brought by gnulib-tool. * gettext-tools/gnulib-tests/.gitignore: Likewise. * gettext-tools/src/search-path.c: New file. * gettext-tools/src/search-path.h: New file. * gettext-tools/src/Makefile.am (noinst_HEADERS): Add search-path.h. (libgettextsrc_la_SOURCES): Add search-path.c. * gettext-tools/src/msgfmt.c: Include "search-path.h". (main): Use get_search_path to locate ITS directories. * gettext-tools/src/xgettext.c: Include "search-path.h". (main): Use get_search_path to locate ITS directories. --- autogen.sh | 3 +- gettext-tools/gnulib-lib/.gitignore | 2 + gettext-tools/gnulib-tests/.gitignore | 1 + gettext-tools/src/Makefile.am | 4 +- gettext-tools/src/msgfmt.c | 47 ++++++------- gettext-tools/src/search-path.c | 126 ++++++++++++++++++++++++++++++++++ gettext-tools/src/search-path.h | 37 ++++++++++ gettext-tools/src/xgettext.c | 54 +++++++-------- 8 files changed, 220 insertions(+), 54 deletions(-) create mode 100644 gettext-tools/src/search-path.c create mode 100644 gettext-tools/src/search-path.h diff --git a/autogen.sh b/autogen.sh index 61a1ee5..6790a23 100755 --- a/autogen.sh +++ b/autogen.sh @@ -261,8 +261,9 @@ if ! $skip_gnulib; then write xalloc xconcat-filename - xmalloca xerror + xmalloca + xmemdup0 xsetenv xstriconv xstriconveh diff --git a/gettext-tools/gnulib-lib/.gitignore b/gettext-tools/gnulib-lib/.gitignore index 2a7078a..9ef54ac 100644 --- a/gettext-tools/gnulib-lib/.gitignore +++ b/gettext-tools/gnulib-lib/.gitignore @@ -416,6 +416,8 @@ /xmalloc.c /xmalloca.c /xmalloca.h +/xmemdup0.c +/xmemdup0.h /xreadlink.c /xreadlink.h /xsetenv.c diff --git a/gettext-tools/gnulib-tests/.gitignore b/gettext-tools/gnulib-tests/.gitignore index bc2c1c2..aa7ad59 100644 --- a/gettext-tools/gnulib-tests/.gitignore +++ b/gettext-tools/gnulib-tests/.gitignore @@ -308,6 +308,7 @@ /test-write.c /test-xalloc-die.c /test-xalloc-die.sh +/test-xmemdup0.c /test-xvasprintf.c /wcrtomb.c /wctob.c diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am index e847021..0538d1e 100644 --- a/gettext-tools/src/Makefile.am +++ b/gettext-tools/src/Makefile.am @@ -39,7 +39,7 @@ 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 cldr-plural.h \ -cldr-plural-exp.h locating-rule.h its.h \ +cldr-plural-exp.h locating-rule.h its.h search-path.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 \ @@ -153,7 +153,7 @@ msgl-ascii.c msgl-iconv.c msgl-equal.c msgl-cat.c msgl-header.c msgl-english.c \ msgl-check.c file-list.c msgl-charset.c po-time.c plural-exp.c plural-eval.c \ plural-table.c quote.h sentence.h sentence.c \ $(FORMAT_SOURCE) \ -read-desktop.c locating-rule.c its.c +read-desktop.c locating-rule.c its.c search-path.c # msggrep needs pattern matching. LIBGREP = ../libgrep/libgrep.a diff --git a/gettext-tools/src/msgfmt.c b/gettext-tools/src/msgfmt.c index 7055fa0..ff4084b 100644 --- a/gettext-tools/src/msgfmt.c +++ b/gettext-tools/src/msgfmt.c @@ -65,6 +65,7 @@ #include "concat-filename.h" #include "its.h" #include "locating-rule.h" +#include "search-path.h" #include "gettext.h" #define _(str) gettext (str) @@ -664,31 +665,27 @@ There is NO WARRANTY, to the extent permitted by law.\n\ if (xml_mode) { - const char *gettextdatadir; - char *versioned_gettextdatadir; - char *its_dirs[2] = { NULL, NULL }; + char **its_dirs; + char **dirs; 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_dirs = get_search_path ("its"); 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]); + for (dirs = its_dirs; *dirs != NULL; dirs++) + { + /* Make it possible to override the locator file location. This + is necessary for running the testsuite before "make + install". */ + char *relocated = relocate (*dirs); + if (relocated != *dirs) + { + free (*dirs); + *dirs = relocated; + } + + locating_rule_list_add_from_directory (its_locating_rules, *dirs); + } its_basename = locating_rule_list_locate (its_locating_rules, xml_template_name, @@ -699,7 +696,7 @@ There is NO WARRANTY, to the extent permitted by law.\n\ size_t j; xml_its_rules = its_rule_list_alloc (); - for (j = 0; j < SIZEOF (its_dirs); j++) + for (j = 0; its_dirs[j] != NULL; j++) { char *its_filename = xconcatenated_filename (its_dirs[j], its_basename, NULL); @@ -712,7 +709,7 @@ There is NO WARRANTY, to the extent permitted by law.\n\ if (ok) break; } - if (j == SIZEOF (its_dirs)) + if (its_dirs[j] == NULL) { its_rule_list_free (xml_its_rules); xml_its_rules = NULL; @@ -720,6 +717,10 @@ There is NO WARRANTY, to the extent permitted by law.\n\ } locating_rule_list_free (its_locating_rules); + for (dirs = its_dirs; *dirs != NULL; dirs++) + free (*dirs); + free (its_dirs); + if (xml_its_rules == NULL) error (EXIT_FAILURE, 0, _("cannot locate ITS rules for %s"), xml_template_name); diff --git a/gettext-tools/src/search-path.c b/gettext-tools/src/search-path.c new file mode 100644 index 0000000..fdb61cb --- /dev/null +++ b/gettext-tools/src/search-path.c @@ -0,0 +1,126 @@ +/* Routines for locating data files + Copyright (C) 2016 Free Software Foundation, Inc. + + This file was written by Daiki Ueno , 2016. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "search-path.h" + +#include +#include + +#include "concat-filename.h" +#include "xalloc.h" +#include "xmemdup0.h" +#include "xvasprintf.h" + +/* Find the standard search path for data files. Returns a NULL + terminated list of strings. */ +char ** +get_search_path (const char *name) +{ + char **result; + const char *gettextdatadir; + const char *gettextdatadirs; + char *base, *dir; + size_t n_dirs = 2; + + gettextdatadirs = getenv ("GETTEXTDATADIRS"); + + /* If GETTEXTDATADIRS is not set, fallback to XDG_DATA_DIRS. */ + if (gettextdatadirs == NULL || *gettextdatadirs == '\0') + gettextdatadirs = getenv ("XDG_DATA_DIRS"); + + if (gettextdatadirs != NULL) + { + const char *start = gettextdatadirs; + + /* Count the number of valid elements in GETTEXTDATADIRS. */ + while (*start != '\0') + { + char *end = strchrnul (start, ':'); + + /* Skip empty element. */ + if (start != end) + n_dirs++; + + if (*end == '\0') + break; + + start = end + 1; + } + } + + result = XCALLOC (n_dirs + 1, char *); + + n_dirs = 0; + + gettextdatadir = getenv ("GETTEXTDATADIR"); + if (gettextdatadir == NULL || gettextdatadir[0] == '\0') + gettextdatadir = GETTEXTDATADIR; + + if (name == NULL) + dir = xstrdup (gettextdatadir); + else + dir = xconcatenated_filename (gettextdatadir, name, NULL); + result[n_dirs++] = dir; + + if (gettextdatadirs != NULL) + { + const char *start = gettextdatadirs; + + /* Count the number of valid elements in GETTEXTDATADIRS. */ + while (*start != '\0') + { + char *end = strchrnul (start, ':'); + + /* Skip empty element. */ + if (start != end) + { + base = xmemdup0 (start, end - start); + if (name == NULL) + dir = base; + else + { + dir = xconcatenated_filename (base, name, NULL); + free (base); + } + result[n_dirs++] = dir; + } + + if (*end == '\0') + break; + + start = end + 1; + } + } + + base = xasprintf ("%s%s", gettextdatadir, PACKAGE_SUFFIX); + if (name == NULL) + dir = base; + else + { + dir = xconcatenated_filename (base, name, NULL); + free (base); + } + result[n_dirs++] = dir; + + return result; +} diff --git a/gettext-tools/src/search-path.h b/gettext-tools/src/search-path.h new file mode 100644 index 0000000..fc11d0c --- /dev/null +++ b/gettext-tools/src/search-path.h @@ -0,0 +1,37 @@ +/* Routines for locating data files + Copyright (C) 2016 Free Software Foundation, Inc. + + This file was written by Daiki Ueno , 2016. + + 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 . */ + +#ifndef _SEARCH_PATH_H +#define _SEARCH_PATH_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Find the standard search path for data files. Returns a NULL + terminated list of strings. If NAME is not NULL, append it to each + directory. Note that it does not resolve relocated pathnames. */ +extern char **get_search_path (const char *name); + + +#ifdef __cplusplus +} +#endif + +#endif /* _SEARCH_PATH_H */ diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index c431897..f67ec21 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -73,6 +73,7 @@ #include "unistr.h" #include "its.h" #include "locating-rule.h" +#include "search-path.h" #include "gettext.h" /* A convenience macro. I don't like writing gettext() every time. */ @@ -328,7 +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 **dirs; + char **its_dirs; char *explicit_its_filename = NULL; const char *file_name; const char *files_from = NULL; @@ -726,36 +728,31 @@ 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"); + if (explicit_its_filename == NULL) + { + its_dirs = get_search_path ("its"); + its_locating_rules = locating_rule_list_alloc (); + for (dirs = its_dirs; *dirs != NULL; dirs++) + { + /* Make it possible to override the locator file location. This + is necessary for running the testsuite before "make + install". */ + char *relocated = relocate (*dirs); + if (relocated != *dirs) + { + free (*dirs); + *dirs = relocated; + } + locating_rule_list_add_from_directory (its_locating_rules, *dirs); + } + } + /* Determine extractor from language. */ if (language != NULL) extractor = language_to_extractor (language); @@ -930,7 +927,7 @@ warning: ITS rule file '%s' does not exist"), explicit_its_filename); its_rule_list_add_from_string (its_rules, ITS_ROOT_UNTRANSLATABLE); - for (j = 0; j < SIZEOF (its_dirs); j++) + for (j = 0; its_dirs[j] != NULL; j++) { char *its_filename = xconcatenated_filename (its_dirs[j], its_basename, @@ -945,7 +942,7 @@ warning: ITS rule file '%s' does not exist"), explicit_its_filename); if (ok) break; } - if (j == SIZEOF (its_dirs)) + if (its_dirs[j] == NULL) { error (0, 0, _("\ warning: ITS rule file '%s' does not exist; check your gettext installation"), @@ -1030,8 +1027,9 @@ warning: file '%s' extension '%s' is unknown; will try C"), filename, extension) if (its_locating_rules) locating_rule_list_free (its_locating_rules); - for (i = 0; i < SIZEOF (its_dirs); i++) + for (i = 0; its_dirs[i] != NULL; i++) free (its_dirs[i]); + free (its_dirs); exit (EXIT_SUCCESS); } -- cgit v1.1