+2001-04-29 Bruno Haible <haible@clisp.cons.org>
+
+ * POTFILES.in: Add src/read-po.c.
+
2001-04-28 Bruno Haible <haible@clisp.cons.org>
* POTFILES.in: Add src/po-charset.c.
src/po-lex.h
src/po-lex.c
src/po.c
+src/read-po.c
src/write-po.c
src/xget-lex.c
src/xgettext.c
+2001-04-29 Bruno Haible <haible@clisp.cons.org>
+
+ * read-po.h: New file.
+ * read-po.c: New file, extracted from msgmerge.c.
+ * msgmerge.c: Don't include string.h. Include read-po.h instead.
+ (merge_class_ty, line_comment, merge_constructor, merge_destructor,
+ merge_directive_domain, merge_directive_message, merge_parse_brief,
+ merge_parse_debrief, merge_comment, merge_comment_dot,
+ merge_comment_special, merge_comment_filepos, grammar): Move out to
+ read-po.c.
+ (compendium, merge): Call read_po_file() instead of grammar().
+ * Makefile.am (noinst_HEADERS): Add read-po.h.
+ (msgmerge_SOURCES): Add read-po.c.
+ * FILES: Update.
+
2001-04-28 Bruno Haible <haible@clisp.cons.org>
* msgcmp.c (usage): Restructure usage message. Talk about ref.pot, not
po.c
Top-level parser functions and callbacks.
+read-po.h
+read-po.c
+ Reading of a PO file, returning a list-of-messages.
+
msgfmt.c Main source for the 'msgfmt' program.
msgcmp.c Main source for the 'msgcmp' program.
msgcomm.c Main source for the 'msgcomm' program.
bin_PROGRAMS = gettext ngettext msgcmp msgfmt msgmerge msgunfmt xgettext msgcomm
noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-charset.h po-lex.h \
-po.h open-po.h str-list.h write-po.h xget-lex.h dir-list.h po-gram-gen.h \
-po-hash-gen.h
+po.h open-po.h read-po.h str-list.h write-po.h xget-lex.h dir-list.h \
+po-gram-gen.h po-hash-gen.h
EXTRA_DIST = FILES
msgfmt_SOURCES = msgfmt.c open-po.c po-gram-gen.y po-hash-gen.y po-charset.c \
po-lex.c po.c str-list.c message.c dir-list.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 str-list.c dir-list.c write-po.c
+po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c write-po.c
msgunfmt_SOURCES = message.c msgunfmt.c str-list.c write-po.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 xget-lex.c xgettext.c dir-list.c \
use good data hiding and encapsulation practices, an object
oriented approach has been taken. An object instance is allocated,
and all actions resulting from the parse will be through
- invokations of method functions of that object. */
+ invocations of method functions of that object. */
static po_method_ty compare_methods =
{
use good data hiding and encapsulation practices, an object
oriented approach has been taken. An object instance is allocated,
and all actions resulting from the parse will be through
- invokations of method functions of that object. */
+ invocations of method functions of that object. */
static po_method_ty format_methods =
{
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <locale.h>
#include "dir-list.h"
#include "error.h"
#include "message.h"
+#include "read-po.h"
#include "write-po.h"
-#include <system.h>
+#include "system.h"
#include "libgettext.h"
#include "po.h"
#define _(str) gettext (str)
-/* This structure defines a derived class of the po_ty class. (See
- po.h for an explanation.) */
-typedef struct merge_class_ty merge_class_ty;
-struct merge_class_ty
-{
- /* inherited instance variables, etc */
- PO_BASE_TY
-
- /* Name of domain we are currently examining. */
- char *domain;
-
- /* List of domains already appeared in the current file. */
- string_list_ty *domain_list;
-
- /* List of messages already appeared in the current file. */
- message_list_ty *mlp;
-
- /* Accumulate comments for next message directive */
- string_list_ty *comment;
- string_list_ty *comment_dot;
-
- /* Flags transported in special comments. */
- int is_fuzzy;
- enum is_c_format is_c_format;
- enum is_wrap do_wrap;
-
- /* Accumulate filepos comments for the next message directive. */
- size_t filepos_count;
- lex_pos_ty *filepos;
-};
-
-
/* String containing name the program is called with. */
const char *program_name;
/* Verbosity level. */
static int verbosity_level;
-/* If nonzero, remember comments for file name and line number for each
- msgid, if present in the reference input. Defaults to true. */
-static int line_comment = 1;
-
/* Force output of PO file even if empty. */
static int force_po;
/* Prototypes for local functions. */
static void usage PARAMS ((int __status));
static void error_print PARAMS ((void));
-static void merge_constructor PARAMS ((po_ty *__that));
-static void merge_destructor PARAMS ((po_ty *__that));
-static void merge_directive_domain PARAMS ((po_ty *__that, char *__name));
-static void merge_directive_message PARAMS ((po_ty *__that, char *__msgid,
- lex_pos_ty *__msgid_pos,
- char *__msgid_plural,
- char *__msgstr,
- size_t __msgstr_len,
- lex_pos_ty *__msgstr_pos));
-static void merge_parse_brief PARAMS ((po_ty *__that));
-static void merge_parse_debrief PARAMS ((po_ty *__that));
-static void merge_comment PARAMS ((po_ty *__that, const char *__s));
-static void merge_comment_dot PARAMS ((po_ty *__that, const char *__s));
-static void merge_comment_special PARAMS ((po_ty *__that, const char *__s));
-static void merge_comment_filepos PARAMS ((po_ty *__that, const char *__name,
- int __line));
-static message_list_ty *grammar PARAMS ((const char *__filename));
static message_list_ty *merge PARAMS ((const char *__fn1, const char *__fn2));
static void compendium PARAMS ((const char *__filename));
{
message_list_ty *mlp;
- mlp = grammar (filename);
+ mlp = read_po_file (filename);
if (!compendiums)
compendiums = message_list_list_alloc ();
message_list_list_append (compendiums, mlp);
}
-static void
-merge_constructor (that)
- po_ty *that;
-{
- merge_class_ty *this = (merge_class_ty *) that;
-
- this->mlp = message_list_alloc ();
- this->domain = MESSAGE_DOMAIN_DEFAULT;
- this->domain_list = string_list_alloc ();
- this->comment = NULL;
- this->comment_dot = NULL;
- this->filepos_count = 0;
- this->filepos = NULL;
- this->is_fuzzy = 0;
- this->is_c_format = undecided;
- this->do_wrap = undecided;
-}
-
-
-static void
-merge_destructor (that)
- po_ty *that;
-{
- merge_class_ty *this = (merge_class_ty *) that;
- size_t j;
-
- string_list_free (this->domain_list);
- /* Do not free this->mlp. */
- if (this->comment != NULL)
- string_list_free (this->comment);
- if (this->comment_dot != NULL)
- string_list_free (this->comment_dot);
- for (j = 0; j < this->filepos_count; ++j)
- free (this->filepos[j].file_name);
- if (this->filepos != NULL)
- free (this->filepos);
-}
-
-
-static void
-merge_directive_domain (that, name)
- po_ty *that;
- char *name;
-{
- size_t j;
-
- merge_class_ty *this = (merge_class_ty *) that;
- /* Override current domain name. Don't free memory. */
- this->domain = name;
-
- /* If there are accumulated comments, throw them away, they are
- probably part of the file header, or about the domain directive,
- and will be unrelated to the next message. */
- if (this->comment != NULL)
- {
- string_list_free (this->comment);
- this->comment = NULL;
- }
- if (this->comment_dot != NULL)
- {
- string_list_free (this->comment_dot);
- this->comment_dot = NULL;
- }
- for (j = 0; j < this->filepos_count; ++j)
- free (this->filepos[j].file_name);
- if (this->filepos != NULL)
- free (this->filepos);
- this->filepos_count = 0;
- this->filepos = NULL;
-}
-
-
-static void
-merge_directive_message (that, msgid, msgid_pos, msgid_plural,
- msgstr, msgstr_len, msgstr_pos)
- po_ty *that;
- char *msgid;
- lex_pos_ty *msgid_pos;
- char *msgid_plural;
- char *msgstr;
- size_t msgstr_len;
- lex_pos_ty *msgstr_pos;
-{
- merge_class_ty *this = (merge_class_ty *) that;
- message_ty *mp;
- message_variant_ty *mvp;
- size_t j;
-
- /* Remember the domain names for later. */
- string_list_append_unique (this->domain_list, this->domain);
-
- /* See if this message ID has been seen before. */
- mp = message_list_search (this->mlp, msgid);
- if (mp)
- free (msgid);
- else
- {
- mp = message_alloc (msgid, msgid_plural);
- message_list_append (this->mlp, mp);
- }
-
- /* Add the accumulated comments to the message. Clear the
- accumulation in preparation for the next message. */
- if (this->comment != NULL)
- {
- for (j = 0; j < this->comment->nitems; ++j)
- message_comment_append (mp, this->comment->item[j]);
- string_list_free (this->comment);
- this->comment = NULL;
- }
- if (this->comment_dot != NULL)
- {
- for (j = 0; j < this->comment_dot->nitems; ++j)
- message_comment_dot_append (mp, this->comment_dot->item[j]);
- string_list_free (this->comment_dot);
- this->comment_dot = NULL;
- }
- for (j = 0; j < this->filepos_count; ++j)
- {
- lex_pos_ty *pp;
-
- pp = &this->filepos[j];
- message_comment_filepos (mp, pp->file_name, pp->line_number);
- free (pp->file_name);
- }
- mp->is_fuzzy = this->is_fuzzy;
- mp->is_c_format = this->is_c_format;
- mp->do_wrap = this->do_wrap;
-
- if (this->filepos != NULL)
- free (this->filepos);
- this->filepos_count = 0;
- this->filepos = NULL;
- this->is_fuzzy = 0;
- this->is_c_format = undecided;
- this->do_wrap = undecided;
-
- /* See if this domain has been seen for this message ID. */
- mvp = message_variant_search (mp, this->domain);
- if (mvp)
- {
- po_gram_error_at_line (msgid_pos, _("duplicate message definition"));
- po_gram_error_at_line (&mvp->pos, _("\
-...this is the location of the first definition"));
- free (msgstr);
- }
- else
- message_variant_append (mp, this->domain, msgstr, msgstr_len, msgstr_pos);
-}
-
-
-static void
-merge_parse_brief (that)
- po_ty *that;
-{
- po_lex_pass_comments (1);
-}
-
-
-static void
-merge_parse_debrief (that)
- po_ty *that;
-{
- merge_class_ty *this = (merge_class_ty *) that;
- message_list_ty *mlp = this->mlp;
- size_t j;
-
- /* For each domain in the used-domain-list, make sure each message
- defines a msgstr in that domain. */
- for (j = 0; j < this->domain_list->nitems; ++j)
- {
- const char *domain_name;
- size_t k;
-
- domain_name = this->domain_list->item[j];
- for (k = 0; k < mlp->nitems; ++k)
- {
- const message_ty *mp;
- size_t m;
-
- mp = mlp->item[k];
- for (m = 0; m < mp->variant_count; ++m)
- {
- message_variant_ty *mvp;
-
- mvp = &mp->variant[m];
- if (strcmp (domain_name, mvp->domain) == 0)
- break;
- }
- if (m >= mp->variant_count)
- po_gram_error_at_line (&mp->variant[0].pos, _("\
-this message has no definition in the \"%s\" domain"), domain_name);
- }
- }
-}
-
-
-static void
-merge_comment (that, s)
- po_ty *that;
- const char *s;
-{
- merge_class_ty *this = (merge_class_ty *) that;
-
- if (this->comment == NULL)
- this->comment = string_list_alloc ();
- string_list_append (this->comment, s);
-}
-
-
-static void
-merge_comment_dot (that, s)
- po_ty *that;
- const char *s;
-{
- merge_class_ty *this = (merge_class_ty *) that;
-
- if (this->comment_dot == NULL)
- this->comment_dot = string_list_alloc ();
- string_list_append (this->comment_dot, s);
-}
-
-
-static void
-merge_comment_special (that, s)
- po_ty *that;
- const char *s;
-{
- merge_class_ty *this = (merge_class_ty *) that;
-
- if (strstr (s, "fuzzy") != NULL)
- this->is_fuzzy = 1;
-
- this->is_c_format = parse_c_format_description_string (s);
- this->do_wrap = parse_c_width_description_string (s);
-}
-
-
-static void
-merge_comment_filepos (that, name, line)
- po_ty *that;
- const char *name;
- int line;
-{
- merge_class_ty *this = (merge_class_ty *) that;
- size_t nbytes;
- lex_pos_ty *pp;
-
- if (!line_comment)
- return;
- nbytes = (this->filepos_count + 1) * sizeof (this->filepos[0]);
- this->filepos = xrealloc (this->filepos, nbytes);
- pp = &this->filepos[this->filepos_count++];
- pp->file_name = xstrdup (name);
- pp->line_number = line;
-}
-
-
-/* So that the one parser can be used for multiple programs, and also
- use good data hiding and encapsulation practices, an object
- oriented approach has been taken. An object instance is allocated,
- and all actions resulting from the parse will be through
- invokations of method functions of that object. */
-
-static po_method_ty merge_methods =
-{
- sizeof (merge_class_ty),
- merge_constructor,
- merge_destructor,
- merge_directive_domain,
- merge_directive_message,
- merge_parse_brief,
- merge_parse_debrief,
- merge_comment,
- merge_comment_dot,
- merge_comment_filepos,
- merge_comment_special
-};
-
-
-static message_list_ty *
-grammar (filename)
- const char *filename;
-{
- po_ty *pop;
- message_list_ty *mlp;
-
- pop = po_alloc (&merge_methods);
- po_lex_pass_obsolete_entries (1);
- po_scan (pop, filename);
- mlp = ((merge_class_ty *) pop)->mlp;
- po_free (pop);
- return mlp;
-}
-
-
#define DOT_FREQUENCE 10
static message_list_ty *
merged = fuzzied = missing = obsolete = 0;
/* This is the definitions file, created by a human. */
- def = grammar (fn1);
+ def = read_po_file (fn1);
/* Glue the definition file and the compendiums together, to define
the set of places to look for message definitions. */
/* This is the references file, created by groping the sources with
the xgettext program. */
- ref = grammar (fn2);
+ ref = read_po_file (fn2);
result = message_list_alloc ();
--- /dev/null
+/* Reading PO files.
+ Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+ This file was written by Peter Miller <millerp@canb.auug.org.au>
+
+ 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 <stdlib.h>
+#include <string.h>
+
+#include "po.h"
+#include "read-po.h"
+#include "system.h"
+#include "libgettext.h"
+
+#define _(str) gettext (str)
+
+
+/* If nonzero, remember comments for file name and line number for each
+ msgid, if present in the reference input. Defaults to true. */
+int line_comment = 1;
+
+
+/* This structure defines a derived class of the po_ty class. (See
+ po.h for an explanation.) */
+typedef struct readall_class_ty readall_class_ty;
+struct readall_class_ty
+{
+ /* inherited instance variables, etc. */
+ PO_BASE_TY
+
+ /* Name of domain we are currently examining. */
+ char *domain;
+
+ /* List of domains already appeared in the current file. */
+ string_list_ty *domain_list;
+
+ /* List of messages already appeared in the current file. */
+ message_list_ty *mlp;
+
+ /* Accumulate comments for next message directive. */
+ string_list_ty *comment;
+ string_list_ty *comment_dot;
+
+ /* Flags transported in special comments. */
+ int is_fuzzy;
+ enum is_c_format is_c_format;
+ enum is_wrap do_wrap;
+
+ /* Accumulate filepos comments for the next message directive. */
+ size_t filepos_count;
+ lex_pos_ty *filepos;
+};
+
+
+/* Prototypes for local functions. */
+static void readall_constructor PARAMS ((po_ty *that));
+static void readall_destructor PARAMS ((po_ty *that));
+static void readall_directive_domain PARAMS ((po_ty *that, char *name));
+static void readall_directive_message PARAMS ((po_ty *that, char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos));
+static void readall_parse_brief PARAMS ((po_ty *that));
+static void readall_parse_debrief PARAMS ((po_ty *that));
+static void readall_comment PARAMS ((po_ty *that, const char *s));
+static void readall_comment_dot PARAMS ((po_ty *that, const char *s));
+static void readall_comment_special PARAMS ((po_ty *that, const char *s));
+static void readall_comment_filepos PARAMS ((po_ty *that, const char *name,
+ int line));
+
+
+static void
+readall_constructor (that)
+ po_ty *that;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+
+ this->mlp = message_list_alloc ();
+ this->domain = MESSAGE_DOMAIN_DEFAULT;
+ this->domain_list = string_list_alloc ();
+ this->comment = NULL;
+ this->comment_dot = NULL;
+ this->filepos_count = 0;
+ this->filepos = NULL;
+ this->is_fuzzy = 0;
+ this->is_c_format = undecided;
+ this->do_wrap = undecided;
+}
+
+
+static void
+readall_destructor (that)
+ po_ty *that;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+ size_t j;
+
+ string_list_free (this->domain_list);
+ /* Do not free this->mlp. */
+ if (this->comment != NULL)
+ string_list_free (this->comment);
+ if (this->comment_dot != NULL)
+ string_list_free (this->comment_dot);
+ for (j = 0; j < this->filepos_count; ++j)
+ free (this->filepos[j].file_name);
+ if (this->filepos != NULL)
+ free (this->filepos);
+}
+
+
+static void
+readall_directive_domain (that, name)
+ po_ty *that;
+ char *name;
+{
+ size_t j;
+
+ readall_class_ty *this = (readall_class_ty *) that;
+ /* Override current domain name. Don't free memory. */
+ this->domain = name;
+
+ /* If there are accumulated comments, throw them away, they are
+ probably part of the file header, or about the domain directive,
+ and will be unrelated to the next message. */
+ if (this->comment != NULL)
+ {
+ string_list_free (this->comment);
+ this->comment = NULL;
+ }
+ if (this->comment_dot != NULL)
+ {
+ string_list_free (this->comment_dot);
+ this->comment_dot = NULL;
+ }
+ for (j = 0; j < this->filepos_count; ++j)
+ free (this->filepos[j].file_name);
+ if (this->filepos != NULL)
+ free (this->filepos);
+ this->filepos_count = 0;
+ this->filepos = NULL;
+}
+
+
+static void
+readall_directive_message (that, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos)
+ po_ty *that;
+ char *msgid;
+ lex_pos_ty *msgid_pos;
+ char *msgid_plural;
+ char *msgstr;
+ size_t msgstr_len;
+ lex_pos_ty *msgstr_pos;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+ message_ty *mp;
+ message_variant_ty *mvp;
+ size_t j;
+
+ /* Remember the domain names for later. */
+ string_list_append_unique (this->domain_list, this->domain);
+
+ /* See if this message ID has been seen before. */
+ mp = message_list_search (this->mlp, msgid);
+ if (mp)
+ free (msgid);
+ else
+ {
+ mp = message_alloc (msgid, msgid_plural);
+ message_list_append (this->mlp, mp);
+ }
+
+ /* Add the accumulated comments to the message. Clear the
+ accumulation in preparation for the next message. */
+ if (this->comment != NULL)
+ {
+ for (j = 0; j < this->comment->nitems; ++j)
+ message_comment_append (mp, this->comment->item[j]);
+ string_list_free (this->comment);
+ this->comment = NULL;
+ }
+ if (this->comment_dot != NULL)
+ {
+ for (j = 0; j < this->comment_dot->nitems; ++j)
+ message_comment_dot_append (mp, this->comment_dot->item[j]);
+ string_list_free (this->comment_dot);
+ this->comment_dot = NULL;
+ }
+ for (j = 0; j < this->filepos_count; ++j)
+ {
+ lex_pos_ty *pp;
+
+ pp = &this->filepos[j];
+ message_comment_filepos (mp, pp->file_name, pp->line_number);
+ free (pp->file_name);
+ }
+ mp->is_fuzzy = this->is_fuzzy;
+ mp->is_c_format = this->is_c_format;
+ mp->do_wrap = this->do_wrap;
+
+ if (this->filepos != NULL)
+ free (this->filepos);
+ this->filepos_count = 0;
+ this->filepos = NULL;
+ this->is_fuzzy = 0;
+ this->is_c_format = undecided;
+ this->do_wrap = undecided;
+
+ /* See if this domain has been seen for this message ID. */
+ mvp = message_variant_search (mp, this->domain);
+ if (mvp)
+ {
+ po_gram_error_at_line (msgid_pos, _("duplicate message definition"));
+ po_gram_error_at_line (&mvp->pos, _("\
+...this is the location of the first definition"));
+ free (msgstr);
+ }
+ else
+ message_variant_append (mp, this->domain, msgstr, msgstr_len, msgstr_pos);
+}
+
+
+static void
+readall_parse_brief (that)
+ po_ty *that;
+{
+ po_lex_pass_comments (1);
+}
+
+
+static void
+readall_parse_debrief (that)
+ po_ty *that;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+ message_list_ty *mlp = this->mlp;
+ size_t j;
+
+ /* For each domain in the used-domain-list, make sure each message
+ defines a msgstr in that domain. */
+ for (j = 0; j < this->domain_list->nitems; ++j)
+ {
+ const char *domain_name;
+ size_t k;
+
+ domain_name = this->domain_list->item[j];
+ for (k = 0; k < mlp->nitems; ++k)
+ {
+ const message_ty *mp;
+ size_t m;
+
+ mp = mlp->item[k];
+ for (m = 0; m < mp->variant_count; ++m)
+ {
+ message_variant_ty *mvp;
+
+ mvp = &mp->variant[m];
+ if (strcmp (domain_name, mvp->domain) == 0)
+ break;
+ }
+ if (m >= mp->variant_count)
+ po_gram_error_at_line (&mp->variant[0].pos, _("\
+this message has no definition in the \"%s\" domain"), domain_name);
+ }
+ }
+}
+
+
+static void
+readall_comment (that, s)
+ po_ty *that;
+ const char *s;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+
+ if (this->comment == NULL)
+ this->comment = string_list_alloc ();
+ string_list_append (this->comment, s);
+}
+
+
+static void
+readall_comment_dot (that, s)
+ po_ty *that;
+ const char *s;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+
+ if (this->comment_dot == NULL)
+ this->comment_dot = string_list_alloc ();
+ string_list_append (this->comment_dot, s);
+}
+
+
+static void
+readall_comment_special (that, s)
+ po_ty *that;
+ const char *s;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+
+ if (strstr (s, "fuzzy") != NULL)
+ this->is_fuzzy = 1;
+
+ this->is_c_format = parse_c_format_description_string (s);
+ this->do_wrap = parse_c_width_description_string (s);
+}
+
+
+static void
+readall_comment_filepos (that, name, line)
+ po_ty *that;
+ const char *name;
+ int line;
+{
+ readall_class_ty *this = (readall_class_ty *) that;
+ size_t nbytes;
+ lex_pos_ty *pp;
+
+ if (!line_comment)
+ return;
+ nbytes = (this->filepos_count + 1) * sizeof (this->filepos[0]);
+ this->filepos = xrealloc (this->filepos, nbytes);
+ pp = &this->filepos[this->filepos_count++];
+ pp->file_name = xstrdup (name);
+ pp->line_number = line;
+}
+
+
+/* So that the one parser can be used for multiple programs, and also
+ use good data hiding and encapsulation practices, an object
+ oriented approach has been taken. An object instance is allocated,
+ and all actions resulting from the parse will be through
+ invocations of method functions of that object. */
+
+static po_method_ty readall_methods =
+{
+ sizeof (readall_class_ty),
+ readall_constructor,
+ readall_destructor,
+ readall_directive_domain,
+ readall_directive_message,
+ readall_parse_brief,
+ readall_parse_debrief,
+ readall_comment,
+ readall_comment_dot,
+ readall_comment_filepos,
+ readall_comment_special
+};
+
+
+message_list_ty *
+read_po_file (filename)
+ const char *filename;
+{
+ po_ty *pop;
+ message_list_ty *mlp;
+
+ pop = po_alloc (&readall_methods);
+ po_lex_pass_obsolete_entries (1);
+ po_scan (pop, filename);
+ mlp = ((readall_class_ty *) pop)->mlp;
+ po_free (pop);
+ return mlp;
+}
--- /dev/null
+/* Reading PO files.
+ Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+ This file was written by Bruno Haible <haible@clisp.cons.org>.
+
+ 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_PO_H
+#define _READ_PO_H
+
+#include "message.h"
+
+/* If nonzero, remember comments for file name and line number for each
+ msgid, if present in the reference input. Defaults to true. */
+extern int line_comment;
+
+/* Read the input file with the name INPUT_NAME. The ending .po is added
+ if necessary. If INPUT_NAME is not an absolute file name and the file is
+ not found, the list of directories in "dir-list.h" is searched. Returns
+ a list of messages. */
+extern message_list_ty *read_po_file PARAMS ((const char *input_name));
+
+#endif /* _READ_PO_H */