+2001-09-02 Bruno Haible <haible@clisp.cons.org>
+
+ * read-mo.h: New file.
+ * read-mo.c: New file, extracted from msgunfmt.c.
+ (read_mo_file): Require non-null message list argument. Return void.
+ * msgunfmt.c (endian, read32, seek32, string32, read_mo_file): Move to
+ read-mo.c.
+ (main): Pass a fresh list, not NULL, to read_mo_file.
+ * Makefile.am (noinst_HEADERS): Add read-mo.h.
+ (msgunfmt_SOURCES): Add read-mo.c.
+
2001-09-02 Bruno Haible <haible@clisp.cons.org>
* msgfmt.h (struct hashtable_entry): Remove type.
noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-charset.h po-lex.h \
po.h open-po.h read-po.h str-list.h write-po.h dir-list.h file-list.h \
po-gram-gen.h po-hash-gen.h msgl-charset.h msgl-iconv.h msgl-ascii.h \
-msgl-cat.h msgfmt.h write-mo.h xgettext.h x-c.h x-po.h
+msgl-cat.h msgfmt.h read-mo.h write-mo.h xgettext.h x-c.h x-po.h
EXTRA_DIST = FILES
msgmerge_SOURCES = message.c msgmerge.c open-po.c po-gram-gen.y po-hash-gen.y \
po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c write-po.c \
msgl-ascii.c
-msgunfmt_SOURCES = message.c msgunfmt.c str-list.c write-po.c msgl-ascii.c
+msgunfmt_SOURCES = message.c msgunfmt.c str-list.c write-po.c msgl-ascii.c \
+read-mo.c
xgettext_SOURCES = message.c open-po.c po-gram-gen.y po-hash-gen.y \
po-charset.c po-lex.c po.c str-list.c xgettext.c dir-list.c write-po.c \
msgl-ascii.c file-list.c x-c.c x-po.c \
# include <config.h>
#endif
-#include <errno.h>
#include <getopt.h>
#include <stdio.h>
-#include <sys/param.h>
-#include <sys/types.h>
#include <stdlib.h>
#include <locale.h>
-#include "hash.h"
-
#include "error.h"
#include "progname.h"
-#include "getline.h"
-#include "printf.h"
-#include <system.h>
-
-#include "gettext.h"
-#include "hash-string.h"
-#include "libgettext.h"
+#include "system.h"
#include "message.h"
+#include "read-mo.h"
#include "write-po.h"
+#include "libgettext.h"
#define _(str) gettext (str)
-#ifndef errno
-extern int errno;
-#endif
-
/* Force output of PO file even if empty. */
static int force_po;
};
-/* This defines the byte order within the file. It needs to be set
- appropriately once we have the file open. */
-static enum { MO_LITTLE_ENDIAN, MO_BIG_ENDIAN } endian;
-
-
/* Prototypes for local functions. Needed to ensure compiler checking of
function argument counts despite of K&R C function definition syntax. */
static void usage PARAMS ((int status));
-static nls_uint32 read32 PARAMS ((FILE *fp, const char *fn));
-static void seek32 PARAMS ((FILE *fp, const char *fn, long offset));
-static char *string32 PARAMS ((FILE *fp, const char *fn, long offset,
- size_t *lengthp));
-static message_list_ty *read_mo_file PARAMS ((message_list_ty *mlp,
- const char *fn));
int
usage (EXIT_SUCCESS);
/* Read the given .mo file. */
+ mlp = message_list_alloc ();
if (optind < argc)
{
- mlp = NULL;
do
- mlp = read_mo_file (mlp, argv[optind]);
+ read_mo_file (mlp, argv[optind]);
while (++optind < argc);
}
else
- mlp = read_mo_file (NULL, "-");
+ read_mo_file (mlp, "-");
result = msgdomain_list_alloc ();
result->item[0]->messages = mlp;
exit (status);
}
-
-
-/* This function reads a 32-bit number from the file, and assembles it
- according to the current ``endian'' setting. */
-static nls_uint32
-read32 (fp, fn)
- FILE *fp;
- const char *fn;
-{
- int c1, c2, c3, c4;
-
- c1 = getc (fp);
- if (c1 == EOF)
- {
- bomb:
- if (ferror (fp))
- error (EXIT_FAILURE, errno, _("error while reading \"%s\""), fn);
- error (EXIT_FAILURE, 0, _("file \"%s\" truncated"), fn);
- }
- c2 = getc (fp);
- if (c2 == EOF)
- goto bomb;
- c3 = getc (fp);
- if (c3 == EOF)
- goto bomb;
- c4 = getc (fp);
- if (c4 == EOF)
- goto bomb;
- if (endian == MO_LITTLE_ENDIAN)
- return (((nls_uint32) c1)
- | ((nls_uint32) c2 << 8)
- | ((nls_uint32) c3 << 16)
- | ((nls_uint32) c4 << 24));
-
- return (((nls_uint32) c1 << 24)
- | ((nls_uint32) c2 << 16)
- | ((nls_uint32) c3 << 8)
- | ((nls_uint32) c4));
-}
-
-
-static void
-seek32 (fp, fn, offset)
- FILE *fp;
- const char *fn;
- long offset;
-{
- if (fseek (fp, offset, 0) < 0)
- error (EXIT_FAILURE, errno, _("seek \"%s\" offset %ld failed"),
- fn, offset);
-}
-
-
-static char *
-string32 (fp, fn, offset, lengthp)
- FILE *fp;
- const char *fn;
- long offset;
- size_t *lengthp;
-{
- long length;
- char *buffer;
- long n;
-
- /* Read the string_desc structure, describing where in the file to
- find the string. */
- seek32 (fp, fn, offset);
- length = read32 (fp, fn);
- offset = read32 (fp, fn);
-
- /* Allocate memory for the string to be read into. Leave space for
- the NUL on the end. */
- buffer = (char *) xmalloc (length + 1);
-
- /* Read in the string. Complain if there is an error or it comes up
- short. Add the NUL ourselves. */
- seek32 (fp, fn, offset);
- n = fread (buffer, 1, length + 1, fp);
- if (n != length + 1)
- {
- if (ferror (fp))
- error (EXIT_FAILURE, errno, _("error while reading \"%s\""), fn);
- error (EXIT_FAILURE, 0, _("file \"%s\" truncated"), fn);
- }
- if (buffer[length] != '\0')
- {
- error (EXIT_FAILURE, 0,
- _("file \"%s\" contains a not NUL terminated string"), fn);
- }
-
- /* Return the string to the caller. */
- *lengthp = length + 1;
- return buffer;
-}
-
-
-/* This function reads an existing .mo file. Return a message list. */
-static message_list_ty *
-read_mo_file (mlp, fn)
- message_list_ty *mlp;
- const char *fn;
-{
- FILE *fp;
- struct mo_file_header header;
- int j;
-
- if (strcmp (fn, "-") == 0 || strcmp (fn, "/dev/stdin") == 0)
- {
- fp = stdin;
- SET_BINARY (fileno (fp));
- }
- else
- {
- fp = fopen (fn, "rb");
- if (fp == NULL)
- error (EXIT_FAILURE, errno,
- _("error while opening \"%s\" for reading"), fn);
- }
-
- /* We must grope the file to determine which endian it is.
- Perversity of the universe tends towards maximum, so it will
- probably not match the currently executing architecture. */
- endian = MO_BIG_ENDIAN;
- header.magic = read32 (fp, fn);
- if (header.magic != _MAGIC)
- {
- endian = MO_LITTLE_ENDIAN;
- seek32 (fp, fn, 0L);
- header.magic = read32 (fp, fn);
- if (header.magic != _MAGIC)
- {
- unrecognised:
- error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"),
- fn);
- }
- }
-
- /* Fill the structure describing the header. */
- header.revision = read32 (fp, fn);
- if (header.revision != MO_REVISION_NUMBER)
- goto unrecognised;
- header.nstrings = read32 (fp, fn);
- header.orig_tab_offset = read32 (fp, fn);
- header.trans_tab_offset = read32 (fp, fn);
- header.hash_tab_size = read32 (fp, fn);
- header.hash_tab_offset = read32 (fp, fn);
-
- if (mlp == NULL)
- mlp = message_list_alloc ();
- for (j = 0; j < header.nstrings; ++j)
- {
- static lex_pos_ty pos = { __FILE__, __LINE__ };
- message_ty *mp;
- char *msgid;
- size_t msgid_len;
- char *msgstr;
- size_t msgstr_len;
-
- /* Read the msgid. */
- msgid = string32 (fp, fn, header.orig_tab_offset + j * 8, &msgid_len);
-
- /* Read the msgstr. */
- msgstr = string32 (fp, fn, header.trans_tab_offset + j * 8, &msgstr_len);
-
- mp = message_alloc (msgid,
- (strlen (msgid) + 1 < msgid_len
- ? msgid + strlen (msgid) + 1
- : NULL),
- msgstr, msgstr_len, &pos);
- message_list_append (mlp, mp);
- }
-
- if (fp != stdin)
- fclose (fp);
- return mlp;
-}
--- /dev/null
+/* Reading binary .mo files.
+ Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
+
+ 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 2, 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, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "read-mo.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* This include file describes the main part of binary .mo format. */
+#include "gettext.h"
+
+#include "error.h"
+#include "system.h"
+#include "message.h"
+#include "libgettext.h"
+
+#define _(str) gettext (str)
+
+
+/* This defines the byte order within the file. It needs to be set
+ appropriately once we have the file open. */
+static enum { MO_LITTLE_ENDIAN, MO_BIG_ENDIAN } endian;
+
+
+/* Prototypes for local functions. Needed to ensure compiler checking of
+ function argument counts despite of K&R C function definition syntax. */
+static nls_uint32 read32 PARAMS ((FILE *fp, const char *fn));
+static void seek32 PARAMS ((FILE *fp, const char *fn, long offset));
+static char *string32 PARAMS ((FILE *fp, const char *fn, long offset,
+ size_t *lengthp));
+
+
+/* This function reads a 32-bit number from the file, and assembles it
+ according to the current ``endian'' setting. */
+static nls_uint32
+read32 (fp, fn)
+ FILE *fp;
+ const char *fn;
+{
+ int c1, c2, c3, c4;
+
+ c1 = getc (fp);
+ if (c1 == EOF)
+ {
+ bomb:
+ if (ferror (fp))
+ error (EXIT_FAILURE, errno, _("error while reading \"%s\""), fn);
+ error (EXIT_FAILURE, 0, _("file \"%s\" truncated"), fn);
+ }
+ c2 = getc (fp);
+ if (c2 == EOF)
+ goto bomb;
+ c3 = getc (fp);
+ if (c3 == EOF)
+ goto bomb;
+ c4 = getc (fp);
+ if (c4 == EOF)
+ goto bomb;
+ if (endian == MO_LITTLE_ENDIAN)
+ return (((nls_uint32) c1)
+ | ((nls_uint32) c2 << 8)
+ | ((nls_uint32) c3 << 16)
+ | ((nls_uint32) c4 << 24));
+
+ return (((nls_uint32) c1 << 24)
+ | ((nls_uint32) c2 << 16)
+ | ((nls_uint32) c3 << 8)
+ | ((nls_uint32) c4));
+}
+
+
+static void
+seek32 (fp, fn, offset)
+ FILE *fp;
+ const char *fn;
+ long offset;
+{
+ if (fseek (fp, offset, 0) < 0)
+ error (EXIT_FAILURE, errno, _("seek \"%s\" offset %ld failed"),
+ fn, offset);
+}
+
+
+static char *
+string32 (fp, fn, offset, lengthp)
+ FILE *fp;
+ const char *fn;
+ long offset;
+ size_t *lengthp;
+{
+ long length;
+ char *buffer;
+ long n;
+
+ /* Read the string_desc structure, describing where in the file to
+ find the string. */
+ seek32 (fp, fn, offset);
+ length = read32 (fp, fn);
+ offset = read32 (fp, fn);
+
+ /* Allocate memory for the string to be read into. Leave space for
+ the NUL on the end. */
+ buffer = (char *) xmalloc (length + 1);
+
+ /* Read in the string. Complain if there is an error or it comes up
+ short. Add the NUL ourselves. */
+ seek32 (fp, fn, offset);
+ n = fread (buffer, 1, length + 1, fp);
+ if (n != length + 1)
+ {
+ if (ferror (fp))
+ error (EXIT_FAILURE, errno, _("error while reading \"%s\""), fn);
+ error (EXIT_FAILURE, 0, _("file \"%s\" truncated"), fn);
+ }
+ if (buffer[length] != '\0')
+ {
+ error (EXIT_FAILURE, 0,
+ _("file \"%s\" contains a not NUL terminated string"), fn);
+ }
+
+ /* Return the string to the caller. */
+ *lengthp = length + 1;
+ return buffer;
+}
+
+
+/* This function reads an existing .mo file. */
+void
+read_mo_file (mlp, fn)
+ message_list_ty *mlp;
+ const char *fn;
+{
+ FILE *fp;
+ struct mo_file_header header;
+ int j;
+
+ if (strcmp (fn, "-") == 0 || strcmp (fn, "/dev/stdin") == 0)
+ {
+ fp = stdin;
+ SET_BINARY (fileno (fp));
+ }
+ else
+ {
+ fp = fopen (fn, "rb");
+ if (fp == NULL)
+ error (EXIT_FAILURE, errno,
+ _("error while opening \"%s\" for reading"), fn);
+ }
+
+ /* We must grope the file to determine which endian it is.
+ Perversity of the universe tends towards maximum, so it will
+ probably not match the currently executing architecture. */
+ endian = MO_BIG_ENDIAN;
+ header.magic = read32 (fp, fn);
+ if (header.magic != _MAGIC)
+ {
+ endian = MO_LITTLE_ENDIAN;
+ seek32 (fp, fn, 0L);
+ header.magic = read32 (fp, fn);
+ if (header.magic != _MAGIC)
+ {
+ unrecognised:
+ error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"),
+ fn);
+ }
+ }
+
+ /* Fill the structure describing the header. */
+ header.revision = read32 (fp, fn);
+ if (header.revision != MO_REVISION_NUMBER)
+ goto unrecognised;
+ header.nstrings = read32 (fp, fn);
+ header.orig_tab_offset = read32 (fp, fn);
+ header.trans_tab_offset = read32 (fp, fn);
+ header.hash_tab_size = read32 (fp, fn);
+ header.hash_tab_offset = read32 (fp, fn);
+
+ for (j = 0; j < header.nstrings; ++j)
+ {
+ static lex_pos_ty pos = { __FILE__, __LINE__ };
+ message_ty *mp;
+ char *msgid;
+ size_t msgid_len;
+ char *msgstr;
+ size_t msgstr_len;
+
+ /* Read the msgid. */
+ msgid = string32 (fp, fn, header.orig_tab_offset + j * 8, &msgid_len);
+
+ /* Read the msgstr. */
+ msgstr = string32 (fp, fn, header.trans_tab_offset + j * 8, &msgstr_len);
+
+ mp = message_alloc (msgid,
+ (strlen (msgid) + 1 < msgid_len
+ ? msgid + strlen (msgid) + 1
+ : NULL),
+ msgstr, msgstr_len, &pos);
+ message_list_append (mlp, mp);
+ }
+
+ if (fp != stdin)
+ fclose (fp);
+}
--- /dev/null
+/* Reading binary .mo files.
+ Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, April 1995.
+
+ 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 2, 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, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _READ_MO_H
+#define _READ_MO_H
+
+#include "message.h"
+
+/* Reads an existing .mo file and adds the messages to mlp. */
+extern void read_mo_file PARAMS ((message_list_ty *mlp, const char *fn));
+
+#endif /* _READ_MO_H */