]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
msgfmt: Refactor --desktop handling
authorDaiki Ueno <ueno@gnu.org>
Mon, 5 Oct 2015 07:33:31 +0000 (16:33 +0900)
committerDaiki Ueno <ueno@gnu.org>
Tue, 6 Oct 2015 01:03:34 +0000 (10:03 +0900)
* gettext-tools/src/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.
* gettext-tools/src/msgfmt.h (msgfmt_operand_ty,
msgfmt_operand_list_ty): New type.
* gettext-tools/src/write-desktop.c (msgdomain_write_desktop_bulk):
Simplify using msgfmt_operand_list_ty.
(msgdomain_write_desktop): Simplify using msgfmt_operand_list_ty.
* gettext-tools/src/write-desktop.h (msgdomain_write_desktop_bulk):
Take OPERANDS as the first argument, instead of LANGUAGES and MESSAGES.

gettext-tools/src/ChangeLog
gettext-tools/src/msgfmt.c
gettext-tools/src/msgfmt.h
gettext-tools/src/write-desktop.c
gettext-tools/src/write-desktop.h

index a29357ec84b75763cb3661de1403753d8bce8599..95b0b337104df442b2469a0e5568bd0cfd3d23e0 100644 (file)
@@ -1,3 +1,20 @@
+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
index ef91f4918d7387ef679f28a178ec6cd6a1a9d710..c1398033a803bc8732ad2a4ad984b00f5edddc6c 100644 (file)
@@ -212,7 +212,6 @@ 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,
@@ -1298,35 +1297,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");
@@ -1334,11 +1328,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))
@@ -1368,32 +1358,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);
+}
 
-  return languages;
+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;
+
+  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_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.  */
@@ -1401,34 +1427,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.  */
@@ -1437,38 +1464,58 @@ 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);
     }
 
-  /* Write the messages into .desktop file.  */
-  if (msgdomain_write_desktop_bulk (languages,
-                                    messages,
-                                    template_file_name,
-                                    keywords,
-                                    file_name))
+  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 retval;
+
+  msgfmt_operand_list_init (&operands);
+
+  /* Read all .po files.  */
+  retval = msgfmt_operand_list_add_directory (&operands, directory);
+  if (retval > 0)
     {
-      retval = EXIT_FAILURE;
-      goto out;
+      msgfmt_operand_list_destroy (&operands);
+      return retval;
     }
 
- 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 .desktop file.  */
+  retval = msgdomain_write_desktop_bulk (&operands,
+                                         template_file_name,
+                                         keywords,
+                                         file_name);
+
+  msgfmt_operand_list_destroy (&operands);
 
   return retval;
 }
index 8f28b338001874fff1315f2ff05d3973341055c3..3651a30cc98e1f96e78134680652cbd37a3f87de 100644 (file)
 #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 */
index b1de2fdf5b60eec270435723279f2e3e333be9b4..cb45f8aae593ad1140974c64bb80164a768e9b76 100644 (file)
@@ -43,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;
 };
@@ -78,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;
@@ -92,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);
                 }
             }
@@ -138,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)
@@ -151,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)
@@ -200,27 +196,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);
+  /* 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;
 
-  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);
-
-  return retval;
+  return msgdomain_write_desktop_bulk (&operands,
+                                       template_file_name,
+                                       keywords,
+                                       file_name);
 }
index 43cb54cd905dc5fad069b8210488a1b625e05d16..d6408e29da872b7a3019d8d5db466fa2c918bcc6 100644 (file)
@@ -19,7 +19,7 @@
 #ifndef _WRITE_DESKTOP_H
 #define _WRITE_DESKTOP_H
 
-#include "message.h"
+#include "msgfmt.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -38,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);