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. */
'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. */
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);
}
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;
/* 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.
*/
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
/* 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,
/* 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++)
#include "error.h"
#include "hash.h"
+#include "message.h"
#include "system.h"
#include "libgettext.h"
/* 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;
};
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:
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;
}
/* 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;
/* 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;
}
/* 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;
}
/* 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)
{
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))