From: Daiki Ueno Date: Tue, 29 Sep 2015 04:56:42 +0000 (+0900) Subject: locating-rule: Rewrite from xlocator X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=88df2629e5d0486e1cee5ae324a7b021f72cafa1;p=thirdparty%2Fgettext.git locating-rule: Rewrite from xlocator --- diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am index b4e6ff745..ebbc26fe2 100644 --- a/gettext-tools/src/Makefile.am +++ b/gettext-tools/src/Makefile.am @@ -40,7 +40,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 xlocator.h its.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 \ @@ -183,7 +183,7 @@ xgettext_SOURCES += \ x-c.c x-po.c x-sh.c x-python.c x-lisp.c x-elisp.c x-librep.c x-scheme.c \ x-smalltalk.c x-java.c x-csharp.c x-awk.c x-ycp.c x-tcl.c x-perl.c x-php.c \ x-rst.c x-glade.c x-lua.c x-javascript.c x-vala.c x-gsettings.c \ - x-desktop.c x-appdata.c xlocator.c its.c + x-desktop.c x-appdata.c locating-rule.c its.c if !WOE32DLL msgattrib_SOURCES = msgattrib.c else diff --git a/gettext-tools/src/locating-rule.c b/gettext-tools/src/locating-rule.c new file mode 100644 index 000000000..a487814ef --- /dev/null +++ b/gettext-tools/src/locating-rule.c @@ -0,0 +1,378 @@ +/* XML resource locating rules + Copyright (C) 2015 Free Software Foundation, Inc. + + This file was written by Daiki Ueno , 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 . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "locating-rule.h" + +#include "basename.h" +#include "concat-filename.h" + +#if HAVE_DIRENT_H +# include +#endif + +#if HAVE_DIRENT_H +# define HAVE_DIR 1 +#else +# define HAVE_DIR 0 +#endif + +#include +#include "error.h" +#include +#include "gettext.h" +#include "hash.h" +#include +#include +#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; + + struct document_locating_rule_list_ty doc_rules; + char *target; +}; + +struct locating_rule_list_ty +{ + char *base; + + 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) +{ + if (fnmatch (rule->pattern, filename, FNM_PATHNAME) != 0) + return NULL; + + if (rule->target != NULL) + return rule->target; + + if (rule->doc_rules.nitems > 0) + { + xmlDoc *doc; + size_t i; + + doc = xmlReadFile (filename, "utf-8", + XML_PARSE_NONET + | XML_PARSE_NOWARNING + | XML_PARSE_NOBLANKS + | XML_PARSE_NOERROR); + if (doc == NULL) + return NULL; + + for (i = 0; i < rule->doc_rules.nitems; i++) + { + const char *target = + document_locating_rule_match (&rule->doc_rules.items[i], doc); + if (target) + return target; + } + } + + return NULL; +} + +char * +locating_rule_list_locate (struct locating_rule_list_ty *rules, + const char *path) +{ + const char *target = NULL; + size_t i; + + for (i = 0; i < rules->nitems; i++) + { + target = locating_rule_match (&rules->items[i], path); + if (target != NULL) + return xconcatenated_filename (rules->base, target, NULL); + } + + return NULL; +} + +static void +missing_attribute (const char *element, const char *attribute) +{ + error (0, 0, _("\"%s\" node does not have \"%s\""), element, 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 ("documentRule", "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->pattern); + free (rule->target); +} + +static bool +locating_rule_list_add_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 ("locatingRule", "pattern"); + xmlFreeDoc (doc); + continue; + } + + memset (&rule, 0, sizeof (struct locating_rule_ty)); + rule.pattern = get_attribute (node, "pattern"); + 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; +} + +static bool +locating_rule_list_add_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_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 (const char *base, const char *directory) +{ + struct locating_rule_list_ty *result; + + xmlCheckVersion (LIBXML_VERSION); + + result = XCALLOC (1, struct locating_rule_list_ty); + result->base = xstrdup (base); + + locating_rule_list_add_directory (result, directory); + + return result; +} + +void +locating_rule_list_destroy (struct locating_rule_list_ty *rules) +{ + free (rules->base); + + 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/xlocator.h b/gettext-tools/src/locating-rule.h similarity index 63% rename from gettext-tools/src/xlocator.h rename to gettext-tools/src/locating-rule.h index 3ef85d068..91785f8e9 100644 --- a/gettext-tools/src/xlocator.h +++ b/gettext-tools/src/locating-rule.h @@ -1,4 +1,4 @@ -/* XML resource locator +/* XML resource locating rules Copyright (C) 2015 Free Software Foundation, Inc. This file was written by Daiki Ueno , 2015. @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef _XLOCATOR_H -#define _XLOCATOR_H +#ifndef _LOCATING_RULE_H +#define _LOCATING_RULE_H #include @@ -25,25 +25,23 @@ extern "C" { #endif -typedef struct xlocator_list_ty xlocator_list_ty; +typedef struct locating_rule_list_ty locating_rule_list_ty; -/* Creates a fresh xlocator_list_ty with the base URI BASE, and loads +/* Creates a fresh locating_rule_list_ty with the base URI BASE, and loads the locating rules from the files in DIRECTORY. */ -extern struct xlocator_list_ty *xlocator_list_alloc (const char *base, +extern struct locating_rule_list_ty *locating_rule_list_alloc (const char *base, const char *directory); /* Determines the location of resource associated with PATH, accoding - to the loaded locating rules. If INSPECT_CONTENT is true, it also - checks the content of the file pointed by PATH. */ -extern char *xlocator_list_locate (xlocator_list_ty *locators, - const char *path, - bool inspect_content); + to the loaded locating rules. */ +extern char *locating_rule_list_locate (locating_rule_list_ty *locators, + const char *path); /* Releases memory allocated for LOCATORS. */ -extern void xlocator_list_free (xlocator_list_ty *locators); +extern void locating_rule_list_free (locating_rule_list_ty *locators); #ifdef __cplusplus } #endif -#endif /* _XLOCATOR_H */ +#endif /* _LOCATING_RULE_H */ diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index a26a85478..e91a835c6 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -71,8 +71,8 @@ #include "propername.h" #include "sentence.h" #include "unistr.h" -#include "xlocator.h" #include "its.h" +#include "locating-rule.h" #include "gettext.h" /* A convenience macro. I don't like writing gettext() every time. */ @@ -208,7 +208,7 @@ const char *xgettext_current_source_encoding; iconv_t xgettext_current_source_iconv; #endif -static xlocator_list_ty *its_locators; +static locating_rule_list_ty *its_locating_rules; /* Long options. */ static const struct option long_options[] = @@ -719,7 +719,7 @@ xgettext cannot work without keywords to look for")); if (its) { const char *gettextdatadir; - char *itsdir, *ruledir, *locatordir; + char *itsdir; /* Make it possible to override the locator file location. This is necessary for running the testsuite before "make @@ -729,13 +729,8 @@ xgettext cannot work without keywords to look for")); gettextdatadir = relocate (GETTEXTDATADIR); itsdir = xconcatenated_filename (gettextdatadir, "its", NULL); - ruledir = xconcatenated_filename (itsdir, "rules", NULL); - locatordir = xconcatenated_filename (itsdir, "locators", NULL); + its_locating_rules = locating_rule_list_alloc (itsdir, itsdir); free (itsdir); - - its_locators = xlocator_list_alloc (ruledir, locatordir); - free (ruledir); - free (locatordir); } /* Determine extractor from language. */ @@ -875,19 +870,12 @@ This version was built without iconv()."), } } - if (language == NULL && its_locators != NULL) + if (language == NULL && its_locating_rules != NULL) { - bool inspect; char *its_filename = NULL; - /* Inspect the content, only when the file extension is - ".xml". */ - inspect = strlen (reduced) >= 4 - && memcmp (reduced + strlen (reduced) - 4, ".xml", 4) - == 0; - - its_filename = xlocator_list_locate (its_locators, filename, - inspect); + its_filename = locating_rule_list_locate (its_locating_rules, + filename); if (its_filename != NULL) { its_rules = its_rule_list_alloc (); @@ -970,8 +958,8 @@ warning: file '%s' extension '%s' is unknown; will try C"), filename, extension) /* Write the PO file. */ msgdomain_list_print (mdlp, file_name, output_syntax, force_po, do_debug); - if (its_locators) - xlocator_list_free (its_locators); + if (its_locating_rules) + locating_rule_list_free (its_locating_rules); exit (EXIT_SUCCESS); } diff --git a/gettext-tools/src/xlocator.c b/gettext-tools/src/xlocator.c deleted file mode 100644 index e6c331c75..000000000 --- a/gettext-tools/src/xlocator.c +++ /dev/null @@ -1,713 +0,0 @@ -/* XML resource locator - Copyright (C) 2015 Free Software Foundation, Inc. - - This file was written by Daiki Ueno , 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 . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "concat-filename.h" - -#if HAVE_DIRENT_H -# include -#endif - -#if HAVE_DIRENT_H -# define HAVE_DIR 1 -#else -# define HAVE_DIR 0 -#endif - -#include "basename.h" -#include -#include "error.h" -#include "gettext.h" -#include "hash.h" -#include -#include -#include "xalloc.h" - -#include "xlocator.h" - -#define _(str) gettext (str) - -/* The schema is the same as the one used in nXML-mode (in Emacs): - http://www.gnu.org/software/emacs/manual/html_node/nxml-mode/Schema-locating-file-syntax-basics.html#Schema-locating-file-syntax-basics - */ - -#define LOCATING_RULES_NS "http://thaiopensource.com/ns/locating-rules/1.0" - -enum xlocator_type -{ - XLOCATOR_URI, - XLOCATOR_URI_PATTERN, - XLOCATOR_NAMESPACE, - XLOCATOR_DOCUMENT_ELEMENT -}; - -struct xlocator_target_ty -{ - bool is_indirection; - bool is_transform; - char *uri; -}; - -struct xlocator_ty -{ - enum xlocator_type type; - - union { - char *uri; - char *pattern; - char *ns; - struct { - char *prefix; - char *local_name; - } d; - } matcher; - - struct xlocator_target_ty target; -}; - -struct xlocator_list_ty -{ - char *base; - - hash_table indirections; - - struct xlocator_ty *items; - size_t nitems; - size_t nitems_max; -}; - -static char * -_xlocator_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 bool -_xlocator_match_pattern (const char *pattern, const char *filename, - ptrdiff_t *start_offset, ptrdiff_t *end_offset) -{ - const char *p = pattern, *q = filename; - size_t length = strlen (filename); - - while (true) - { - switch (*p) - { - case '\0': - return *q == '\0'; - - case '*': - if (*q == '\0') - return false; - else - { - const char *end = filename + length; - while (true) - { - if (_xlocator_match_pattern (p + 1, end, NULL, NULL)) - { - if (start_offset) - *start_offset = q - filename; - if (end_offset) - *end_offset = end - filename; - return true; - } - if (end == q + 1) - break; - end--; - } - return false; - } - - default: - if (*p == *q) - return _xlocator_match_pattern (p + 1, q + 1, NULL, NULL); - return false; - } - } -} - -static bool -xlocator_match (struct xlocator_ty *locator, const char *path, - struct xlocator_target_ty *target, - bool inspect_content) -{ - switch (locator->type) - { - case XLOCATOR_URI: - return strcmp (locator->matcher.uri, path) == 0; - - case XLOCATOR_URI_PATTERN: - { - char *filename = basename (path); - /* We can't simply use fnmatch() here, since PATH is a component - of a URI. */ - if (!target->is_transform) - return _xlocator_match_pattern (locator->matcher.pattern, filename, - NULL, NULL); - else - { - ptrdiff_t start_offset = -1, end_offset = -1; - char *star, *buffer, *bp; - - if (!_xlocator_match_pattern (locator->matcher.pattern, filename, - &start_offset, &end_offset)) - return false; - - /* If fromPattern doesn't contain '*', use toPattern as it - is as URI. */ - if (start_offset < 0 || end_offset < 0) - return true; - - /* If toPattern doesn't contain '*', use the pattern as it - is as URI. */ - star = strchr (target->uri, '*'); - if (star == NULL) - return true; - - bp = buffer = XNMALLOC ((filename - path) - + (star - target->uri) - + (end_offset - start_offset) - + strlen (star + 1) + 1, - char); - bp = stpncpy (bp, path, filename - path); - if (star > target->uri) - bp = stpncpy (bp, target->uri, star - target->uri); - bp = stpncpy (bp, filename + start_offset, - end_offset - start_offset); - if (*star != '\0') - bp = stpcpy (bp, star + 1); - free (target->uri); - target->is_transform = false; - target->uri = buffer; - return true; - } - } - - case XLOCATOR_NAMESPACE: - case XLOCATOR_DOCUMENT_ELEMENT: - if (!inspect_content) - return false; - else - { - xmlDoc *doc; - xmlNode *root; - bool result; - - doc = xmlReadFile (path, "utf-8", - XML_PARSE_NONET - | XML_PARSE_NOWARNING - | XML_PARSE_NOBLANKS - | XML_PARSE_NOERROR); - if (doc == NULL) - return false; - - - root = xmlDocGetRootElement (doc); - if (locator->type == XLOCATOR_NAMESPACE) - result = root->ns != NULL - && xmlStrEqual (root->ns->href, BAD_CAST locator->matcher.ns); - else - result = - ((!locator->matcher.d.prefix - || *locator->matcher.d.prefix == '\0' - || !root->ns - || xmlStrEqual (root->ns->prefix, - BAD_CAST locator->matcher.d.prefix)) - && (!locator->matcher.d.local_name - || xmlStrEqual (root->name, - BAD_CAST locator->matcher.d.local_name))); - xmlFreeDoc (doc); - return result; - } - - default: - error (0, 0, _("unsupported locator type: %d"), locator->type); - return false; - } -} - -static char * -xlocator_list_resolve_target (struct xlocator_list_ty *locators, - struct xlocator_target_ty *target) -{ - char *target_uri = NULL; - char *result = NULL; - - if (!target->is_indirection) - target_uri = xstrdup (target->uri); - else - { - void *value; - - if (hash_find_entry (&locators->indirections, - target->uri, strlen (target->uri), - &value) == 0) - { - struct xlocator_target_ty *next_target = - (struct xlocator_target_ty *) value; - target_uri = xlocator_list_resolve_target (locators, next_target); - } - else - error (0, 0, _("cannot resolve \"typeId\" %s"), target->uri); - } - - if (target_uri != NULL) - { - char *path; - xmlChar *absolute_uri; - xmlURI *uri; - - /* Use a dummy file name under the locators->base directory, so - that xmlBuildURI() resolve a URI relative to the file, not - the parent directory. */ - path = xconcatenated_filename (locators->base, ".", NULL); - absolute_uri = xmlBuildURI (BAD_CAST target_uri, BAD_CAST path); - free (path); - - uri = xmlParseURI ((const char *) absolute_uri); - xmlFree (absolute_uri); - - if (uri != NULL) - result = xstrdup (uri->path); - xmlFreeURI (uri); - } - - free (target_uri); - return result; -} - -char * -xlocator_list_locate (struct xlocator_list_ty *locators, - const char *path, - bool inspect_content) -{ - struct xlocator_ty *locator; - size_t i; - - for (i = 0; i < locators->nitems; i++) - { - locator = &locators->items[i]; - if (xlocator_match (locator, path, &locator->target, inspect_content)) - break; - } - - if (i == locators->nitems) - return NULL; - - return xlocator_list_resolve_target (locators, &locator->target); -} - -static void -_xlocator_error_missing_attribute (const char *element, const char *attribute) -{ - error (0, 0, _("\"%s\" node does not have \"%s\""), element, attribute); -} - -static void -_xlocator_error_missing_attributes (const char *element, ...) -{ - va_list ap; - char *buffer = NULL; - size_t buflen = 0; - size_t bufmax = 0; - - va_start (ap, element); - while (true) - { - const char *attribute; - size_t length; - - attribute = va_arg (ap, char *); - if (!attribute) - break; - - length = strlen (attribute) + 2; - if (buflen + length + 1 >= bufmax) - { - bufmax = bufmax * 2 + length + 1; - buffer = xrealloc (buffer, bufmax); - } - sprintf (&buffer[buflen], "%s, ", attribute); - buflen += length; - } - va_end (ap); - - if (buflen > 0) - buffer[buflen - 2] = '\0'; - - error (0, 0, _("\"%s\" node must have one of: %s"), - element, buffer); -} - -static bool -xlocator_target_init (struct xlocator_target_ty *target, xmlNode *node) -{ - if (!(xmlHasProp (node, BAD_CAST "uri") - || xmlHasProp (node, BAD_CAST "typeId"))) - { - _xlocator_error_missing_attributes ((const char *) node->name, - "uri", "typeId", NULL); - return false; - } - - if (xmlHasProp (node, BAD_CAST "uri")) - { - target->uri = _xlocator_get_attribute (node, "uri"); - target->is_indirection = false; - } - else - { - target->uri = _xlocator_get_attribute (node, "typeId"); - target->is_indirection = true; - } - - return true; -} - -static size_t -_xlocator_count_transform_pattern (const char *pattern) -{ - const char *p; - size_t result; - - for (p = pattern, result = 0; ; p++, result++) - { - p = strchr (p, '*'); - if (!p) - break; - } - - return result; -} - -static bool -xlocator_init (struct xlocator_ty *locator, xmlNode *node) -{ - memset (locator, 0, sizeof (struct xlocator_ty)); - - if (xmlStrEqual (node->name, BAD_CAST "uri")) - { - if (!(xmlHasProp (node, BAD_CAST "resource") - || xmlHasProp (node, BAD_CAST "pattern"))) - { - _xlocator_error_missing_attributes ("uri", "resource", "pattern", - NULL); - return false; - } - - if (xmlHasProp (node, BAD_CAST "resource")) - { - locator->type = XLOCATOR_URI; - locator->matcher.uri = _xlocator_get_attribute (node, "resource"); - } - else - { - locator->type = XLOCATOR_URI_PATTERN; - locator->matcher.uri = _xlocator_get_attribute (node, "pattern"); - } - - return xlocator_target_init (&locator->target, node); - } - else if (xmlStrEqual (node->name, BAD_CAST "transformURI")) - { - size_t from_count, to_count; - - if (!xmlHasProp (node, BAD_CAST "fromPattern")) - { - _xlocator_error_missing_attribute ("transformURI", "fromPattern"); - return false; - } - if (!xmlHasProp (node, BAD_CAST "toPattern")) - { - _xlocator_error_missing_attribute ("transformURI", "toPattern"); - return false; - } - - locator->type = XLOCATOR_URI_PATTERN; - locator->matcher.uri = _xlocator_get_attribute (node, "fromPattern"); - locator->target.uri = _xlocator_get_attribute (node, "toPattern"); - locator->target.is_transform = true; - - from_count = _xlocator_count_transform_pattern (locator->matcher.uri); - to_count = _xlocator_count_transform_pattern (locator->target.uri); - if (from_count > 1) - { - error (0, 0, _("\"%s\" contains multiple wildcard characters"), - "fromPattern"); - return false; - } - if (to_count > from_count) - { - error (0, 0, _("\"%s\" contains %zu wildcard characters," - " while \"%s\" contains %zu"), - "toPattern", to_count, "fromPattern", from_count); - return false; - } - - return true; - } - else if (xmlStrEqual (node->name, BAD_CAST "namespace")) - { - if (!xmlHasProp (node, BAD_CAST "ns")) - { - _xlocator_error_missing_attribute ("namespace", "ns"); - return false; - } - - locator->type = XLOCATOR_NAMESPACE; - locator->matcher.ns = _xlocator_get_attribute (node, "ns"); - - return xlocator_target_init (&locator->target, node); - } - else if (xmlStrEqual (node->name, BAD_CAST "documentElement")) - { - if (!xmlHasProp (node, BAD_CAST "prefix")) - { - _xlocator_error_missing_attribute ("documentElement", "prefix"); - return false; - } - if (!xmlHasProp (node, BAD_CAST "localName")) - { - _xlocator_error_missing_attribute ("documentElement", "localName"); - return false; - } - - locator->type = XLOCATOR_DOCUMENT_ELEMENT; - locator->matcher.d.prefix = - _xlocator_get_attribute (node, "prefix"); - locator->matcher.d.local_name = - _xlocator_get_attribute (node, "localName"); - - return xlocator_target_init (&locator->target, node); - } - - return false; -} - -static void -xlocator_destroy (struct xlocator_ty *locator) -{ - switch (locator->type) - { - case XLOCATOR_URI: - free (locator->matcher.uri); - break; - - case XLOCATOR_URI_PATTERN: - free (locator->matcher.pattern); - break; - - case XLOCATOR_NAMESPACE: - free (locator->matcher.ns); - break; - - case XLOCATOR_DOCUMENT_ELEMENT: - free (locator->matcher.d.prefix); - free (locator->matcher.d.local_name); - break; - } - - free (locator->target.uri); -} - -static bool -xlocator_list_add_file (struct xlocator_list_ty *locators, - const char *locator_file_name) -{ - xmlDoc *doc; - xmlNode *root, *node; - - doc = xmlReadFile (locator_file_name, "utf-8", - XML_PARSE_NONET - | XML_PARSE_NOWARNING - | XML_PARSE_NOBLANKS - | XML_PARSE_NOERROR); - if (doc == NULL) - 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 "typeId")) - { - struct xlocator_target_ty *target; - char *id; - - if (!(xmlHasProp (node, BAD_CAST "id") - && (xmlHasProp (node, BAD_CAST "typeId") - || xmlHasProp (node, BAD_CAST "uri")))) - { - xmlFreeDoc (doc); - return false; - } - - id = _xlocator_get_attribute (node, "id"); - target = XMALLOC (struct xlocator_target_ty); - if (xmlHasProp (node, BAD_CAST "typeId")) - { - target->is_indirection = true; - target->uri = _xlocator_get_attribute (node, "typeId"); - } - else - { - target->is_indirection = false; - target->uri = _xlocator_get_attribute (node, "uri"); - } - hash_insert_entry (&locators->indirections, id, strlen (id), - target); - free (id); - } - else - { - struct xlocator_ty locator; - - if (!xlocator_init (&locator, node)) - { - xlocator_destroy (&locator); - continue; - } - - if (locators->nitems == locators->nitems_max) - { - locators->nitems_max = 2 * locators->nitems_max + 1; - locators->items = - xrealloc (locators->items, - sizeof (struct xlocator_ty) * locators->nitems_max); - } - memcpy (&locators->items[locators->nitems++], &locator, - sizeof (struct xlocator_ty)); - } - } - - xmlFreeDoc (doc); - return true; -} - -static bool -xlocator_list_add_directory (struct xlocator_list_ty *locators, - 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); - xlocator_list_add_file (locators, locator_file_name); - free (locator_file_name); - } - } - else if (errno != 0) - return false; - else - break; - } - if (closedir (dirp)) - return false; - -#endif - return true; -} - -struct xlocator_list_ty * -xlocator_list_alloc (const char *base, const char *directory) -{ - struct xlocator_list_ty *result; - - xmlCheckVersion (LIBXML_VERSION); - - result = XCALLOC (1, struct xlocator_list_ty); - hash_init (&result->indirections, 10); - result->base = xstrdup (base); - - xlocator_list_add_directory (result, directory); - - return result; -} - -void -xlocator_list_destroy (struct xlocator_list_ty *locators) -{ - void *iter; - const void *key; - size_t keylen; - void *data; - - iter = NULL; - while (hash_iterate (&locators->indirections, &iter, &key, &keylen, &data) - == 0) - { - struct xlocator_target_ty *target = data; - free (target->uri); - free (target); - } - hash_destroy (&locators->indirections); - - free (locators->base); - - while (locators->nitems-- > 0) - xlocator_destroy (&locators->items[locators->nitems]); - free (locators->items); -} - -void -xlocator_list_free (struct xlocator_list_ty *locators) -{ - if (locators != NULL) - xlocator_list_destroy (locators); - free (locators); -} diff --git a/gettext-tools/tests/xgettext-its-1 b/gettext-tools/tests/xgettext-its-1 index 605e93872..e814b8c77 100755 --- a/gettext-tools/tests/xgettext-its-1 +++ b/gettext-tools/tests/xgettext-its-1 @@ -16,26 +16,26 @@ EOF ${XGETTEXT} --its -o empty.pot empty.xml 2>empty.err || { cat empty.err; exit 1; } test -d its || mkdir its -test -d its/locators || mkdir its/locators -test -d its/rules || mkdir its/rules -cat <<\EOF > its/locators/empty-1.loc +cat <<\EOF > its/empty-1.loc EOF ${XGETTEXT} --its -o empty.pot empty.xml 2>empty.err || { cat empty.err; exit 1; } -cat <<\EOF > its/locators/empty-2.loc +cat <<\EOF > its/empty-2.loc - - + + + + EOF ${XGETTEXT} --its -o empty.pot empty.xml 2>empty.err || { cat empty.err; exit 1; } -cat <<\EOF > its/rules/empty.its +cat <<\EOF > its/empty.its @@ -43,14 +43,16 @@ EOF ${XGETTEXT} --its -o empty.pot empty.xml 2>empty.err || { cat empty.err; exit 1; } -cat <<\EOF > its/locators/messages.loc +cat <<\EOF > its/messages.loc - - + + + + EOF -cat <<\EOF > its/rules/messages.its +cat <<\EOF > its/messages.its