From: Bruno Haible Date: Thu, 6 Sep 2001 00:18:00 +0000 (+0000) Subject: Split off the .mo file reader from msgunfmt. X-Git-Tag: v0.11~516 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d0a341417ec46961adf2649faef50f79b087029;p=thirdparty%2Fgettext.git Split off the .mo file reader from msgunfmt. --- diff --git a/src/ChangeLog b/src/ChangeLog index e1ea0ca49..0281874c1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2001-09-02 Bruno Haible + + * 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 * msgfmt.h (struct hashtable_entry): Remove type. diff --git a/src/Makefile.am b/src/Makefile.am index 8586a9f7a..8d9f3c947 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ msgcat msgcomm msgconv msgen msgexec msggrep msguniq 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 @@ -51,7 +51,8 @@ format.c format-c.c format-java.c format-lisp.c format-python.c format-ycp.c 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 \ diff --git a/src/msgunfmt.c b/src/msgunfmt.c index 4e7f36189..c44aba400 100644 --- a/src/msgunfmt.c +++ b/src/msgunfmt.c @@ -20,34 +20,21 @@ # include #endif -#include #include #include -#include -#include #include #include -#include "hash.h" - #include "error.h" #include "progname.h" -#include "getline.h" -#include "printf.h" -#include - -#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; @@ -69,20 +56,9 @@ static const struct option long_options[] = }; -/* 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 @@ -185,15 +161,15 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ 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; @@ -275,179 +251,3 @@ Informative output:\n\ 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; -} diff --git a/src/read-mo.c b/src/read-mo.c new file mode 100644 index 000000000..0d7bf1825 --- /dev/null +++ b/src/read-mo.c @@ -0,0 +1,224 @@ +/* Reading binary .mo files. + Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. + Written by Ulrich Drepper , 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 +#endif + +#include "read-mo.h" + +#include +#include +#include +#include + +/* 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); +} diff --git a/src/read-mo.h b/src/read-mo.h new file mode 100644 index 000000000..de732862a --- /dev/null +++ b/src/read-mo.h @@ -0,0 +1,27 @@ +/* Reading binary .mo files. + Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. + Written by Ulrich Drepper , 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 */