]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Change the .mo file writer to accept a list of messages, not a hash table.
authorBruno Haible <bruno@clisp.org>
Wed, 5 Sep 2001 12:02:41 +0000 (12:02 +0000)
committerBruno Haible <bruno@clisp.org>
Wed, 5 Sep 2001 12:02:41 +0000 (12:02 +0000)
src/ChangeLog
src/msgfmt.c
src/msgfmt.h
src/write-mo.c
src/write-mo.h

index b3139ee11746546434a9eb61a1096a85493629df..e1ea0ca491d608956c5afe0fa7a35e0fdf0a1501 100644 (file)
@@ -1,3 +1,23 @@
+2001-09-02  Bruno Haible  <haible@clisp.cons.org>
+
+       * msgfmt.h (struct hashtable_entry): Remove type.
+       (verbose): New declaration.
+       * msgfmt.c (msg_domain): Add a message list field.
+       (verbose): Make non-static.
+       (main): Pass the message list, not the hash table, to
+       msgdomain_write_mo. Free the message list when done.
+       (new_domain): Initialize the message list to empty.
+       (format_directive_message): Change type of entry to 'message_ty *'.
+       Store msgid in it.
+       * write-mo.h: Don't include hash.h.
+       (msgdomain_write_mo): Change argument type from hash table to message
+       list.
+       * write-mo.c (id_str_pair): Add const.
+       (write_table): Change argument type from hash table to message list.
+       Use 'message_ty' instead of 'struct hashtable_entry'.
+       (msgdomain_write_mo): Change argument type from hash table to message
+       list.
+
 2001-09-01  Bruno Haible  <haible@clisp.cons.org>
 
        * msgfmt.h: New file, extracted from msgfmt.c.
index fc5ff60795cf48ef0b7844cadc2d2bdcbc0a3cd3..68d97571405a866752d164822c634147f8894db3 100644 (file)
@@ -75,6 +75,8 @@ static const char *output_file_name;
    each output file.  */
 struct msg_domain
 {
+  /* List for mapping message IDs to message strings.  */
+  message_list_ty *mlp;
   /* Table for mapping message IDs to message strings.  */
   hash_table symbol_tab;
   /* Name of domain these ID/String pairs are part of.  */
@@ -91,7 +93,7 @@ static struct msg_domain *current_domain;
    '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().  */
-static bool verbose = false;
+bool verbose = false;
 
 /* If true check strings according to format string rules for the
    language.  */
@@ -309,11 +311,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 
   for (domain = domain_list; domain != NULL; domain = domain->next)
     {
-      if (msgdomain_write_mo (&domain->symbol_tab, domain->domain_name,
+      if (msgdomain_write_mo (domain->mlp, domain->domain_name,
                              domain->file_name))
        exit_status = EXIT_FAILURE;
 
-      /* Hashing table is not used anmore.  */
+      /* List is not used anymore.  */
+      message_list_free (domain->mlp);
+      /* Hashing table is not used anymore.  */
       delete_hash (&domain->symbol_tab);
     }
 
@@ -452,6 +456,7 @@ new_domain (name, file_name)
       struct msg_domain *domain;
 
       domain = (struct msg_domain *) xmalloc (sizeof (struct msg_domain));
+      domain->mlp = message_list_alloc ();
       if (init_hash (&domain->symbol_tab, 100) != 0)
        error (EXIT_FAILURE, errno, _("while creating hash table"));
       domain->domain_name = name;
@@ -628,10 +633,8 @@ check_pair (msgid, msgid_pos, msgid_plural, msgstr, msgstr_len, msgstr_pos,
 
 
 /* The rest of the file is similar to read-po.c.  The differences are:
-   - The result is a hash table of msgid -> struct hashtable_entry, not
-     a linear list.  This is more efficient, because the order of the
-     entries does not matter and the only lookup operation performed on
-     the message set is the duplicate lookup.
+   - The result is both a message_list_ty and a hash table mapping
+     msgid -> message_ty.  This is useful to speed up the duplicate lookup.
    - Comments are not stored, they are discarded right away.
    - The header entry check is performed on-the-fly.
  */
@@ -729,7 +732,7 @@ format_directive_message (that, msgid_string, msgid_pos, msgid_plural,
      bool obsolete;
 {
   msgfmt_class_ty *this = (msgfmt_class_ty *) that;
-  struct hashtable_entry *entry;
+  message_ty *entry;
   size_t i;
 
   /* Don't emit untranslated entries.  Also don't emit fuzzy entries, unless
@@ -824,12 +827,11 @@ some header fields still have the initial default value"));
 
       /* We found a valid pair of msgid/msgstr.
         Construct struct to describe msgstr definition.  */
-      entry = (struct hashtable_entry *) xmalloc (sizeof (*entry));
-
+      entry = message_alloc (NULL, NULL, NULL, 0, msgstr_pos);
+      entry->msgid = msgid_string;
       entry->msgid_plural = msgid_plural;
       entry->msgstr = msgstr_string;
       entry->msgstr_len = msgstr_len;
-      entry->pos = *msgstr_pos;
 
       /* Do some more checks on both strings.  */
       check_pair (msgid_string, msgid_pos, msgid_plural,
@@ -867,13 +869,13 @@ duplicate message definition"));
 
          /* We don't need the just constructed entries'
             parameter string (allocated in po-gram.y).  */
+         free (msgid_string);
          free (msgstr_string);
        }
+      else
+       message_list_append (current_domain->mlp, entry);
   }
 
-  /* We do not need the msgid string in any case.  */
-  free (msgid_string);
-
   /* Prepare for next message.  */
   this->is_fuzzy = false;
   for (i = 0; i < NFORMATS; i++)
index 1dbe2ec97d41913274c659f14d3c90631ea66773..758e96f82c6578dd024a4008ff554517f95cf691 100644 (file)
 #ifndef _MSGFMT_H
 #define _MSGFMT_H
 
-#include "pos.h"
+#include "message.h"
 
-/* Contains information about the definition of one translation.
-   The msgid is the hash table key.  This is a mini 'struct message_ty'.  */
-struct hashtable_entry
-{
-  char *msgid_plural;  /* The msgid's plural, if present.  */
-  char *msgstr;                /* The msgstr strings.  */
-  size_t msgstr_len;   /* The number of bytes in msgstr, including NULs.  */
-  lex_pos_ty pos;      /* Position in the source PO file.  */
-};
+/* 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 bool verbose;
 
 #endif /* _MSGFMT_H */
index d74de578e3419ad74ab1ed48d2510c61be1068cc..fa1488c4b0235e0d80320240e32171d7c10f234d 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "error.h"
 #include "hash.h"
+#include "message.h"
 #include "system.h"
 #include "libgettext.h"
 
@@ -62,18 +63,18 @@ bool no_hash_table;
 /* Prototypes for local functions.  Needed to ensure compiler checking of
    function argument counts despite of K&R C function definition syntax.  */
 static int compare_id PARAMS ((const void *pval1, const void *pval2));
-static void write_table PARAMS ((FILE *output_file, hash_table *tab));
+static void write_table PARAMS ((FILE *output_file, message_list_ty *mlp));
 
 
 /* Define the data structure which we need to represent the data to
    be written out.  */
 struct id_str_pair
 {
-  char *id;
+  const char *id;
   size_t id_len;
-  char *id_plural;
+  const char *id_plural;
   size_t id_plural_len;
-  char *str;
+  const char *str;
   size_t str_len;
 };
 
@@ -89,9 +90,9 @@ compare_id (pval1, pval2)
 
 
 static void
-write_table (output_file, tab)
+write_table (output_file, mlp)
      FILE *output_file;
-     hash_table *tab;
+     message_list_ty *mlp;
 {
   static char null = '\0';
   /* This should be explained:
@@ -115,66 +116,63 @@ write_table (output_file, tab)
      Formulas: [Knuth, The Art of Computer Programming, Volume 3,
                Sorting and Searching, 1973, Addison Wesley]  */
   nls_uint32 hash_tab_size =
-    (no_hash_table ? 0 : next_prime ((tab->filled * 4) / 3));
+    (no_hash_table ? 0 : next_prime ((mlp->nitems * 4) / 3));
   nls_uint32 *hash_tab;
 
   /* Header of the .mo file to be written.  */
   struct mo_file_header header;
   struct id_str_pair *msg_arr;
-  void *ptr;
-  size_t cnt;
-  const void *id;
-  size_t id_len;
-  struct hashtable_entry *entry;
+  size_t cnt, j;
+  message_ty *entry;
   struct string_desc sd;
 
   /* Fill the structure describing the header.  */
   header.magic = _MAGIC;               /* Magic number.  */
   header.revision = MO_REVISION_NUMBER;        /* Revision number of file format.  */
-  header.nstrings = tab->filled;       /* Number of strings.  */
+  header.nstrings = mlp->nitems;       /* Number of strings.  */
   header.orig_tab_offset = sizeof (header);
                        /* Offset of table for original string offsets.  */
   header.trans_tab_offset = sizeof (header)
-                           + tab->filled * sizeof (struct string_desc);
+                           + mlp->nitems * sizeof (struct string_desc);
                        /* Offset of table for translation string offsets.  */
   header.hash_tab_size = hash_tab_size;        /* Size of used hashing table.  */
   header.hash_tab_offset =
        no_hash_table ? 0 : sizeof (header)
-                           + 2 * (tab->filled * sizeof (struct string_desc));
+                           + 2 * (mlp->nitems * sizeof (struct string_desc));
                        /* Offset of hashing table.  */
 
   /* Write the header out.  */
   fwrite (&header, sizeof (header), 1, output_file);
 
   /* Allocate table for the all elements of the hashing table.  */
-  msg_arr = (struct id_str_pair *) alloca (tab->filled * sizeof (msg_arr[0]));
+  msg_arr = (struct id_str_pair *) alloca (mlp->nitems * sizeof (msg_arr[0]));
 
-  /* Read values from hashing table into array.  */
-  for (cnt = 0, ptr = NULL;
-       iterate_table (tab, &ptr, &id, &id_len, (void **) &entry) >= 0;
-       ++cnt)
+  /* Read values from list into array.  */
+  for (j = 0; j < mlp->nitems; j++)
     {
-      msg_arr[cnt].id = (char *) id;
-      msg_arr[cnt].id_len = id_len;
-      msg_arr[cnt].id_plural = entry->msgid_plural;
-      msg_arr[cnt].id_plural_len =
+      entry = mlp->item[j];
+
+      msg_arr[j].id = entry->msgid;
+      msg_arr[j].id_len = strlen (entry->msgid) + 1;
+      msg_arr[j].id_plural = entry->msgid_plural;
+      msg_arr[j].id_plural_len =
        (entry->msgid_plural != NULL ? strlen (entry->msgid_plural) + 1 : 0);
-      msg_arr[cnt].str = entry->msgstr;
-      msg_arr[cnt].str_len = entry->msgstr_len;
+      msg_arr[j].str = entry->msgstr;
+      msg_arr[j].str_len = entry->msgstr_len;
     }
 
   /* Sort the table according to original string.  */
-  qsort (msg_arr, tab->filled, sizeof (msg_arr[0]), compare_id);
+  qsort (msg_arr, mlp->nitems, sizeof (msg_arr[0]), compare_id);
 
   /* Set offset to first byte after all the tables.  */
   sd.offset = roundup (sizeof (header)
-                      + tab->filled * sizeof (sd)
-                      + tab->filled * sizeof (sd)
+                      + mlp->nitems * sizeof (sd)
+                      + mlp->nitems * sizeof (sd)
                       + hash_tab_size * sizeof (nls_uint32),
                       alignment);
 
   /* Write out length and starting offset for all original strings.  */
-  for (cnt = 0; cnt < tab->filled; ++cnt)
+  for (cnt = 0; cnt < mlp->nitems; ++cnt)
     {
       /* Subtract 1 because of the terminating NUL.  */
       sd.length = msg_arr[cnt].id_len + msg_arr[cnt].id_plural_len - 1;
@@ -183,7 +181,7 @@ write_table (output_file, tab)
     }
 
   /* Write out length and starting offset for all translation strings.  */
-  for (cnt = 0; cnt < tab->filled; ++cnt)
+  for (cnt = 0; cnt < mlp->nitems; ++cnt)
     {
       /* Subtract 1 because of the terminating NUL.  */
       sd.length = msg_arr[cnt].str_len - 1;
@@ -200,7 +198,7 @@ write_table (output_file, tab)
 
       /* Insert all value in the hash table, following the algorithm described
         above.  */
-      for (cnt = 0; cnt < tab->filled; ++cnt)
+      for (cnt = 0; cnt < mlp->nitems; ++cnt)
        {
          nls_uint32 hash_val = hash_string (msg_arr[cnt].id);
          nls_uint32 idx = hash_val % hash_tab_size;
@@ -226,12 +224,12 @@ write_table (output_file, tab)
     }
 
   /* Write bytes to make first string to be aligned.  */
-  cnt = sizeof (header) + 2 * tab->filled * sizeof (sd)
+  cnt = sizeof (header) + 2 * mlp->nitems * sizeof (sd)
        + hash_tab_size * sizeof (nls_uint32);
   fwrite (&null, 1, roundup (cnt, alignment) - cnt, output_file);
 
   /* Now write the original strings.  */
-  for (cnt = 0; cnt < tab->filled; ++cnt)
+  for (cnt = 0; cnt < mlp->nitems; ++cnt)
     {
       size_t len = msg_arr[cnt].id_len + msg_arr[cnt].id_plural_len;
 
@@ -243,28 +241,26 @@ write_table (output_file, tab)
     }
 
   /* Now write the translation strings.  */
-  for (cnt = 0; cnt < tab->filled; ++cnt)
+  for (cnt = 0; cnt < mlp->nitems; ++cnt)
     {
       size_t len = msg_arr[cnt].str_len;
 
       fwrite (msg_arr[cnt].str, len, 1, output_file);
       fwrite (&null, 1, roundup (len, alignment) - len, output_file);
-
-      free (msg_arr[cnt].str);
     }
 }
 
 
 int
-msgdomain_write_mo (tab, domain_name, file_name)
-     hash_table *tab;
+msgdomain_write_mo (mlp, domain_name, file_name)
+     message_list_ty *mlp;
      const char *domain_name;
      const char *file_name;
 {
   FILE *output_file;
 
   /* If no entry for this domain don't even create the file.  */
-  if (tab->filled != 0)
+  if (mlp->nitems != 0)
     {
       if (strcmp (domain_name, "-") == 0)
        {
@@ -284,7 +280,7 @@ msgdomain_write_mo (tab, domain_name, file_name)
 
       if (output_file != NULL)
        {
-         write_table (output_file, tab);
+         write_table (output_file, mlp);
 
          /* Make sure nothing went wrong.  */
          if (fflush (output_file) || ferror (output_file))
index 973b0047e4fcf934af4ab3357657b9c4c732995e..2f9c7dbebb44382392956fe42de439b2776eb187 100644 (file)
@@ -22,7 +22,6 @@
 #include <stdbool.h>
 
 #include "msgfmt.h"
-#include "hash.h"
 
 /* Alignment of strings in resulting .mo file.  */
 extern size_t alignment;
@@ -30,12 +29,12 @@ extern size_t alignment;
 /* True if no hash table in .mo is wanted.  */
 extern bool no_hash_table;
 
-/* Write a GNU mo file.  tab is a hash table containing the messages to be
-   output, mapping 'const char *msgid' to 'struct hashtable_entry *'.
+/* Write a GNU mo file.  mlp is a list containing the messages to be output.
    domain_name is the domain name, file_name is the desired file name.
    Return 0 if ok, nonzero on error.  */
 extern int
-       msgdomain_write_mo PARAMS ((hash_table *tab, const char *domain_name,
+       msgdomain_write_mo PARAMS ((message_list_ty *mlp,
+                                  const char *domain_name,
                                   const char *file_name));
 
 #endif /* _WRITE_MO_H */