+2003-04-13 Bruno Haible <bruno@clisp.org>
+
+ Unify three PO file parsers.
+ * read-po-abstract.h: Renamed from po.h.
+ (abstract_po_reader_class_ty): Renamed from po_method_ty.
+ (abstract_po_reader_ty): Renamed from po_ty.
+ (ABSTRACT_PO_READER_TY): Renamed from PO_BASE_TY.
+ (po_reader_alloc): Renamed from po_alloc.
+ (po_reader_free): Renamed from po_free.
+ * read-po-abstract.c: Renamed from po.c.
+ (po_reader_alloc): Renamed from po_alloc.
+ (po_reader_free): Renamed from po_free.
+ (call_parse_brief): Renamed from po_parse_brief.
+ (call_parse_debrief): Renamed from po_parse_debrief.
+ (call_directive_domain): Renamed from po_directive_domain.
+ (call_directive_message): Renamed from po_directive_message.
+ (call_comment): Renamed from po_comment.
+ (call_comment_dot): Renamed from po_comment_dot.
+ (call_comment_filepos): Renamed from po_comment_filepos.
+ (call_comment_special): Renamed from po_comment_special.
+ * read-po.h: Include read-po-abstract.h.
+ (default_po_reader_class_ty, default_po_reader_ty): New types.
+ (ABSTRACT_PO_READER_TY): New macro.
+ (default_constructor, default_destructor, default_parse_brief,
+ default_parse_debrief, default_directive_domain,
+ default_directive_message, default_comment, default_comment_dot,
+ default_comment_filepos, default_comment_special, default_set_domain,
+ default_add_message): New declarations.
+ (default_po_reader_alloc): New declaration.
+ * read-po.c (default_po_reader_ty): Renamed from readall_class_ty.
+ Add fields handle_comments, handle_filepos_comments,
+ allow_domain_directives, allow_duplicates,
+ allow_duplicates_if_same_msgstr.
+ (call_set_domain, call_add_message, call_frob_new_message): New
+ functions.
+ (default_constructor): Renamed from readall_constructor. Don't set
+ this->mdlp and this->mlp.
+ (default_destructor): Renamed from readall_destructor.
+ (default_parse_brief): Renamed from readall_parse_brief.
+ (default_parse_debrief): New function.
+ (default_copy_comment_state, default_reset_comment_state): New
+ functions.
+ (default_directive_domain): Renamed from readall_directive_domain.
+ Call set_domain method.
+ (default_directive_message): Renamed from readall_directive_message.
+ Call add_message method.
+ (default_comment): Renamed from readall_comment.
+ (default_comment_dot): Renamed from readall_comment_dot.
+ (default_comment_filepos): Renamed from readall_comment_filepos.
+ (default_comment_special): Renamed from readall_comment_special.
+ (default_set_domain, default_add_message): New functions.
+ (default_methods): Renamed from readall_methods.
+ (default_po_reader_alloc): New function.
+ (read_po, read_po_file): Update.
+ * msgfmt.c: Include read-po.h instead of po.h.
+ (msgfmt_po_reader_ty): Renamed from msgfmt_class_ty. Inherit
+ from default_po_reader_ty.
+ (main): Drop po_lex_pass_comments call, done by default_parse_brief.
+ (msgfmt_constructor): Renamed from format_constructor. Call superclass
+ function.
+ (msgfmt_parse_debrief): Renamed from format_debrief. Call superclass
+ function.
+ (format_directive_domain): Remove function.
+ (msgfmt_set_domain): New function.
+ (format_directive_message): Remove function.
+ (msgfmt_add_message, msgfmt_frob_new_message): New functions.
+ (msgfmt_comment_special): Renamed from format_comment_special.
+ (msgfmt_methods): Renamed from format_methods.
+ (read_po_file_msgfmt): Renamed from read_po_file.
+ * x-po.c: Include read-po.h instead of po.h.
+ (extract_class_ty, extract_constructor, extract_directive_domain,
+ extract_directive_message, extract_parse_brief, extract_comment,
+ extract_comment_dot, extract_comment_filepos, extract_comment_special):
+ Remove functions.
+ (extract_add_message): New function.
+ (extract_methods): Update.
+ (extract_po): Update.
+ * xgettext.c: Include read-po-abstract.h instead of po.h.
+ (exclude_directive_domain, exclude_directive_message, exclude_methods,
+ read_exclusion_file): Update.
+ * msgcmp.c: Don't include po.h.
+ * msgmerge.c: Likewise.
+ * po-gram-gen.y: Include read-po-abstract.h instead of po.h.
+ * po-hash-gen.y: Likewise.
+ (po_parse_comment_filepos): Renamed from po_hash.
+ * po-hash.h (po_parse_comment_filepos): Renamed from po_hash.
+ * Makefile.am (noinst_HEADERS): Remove po.h, add read-po-abstract.h.
+ (COMMON_SOURCE): Remove po.c, add read-po-abstract.c.
+ * Makefile.msvc (OBJECTS): Remove po.obj, add read-po-abstract.obj.
+ (read-po-abstract.obj): Renamed from po.obj.
+ * Makefile.vms (OBJECTS): Remove po.obj, add read-po-abstract.obj.
+ (read-po-abstract.obj): Renamed from po.obj.
+
2003-04-13 Bruno Haible <bruno@clisp.org>
* write-po.h (message_print_comment, message_print_comment_dot,
Short description of the source files
=====================================
-1)
-gettext.c Source for the 'gettext' program.
-ngettext.c Source for the 'ngettext' program.
-
-2) The msg* and xgettext programs.
+The msg* and xgettext programs.
Bottom-up structure:
| po-lex.c
| Lexical analysis of PO files.
|
-| po.h
+| read-po-abstract.h
| po-hash.h
| po-hash-gen.y
| po-gram.h
| po-gram-gen.y
-| po.c
+| read-po-abstract.c
| Parsing of PO files.
-| po.h
+| read-po-abstract.h
| General parser structure.
| po-hash.h
| po-hash-gen.y
| po-gram.h
| po-gram-gen.y
| Parsing of PO files, based on po-lex.{h,c}.
-| po.c
+| read-po-abstract.c
| Top-level parser functions and callbacks.
|
| read-po.h
include_HEADERS = gettext-po.h
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-gram-gen2.h po-hash-gen.h msgl-charset.h msgl-equal.h \
-msgl-iconv.h msgl-ascii.h msgl-cat.h msgl-english.h msgfmt.h msgunfmt.h \
-read-mo.h write-mo.h read-java.h write-java.h read-tcl.h write-tcl.h \
-po-time.h plural-table.h format.h xgettext.h x-c.h x-po.h x-python.h x-lisp.h \
-x-elisp.h x-librep.h x-smalltalk.h x-java.h x-awk.h x-ycp.h x-tcl.h x-php.h \
-x-rst.h x-glade.h
+open-po.h read-po-abstract.h read-po.h str-list.h write-po.h dir-list.h \
+file-list.h po-gram-gen.h po-gram-gen2.h po-hash-gen.h msgl-charset.h \
+msgl-equal.h msgl-iconv.h msgl-ascii.h msgl-cat.h msgl-english.h msgfmt.h \
+msgunfmt.h read-mo.h write-mo.h read-java.h write-java.h read-tcl.h \
+write-tcl.h po-time.h plural-table.h format.h xgettext.h x-c.h x-po.h \
+x-python.h x-lisp.h x-elisp.h x-librep.h x-smalltalk.h x-java.h x-awk.h \
+x-ycp.h x-tcl.h x-php.h x-rst.h x-glade.h
EXTRA_DIST += FILES project-id ChangeLog.0
# All programs deal with message lists.
# All programs must read PO files. (msgunfmt also, for read-java.c.)
# message.c -> str-list.c.
-# (po.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> str-list.c.
-# (po.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> open-po.c -> dir-list.c -> str-list.c.
-# (po.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> po-charset.c.
-# (po.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> message.c -> str-list.c.
+# (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> str-list.c.
+# (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> open-po.c -> dir-list.c -> str-list.c.
+# (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> po-charset.c.
+# (read-po-abstract.c <--> po-hash-gen.y <--> po-gram-gen.y <--> po-lex.c) -> message.c -> str-list.c.
COMMON_SOURCE = message.c \
-po.c po-lex.c po-gram-gen.y po-hash-gen.y po-charset.c \
+read-po-abstract.c po-lex.c po-gram-gen.y po-hash-gen.y po-charset.c \
open-po.c dir-list.c str-list.c
# xgettext and msgfmt deal with format strings.
OBJECTS = \
message.obj \
- po.obj \
+ read-po-abstract.obj \
po-lex.obj \
po-gram-gen.obj \
po-hash-gen.obj \
message.obj : message.c
$(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c message.c
-po.obj : po.c
- $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c po.c
+read-po-abstract.obj : read-po-abstract.c
+ $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c read-po-abstract.c
po-lex.obj : po-lex.c
$(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c po-lex.c
OBJECTS = \
message.obj, \
- po.obj, \
+ read-po-abstract.obj, \
po-lex.obj, \
po-gram-gen.obj, \
po-hash-gen.obj, \
message.obj : message.c
$(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) message.c
-po.obj : po.c
- $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) po.c
+read-po-abstract.obj : read-po-abstract.c
+ $(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) read-po-abstract.c
po-lex.obj : po-lex.c
$(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) po-lex.c
#include "message.h"
#include "exit.h"
#include "read-po.h"
-#include "po.h"
#include "msgl-iconv.h"
#include "strstr.h"
#include "strcase.h"
#include "gettext.h"
#include "message.h"
-#include "po.h"
+#include "read-po.h"
#define _(str) gettext (str)
# define USE_SIGINFO 1
#endif
-/* This structure defines a derived class of the po_ty class. (See
- po.h for an explanation.) */
-typedef struct msgfmt_class_ty msgfmt_class_ty;
-struct msgfmt_class_ty
-{
- /* inherited instance variables, etc */
- PO_BASE_TY
-
- bool is_fuzzy;
- enum is_format is_format[NFORMATS];
- enum is_wrap do_wrap;
-
- bool has_header_entry;
- bool has_nonfuzzy_header_entry;
-};
-
/* Contains exit status for case in which no premature exit occurs. */
static int exit_status;
static struct msg_domain *new_domain (const char *name, const char *file_name);
static bool is_nonobsolete (const message_ty *mp);
static void check_plural (message_list_ty *mlp);
-static void read_po_file (char *filename);
+static void read_po_file_msgfmt (char *filename);
int
strict_uniforum ? add_mo_suffix (output_file_name)
: output_file_name);
- /* Prepare PO file reader. We need to see the comments because inexact
- translations must be reported. */
- po_lex_pass_comments (true);
-
/* Process all given .po files. */
while (argc > optind)
{
current_domain = NULL;
/* And process the input file. */
- read_po_file (argv[optind]);
+ read_po_file_msgfmt (argv[optind]);
++optind;
}
}
-/* The rest of the file is similar to read-po.c. The differences are:
- - Comments are not stored, they are discarded right away.
+/* The rest of the file defines a subclass msgfmt_po_reader_ty of
+ default_po_reader_ty. Its particularities are:
- The header entry check is performed on-the-fly.
+ - Comments are not stored, they are discarded right away.
+ (This is achieved by setting handle_comments = false and
+ handle_filepos_comments = false.)
+ - The multi-domain handling is adapted to our domain_list.
*/
+/* This structure defines a derived class of the default_po_reader_ty class.
+ (See read-po-abstract.h for an explanation.) */
+typedef struct msgfmt_po_reader_ty msgfmt_po_reader_ty;
+struct msgfmt_po_reader_ty
+{
+ /* inherited instance variables, etc */
+ DEFAULT_PO_READER_TY
+
+ bool has_header_entry;
+ bool has_nonfuzzy_header_entry;
+};
+
+
/* Prepare for first message. */
static void
-format_constructor (po_ty *that)
+msgfmt_constructor (abstract_po_reader_ty *that)
{
- msgfmt_class_ty *this = (msgfmt_class_ty *) that;
- size_t i;
+ msgfmt_po_reader_ty *this = (msgfmt_po_reader_ty *) that;
+
+ /* Invoke superclass constructor. */
+ default_constructor (that);
- this->is_fuzzy = false;
- for (i = 0; i < NFORMATS; i++)
- this->is_format[i] = undecided;
- this->do_wrap = undecided;
this->has_header_entry = false;
this->has_nonfuzzy_header_entry = false;
}
/* Some checks after whole file is read. */
static void
-format_debrief (po_ty *that)
+msgfmt_parse_debrief (abstract_po_reader_ty *that)
{
- msgfmt_class_ty *this = (msgfmt_class_ty *) that;
+ msgfmt_po_reader_ty *this = (msgfmt_po_reader_ty *) that;
+
+ /* Invoke superclass method. */
+ default_parse_debrief (that);
/* Test whether header entry was found. */
if (check_header)
}
-/* Process `domain' directive from .po file. */
+/* Set 'domain' directive when seen in .po file. */
static void
-format_directive_domain (po_ty *pop, char *name)
+msgfmt_set_domain (default_po_reader_ty *this, char *name)
{
/* If no output file was given, we change it with each `domain'
directive. */
/* Set new domain. */
current_domain = new_domain (name, add_mo_suffix (name));
+ this->domain = current_domain->domain_name;
+ this->mlp = current_domain->mlp;
}
else
{
if (check_domain)
- error (0, 0, _("`domain %s' directive ignored"), name);
+ po_gram_error_at_line (&gram_pos,
+ _("`domain %s' directive ignored"), name);
- /* NAME was allocated in po-gram.y but is not used anywhere. */
+ /* NAME was allocated in po-gram-gen.y but is not used anywhere. */
free (name);
}
}
-/* Process `msgid'/`msgstr' pair from .po file. */
-static void
-format_directive_message (po_ty *that,
- char *msgid_string,
- lex_pos_ty *msgid_pos,
- char *msgid_plural,
- char *msgstr_string, size_t msgstr_len,
- lex_pos_ty *msgstr_pos,
- bool obsolete)
+void
+msgfmt_add_message (default_po_reader_ty *this,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ bool obsolete)
{
- msgfmt_class_ty *this = (msgfmt_class_ty *) that;
- message_ty *mp;
- size_t i;
-
/* Check whether already a domain is specified. If not, use default
domain. */
if (current_domain == NULL)
- current_domain = new_domain (MESSAGE_DOMAIN_DEFAULT,
- add_mo_suffix (MESSAGE_DOMAIN_DEFAULT));
-
- /* Duplicate checking. */
- mp = message_list_search (current_domain->mlp, msgid_string);
- if (mp)
{
- /* We give a fatal error about this, regardless whether the
- translations are equal or different. This is for consistency
- with msgmerge, msgcat and others. The user can use the
- msguniq program to get rid of duplicates. */
- po_gram_error_at_line (msgid_pos, _("duplicate message definition"));
- po_gram_error_at_line (&mp->pos, _("\
-...this is the location of the first definition"));
-
- /* We don't need the just constructed entries' parameter string
- (allocated in po-gram.y). */
- free (msgid_string);
- free (msgstr_string);
+ current_domain = new_domain (MESSAGE_DOMAIN_DEFAULT,
+ add_mo_suffix (MESSAGE_DOMAIN_DEFAULT));
+ /* Keep current_domain and this->domain synchronized. */
+ this->domain = current_domain->domain_name;
+ this->mlp = current_domain->mlp;
}
- else
+
+ /* Invoke superclass method. */
+ default_add_message (this, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos, obsolete);
+}
+
+
+static void
+msgfmt_frob_new_message (default_po_reader_ty *that, message_ty *mp,
+ const lex_pos_ty *msgid_pos,
+ const lex_pos_ty *msgstr_pos)
+{
+ msgfmt_po_reader_ty *this = (msgfmt_po_reader_ty *) that;
+
+ if (!mp->obsolete)
{
- /* Construct message to add to the list.
- Non-obsolete messages will be output.
- Obsolete message go into the list only for duplicate checking. */
- mp = message_alloc (NULL, NULL, msgstr_string, msgstr_len, msgstr_pos);
- mp->msgid = msgid_string;
- mp->msgid_plural = msgid_plural;
- mp->obsolete = obsolete;
- for (i = 0; i < NFORMATS; i++)
- mp->is_format[i] = this->is_format[i];
-
- if (!obsolete)
+ /* Don't emit untranslated entries.
+ Also don't emit fuzzy entries, unless --use-fuzzy was specified.
+ But ignore fuzziness of the header entry. */
+ if (mp->msgstr[0] == '\0'
+ || (!include_all && mp->is_fuzzy && mp->msgid[0] != '\0'))
{
- /* Don't emit untranslated entries.
- Also don't emit fuzzy entries, unless --use-fuzzy was specified.
- But ignore fuzziness of the header entry. */
- if (msgstr_string[0] == '\0'
- || (!include_all && this->is_fuzzy && msgid_string[0] != '\0'))
+ if (check_compatibility)
{
- if (check_compatibility)
- {
- error_with_progname = false;
- error_at_line (0, 0, msgstr_pos->file_name,
- msgstr_pos->line_number,
- (msgstr_string[0] == '\0'
- ? _("empty `msgstr' entry ignored")
- : _("fuzzy `msgstr' entry ignored")));
- error_with_progname = true;
- }
-
- /* Increment counter for fuzzy/untranslated messages. */
- if (msgstr_string[0] == '\0')
- ++msgs_untranslated;
- else
- ++msgs_fuzzy;
-
- mp->obsolete = true;
+ error_with_progname = false;
+ error_at_line (0, 0, mp->pos.file_name, mp->pos.line_number,
+ (mp->msgstr[0] == '\0'
+ ? _("empty `msgstr' entry ignored")
+ : _("fuzzy `msgstr' entry ignored")));
+ error_with_progname = true;
}
+
+ /* Increment counter for fuzzy/untranslated messages. */
+ if (mp->msgstr[0] == '\0')
+ ++msgs_untranslated;
else
+ ++msgs_fuzzy;
+
+ mp->obsolete = true;
+ }
+ else
+ {
+ /* Test for header entry. */
+ if (mp->msgid[0] == '\0')
{
- /* Test for header entry. */
- if (msgid_string[0] == '\0')
- {
- this->has_header_entry = true;
- if (!this->is_fuzzy)
- this->has_nonfuzzy_header_entry = true;
-
- /* Do some more tests on the contents of the header
- entry. */
- if (check_header)
- check_header_entry (msgstr_string);
- }
- else
- /* We don't count the header entry in the statistic so place
- the counter incrementation here. */
- if (this->is_fuzzy)
- ++msgs_fuzzy;
- else
- ++msgs_translated;
-
- /* Do some more checks on both strings. */
- check_pair (msgid_string, msgid_pos, msgid_plural,
- msgstr_string, msgstr_len, msgstr_pos,
- this->is_format);
+ this->has_header_entry = true;
+ if (!mp->is_fuzzy)
+ this->has_nonfuzzy_header_entry = true;
+
+ /* Do some more tests on the contents of the header entry. */
+ if (check_header)
+ check_header_entry (mp->msgstr);
}
+ else
+ /* We don't count the header entry in the statistic so place
+ the counter incrementation here. */
+ if (mp->is_fuzzy)
+ ++msgs_fuzzy;
+ else
+ ++msgs_translated;
+
+ /* Do some more checks on both strings. */
+ check_pair (mp->msgid, msgid_pos, mp->msgid_plural,
+ mp->msgstr, mp->msgstr_len, msgstr_pos,
+ mp->is_format);
}
- message_list_append (current_domain->mlp, mp);
}
-
- /* Prepare for next message. */
- this->is_fuzzy = false;
- for (i = 0; i < NFORMATS; i++)
- this->is_format[i] = undecided;
- this->do_wrap = undecided;
}
/* Test for `#, fuzzy' comments and warn. */
static void
-format_comment_special (po_ty *that, const char *s)
+msgfmt_comment_special (abstract_po_reader_ty *that, const char *s)
{
- msgfmt_class_ty *this = (msgfmt_class_ty *) that;
- bool fuzzy;
+ msgfmt_po_reader_ty *this = (msgfmt_po_reader_ty *) that;
- po_parse_comment_special (s, &fuzzy, this->is_format, &this->do_wrap);
+ /* Invoke superclass method. */
+ default_comment_special (that, s);
- if (fuzzy)
+ if (this->is_fuzzy)
{
static bool warned = false;
%s: warning: source file contains fuzzy translation"),
gram_pos.file_name);
}
-
- this->is_fuzzy = true;
}
}
and all actions resulting from the parse will be through
invocations of method functions of that object. */
-static po_method_ty format_methods =
+static default_po_reader_class_ty msgfmt_methods =
{
- sizeof (msgfmt_class_ty),
- format_constructor, /* constructor */
- NULL, /* destructor */
- format_directive_domain,
- format_directive_message,
- NULL, /* parse_brief */
- format_debrief, /* parse_debrief */
- NULL, /* comment */
- NULL, /* comment_dot */
- NULL, /* comment_filepos */
- format_comment_special /* comment */
+ {
+ sizeof (msgfmt_po_reader_ty),
+ msgfmt_constructor,
+ default_destructor,
+ default_parse_brief,
+ msgfmt_parse_debrief,
+ default_directive_domain,
+ default_directive_message,
+ default_comment,
+ default_comment_dot,
+ default_comment_filepos,
+ msgfmt_comment_special
+ },
+ msgfmt_set_domain, /* set_domain */
+ msgfmt_add_message, /* add_message */
+ msgfmt_frob_new_message /* frob_new_message */
};
/* Read .po file FILENAME and store translation pairs. */
static void
-read_po_file (char *filename)
+read_po_file_msgfmt (char *filename)
{
- po_ty *pop;
-
- pop = po_alloc (&format_methods);
+ default_po_reader_ty *pop;
+
+ pop = default_po_reader_alloc (&msgfmt_methods);
+ pop->handle_comments = false;
+ pop->handle_filepos_comments = false;
+ pop->allow_domain_directives = true;
+ pop->allow_duplicates = false;
+ pop->allow_duplicates_if_same_msgstr = false;
+ pop->mdlp = NULL;
+ pop->mlp = NULL;
+ if (current_domain != NULL)
+ {
+ /* Keep current_domain and this->domain synchronized. */
+ pop->domain = current_domain->domain_name;
+ pop->mlp = current_domain->mlp;
+ }
po_lex_pass_obsolete_entries (true);
- po_scan_file (pop, filename);
- po_free (pop);
+ po_scan_file ((abstract_po_reader_ty *) pop, filename);
+ po_reader_free ((abstract_po_reader_ty *) pop);
}
#include "strcase.h"
#include "stpcpy.h"
#include "stpncpy.h"
-#include "po.h"
#include "msgl-iconv.h"
#include "msgl-equal.h"
#include "plural-exp.h"
/* GNU gettext - internationalization aids
- Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2000-2001, 2003 Free Software Foundation, Inc.
This file was written by Peter Miller <pmiller@agso.gov.au>
#include "error.h"
#include "xmalloc.h"
#include "gettext.h"
-#include "po.h"
+#include "read-po-abstract.h"
#define _(str) gettext (str)
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1996, 1998, 2001-2002 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2001-2003 Free Software Foundation, Inc.
This file was written by Peter Miller <pmiller@agso.gov.au>
#include <string.h>
#include "xmalloc.h"
-#include "po.h"
+#include "read-po-abstract.h"
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
/* Analyze whether the string (a pseudo-comment line) contains file names
and line numbers. */
int
-po_hash (const char *s)
+po_parse_comment_filepos (const char *s)
{
cur = s;
last_was_colon = false;
/* GNU gettext - internationalization aids
- Copyright (C) 1995-1996, 1998, 2001-2002 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 1998, 2001-2003 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
sign "#:" or "#". If the string contains file names and line numbers,
return 0 and call po_callback_comment_filepos for each of them. Otherwise
return nonzero. */
-extern int po_hash (const char *string);
+extern int po_parse_comment_filepos (const char *string);
#endif /* _PO_HASH_H */
-/* GNU gettext - internationalization aids
+/* Reading PO files, abstract class.
Copyright (C) 1995-1996, 1998, 2000-2003 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
#endif
/* Specification. */
-#include "po.h"
+#include "read-po-abstract.h"
#include <stdlib.h>
#include <string.h>
#include "xmalloc.h"
/* Local variables. */
-static po_ty *callback_arg;
+static abstract_po_reader_ty *callback_arg;
-po_ty *
-po_alloc (po_method_ty *pomp)
+/* ========================================================================= */
+/* Allocating and freeing instances of abstract_po_reader_ty. */
+
+
+abstract_po_reader_ty *
+po_reader_alloc (abstract_po_reader_class_ty *method_table)
{
- po_ty *pop;
+ abstract_po_reader_ty *pop;
- pop = (po_ty *) xmalloc (pomp->size);
- pop->method = pomp;
- if (pomp->constructor)
- pomp->constructor (pop);
+ pop = (abstract_po_reader_ty *) xmalloc (method_table->size);
+ pop->methods = method_table;
+ if (method_table->constructor)
+ method_table->constructor (pop);
return pop;
}
void
-po_free (po_ty *pop)
+po_reader_free (abstract_po_reader_ty *pop)
{
- if (pop->method->destructor)
- pop->method->destructor (pop);
+ if (pop->methods->destructor)
+ pop->methods->destructor (pop);
free (pop);
}
-static void
-po_parse_brief (po_ty *pop)
+/* ========================================================================= */
+/* Inline functions to invoke the methods. */
+
+
+static inline void
+call_parse_brief (abstract_po_reader_ty *pop)
+{
+ if (pop->methods->parse_brief)
+ pop->methods->parse_brief (pop);
+}
+
+static inline void
+call_parse_debrief (abstract_po_reader_ty *pop)
+{
+ if (pop->methods->parse_debrief)
+ pop->methods->parse_debrief (pop);
+}
+
+static inline void
+call_directive_domain (abstract_po_reader_ty *pop, char *name)
{
- if (pop->method->parse_brief)
- pop->method->parse_brief (pop);
+ if (pop->methods->directive_domain)
+ pop->methods->directive_domain (pop, name);
}
+static inline void
+call_directive_message (abstract_po_reader_ty *pop,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ bool obsolete)
+{
+ if (pop->methods->directive_message)
+ pop->methods->directive_message (pop, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos, obsolete);
+}
-static void
-po_parse_debrief (po_ty *pop)
+static inline void
+call_comment (abstract_po_reader_ty *pop, const char *s)
{
- if (pop->method->parse_debrief)
- pop->method->parse_debrief (pop);
+ if (pop->methods->comment != NULL)
+ pop->methods->comment (pop, s);
}
+static inline void
+call_comment_dot (abstract_po_reader_ty *pop, const char *s)
+{
+ if (pop->methods->comment_dot != NULL)
+ pop->methods->comment_dot (pop, s);
+}
+
+static inline void
+call_comment_filepos (abstract_po_reader_ty *pop, const char *name, size_t line)
+{
+ if (pop->methods->comment_filepos)
+ pop->methods->comment_filepos (pop, name, line);
+}
+
+static inline void
+call_comment_special (abstract_po_reader_ty *pop, const char *s)
+{
+ if (pop->methods->comment_special != NULL)
+ pop->methods->comment_special (pop, s);
+}
+
+
+/* ========================================================================= */
+/* Exported functions. */
+
void
-po_scan_start (po_ty *pop)
+po_scan_start (abstract_po_reader_ty *pop)
{
/* The parse will call the po_callback_... functions (see below)
when the various directive are recognised. The callback_arg
have the relevant method invoked. */
callback_arg = pop;
- po_parse_brief (pop);
+ call_parse_brief (pop);
}
void
-po_scan_end (po_ty *pop)
+po_scan_end (abstract_po_reader_ty *pop)
{
- po_parse_debrief (pop);
+ call_parse_debrief (pop);
callback_arg = NULL;
}
void
-po_scan (po_ty *pop, FILE *fp,
+po_scan (abstract_po_reader_ty *pop, FILE *fp,
const char *real_filename, const char *logical_filename)
{
/* Parse the stream's content. */
void
-po_scan_file (po_ty *pop, const char *filename)
+po_scan_file (abstract_po_reader_ty *pop, const char *filename)
{
/* Open the file and parse it. */
lex_open (filename);
}
-static void
-po_directive_domain (po_ty *pop, char *name)
-{
- if (pop->method->directive_domain)
- pop->method->directive_domain (pop, name);
-}
+/* ========================================================================= */
+/* Callbacks used by po-gram.y or po-hash.y or po-lex.c, indirectly
+ from po_scan. */
/* This function is called by po_gram_lex() whenever a domain directive
po_callback_domain (char *name)
{
/* assert(callback_arg); */
- po_directive_domain (callback_arg, name);
-}
-
-
-static void
-po_directive_message (po_ty *pop,
- char *msgid,
- lex_pos_ty *msgid_pos,
- char *msgid_plural,
- char *msgstr, size_t msgstr_len,
- lex_pos_ty *msgstr_pos,
- bool obsolete)
-{
- if (pop->method->directive_message)
- pop->method->directive_message (pop, msgid, msgid_pos, msgid_plural,
- msgstr, msgstr_len, msgstr_pos, obsolete);
+ call_directive_domain (callback_arg, name);
}
if (msgid[0] == '\0' && !obsolete)
po_lex_charset_set (msgstr, gram_pos.file_name);
- po_directive_message (callback_arg, msgid, msgid_pos, msgid_plural,
- msgstr, msgstr_len, msgstr_pos, obsolete);
-}
-
-
-static void
-po_comment (po_ty *pop, const char *s)
-{
- if (pop->method->comment != NULL)
- pop->method->comment (pop, s);
-}
-
-
-static void
-po_comment_dot (po_ty *pop, const char *s)
-{
- if (pop->method->comment_dot != NULL)
- pop->method->comment_dot (pop, s);
+ call_directive_message (callback_arg, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos, obsolete);
}
-static void
-po_comment_filepos (po_ty *pop, const char *name, size_t line)
-{
- if (pop->method->comment_filepos)
- pop->method->comment_filepos (pop, name, line);
-}
-
-
-/* This function is called by po_hash(), once for each filename. */
+/* This function is called by po_parse_comment_filepos(), once for each
+ filename. */
void
po_callback_comment_filepos (const char *name, size_t line)
{
/* assert(callback_arg); */
- po_comment_filepos (callback_arg, name, line);
-}
-
-
-static void
-po_comment_special (po_ty *pop, const char *s)
-{
- if (pop->method->comment_special != NULL)
- pop->method->comment_special (pop, s);
+ call_comment_filepos (callback_arg, name, line);
}
/* This function is called by po_gram_lex() whenever a comment is
seen. It analyzes the comment to see what sort it is, and then
- dispatches it to the appropriate method: po_comment, po_comment_dot,
- po_comment_filepos (via po_hash), or po_comment_special. */
+ dispatches it to the appropriate method: call_comment, call_comment_dot,
+ call_comment_filepos (via po_parse_comment_filepos), or
+ call_comment_special. */
void
po_callback_comment (const char *s)
{
/* assert(callback_arg); */
if (*s == '.')
- po_comment_dot (callback_arg, s + 1);
+ call_comment_dot (callback_arg, s + 1);
else if (*s == ':')
{
/* Parse the file location string. If the parse succeeds, the
appropriate callback will be invoked. If the parse fails,
- the po_hash function will return non-zero - so pretend it was
- a normal comment. */
- if (po_hash (s + 1) == 0)
+ the po_parse_comment_filepos function will return non-zero - so
+ pretend it was a normal comment. */
+ if (po_parse_comment_filepos (s + 1) == 0)
/* Do nothing, it is a GNU-style file pos line. */ ;
else
- po_comment (callback_arg, s + 1);
+ call_comment (callback_arg, s + 1);
}
else if (*s == ',' || *s == '!')
{
/* Get all entries in the special comment line. */
- po_comment_special (callback_arg, s + 1);
+ call_comment_special (callback_arg, s + 1);
}
else
{
appropriate callback will be invoked. */
if (s[0] == ' ' && (s[1] == 'F' || s[1] == 'f') && s[2] == 'i'
&& s[3] == 'l' && s[4] == 'e' && s[5] == ':'
- && po_hash (s) == 0)
+ && po_parse_comment_filepos (s) == 0)
/* Do nothing, it is a Sun-style file pos line. */ ;
else
- po_comment (callback_arg, s);
+ call_comment (callback_arg, s);
}
}
-/* GNU gettext - internationalization aids
+/* Reading PO files, abstract class.
Copyright (C) 1995-1996, 1998, 2000-2003 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#ifndef _PO_H
-#define _PO_H
+#ifndef _READ_PO_ABSTRACT_H
+#define _READ_PO_ABSTRACT_H
#include "po-lex.h"
#include "message.h"
used to indicate a type name. */
/* The following pair of structures cooperate to create an "Object" in
- the OO sense, we are simply doing it manually, rather than with the
+ the OO sense. We are simply doing it manually, rather than with the
help of an OO compiler. This implementation allows polymorphism
- and inheritance - more than enough for the immediate needs.
-
- This first structure contains pointers to functions. Each function
- is a method for the class (base or derived).
-
- Use a NULL pointer where no action is required. */
+ and inheritance - more than enough for the immediate needs. */
/* Forward declaration. */
-struct po_ty;
+struct abstract_po_reader_ty;
+
+/* This first structure, playing the role of the "Class" in OO sense,
+ contains pointers to functions. Each function is a method for the
+ class (base or derived). Use a NULL pointer where no action is
+ required. */
-typedef struct po_method_ty po_method_ty;
-struct po_method_ty
+typedef struct abstract_po_reader_class_ty abstract_po_reader_class_ty;
+struct abstract_po_reader_class_ty
{
- /* how many bytes to malloc for this class */
+ /* how many bytes to malloc for an instance of this class */
size_t size;
/* what to do immediately after the instance is malloc()ed */
- void (*constructor) (struct po_ty *pop);
+ void (*constructor) (struct abstract_po_reader_ty *pop);
/* what to do immediately before the instance is free()ed */
- void (*destructor) (struct po_ty *pop);
+ void (*destructor) (struct abstract_po_reader_ty *pop);
+
+ /* This method is invoked before the parse, but after the file is
+ opened by the lexer. */
+ void (*parse_brief) (struct abstract_po_reader_ty *pop);
+
+ /* This method is invoked after the parse, but before the file is
+ closed by the lexer. The intention is to make consistency checks
+ against the file here, and emit the errors through the lex_error*
+ functions. */
+ void (*parse_debrief) (struct abstract_po_reader_ty *pop);
/* what to do with a domain directive */
- void (*directive_domain) (struct po_ty *pop, char *name);
+ void (*directive_domain) (struct abstract_po_reader_ty *pop, char *name);
/* what to do with a message directive */
- void (*directive_message) (struct po_ty *pop,
+ void (*directive_message) (struct abstract_po_reader_ty *pop,
char *msgid, lex_pos_ty *msgid_pos,
char *msgid_plural,
char *msgstr, size_t msgstr_len,
lex_pos_ty *msgstr_pos,
bool obsolete);
- /* This method is invoked before the parse, but after the file is
- opened by the lexer. */
- void (*parse_brief) (struct po_ty *pop);
-
- /* This method is invoked after the parse, but before the file is
- closed by the lexer. The intention is to make consistency checks
- against the file here, and emit the errors through the lex_error*
- functions. */
- void (*parse_debrief) (struct po_ty *pop);
-
/* What to do with a plain-vanilla comment - the expectation is that
they will be accumulated, and added to the next message
definition seen. Or completely ignored. */
- void (*comment) (struct po_ty *pop, const char *s);
+ void (*comment) (struct abstract_po_reader_ty *pop, const char *s);
/* What to do with a comment that starts with a dot (i.e. extracted
by xgettext) - the expectation is that they will be accumulated,
and added to the next message definition seen. Or completely
ignored. */
- void (*comment_dot) (struct po_ty *pop, const char *s);
+ void (*comment_dot) (struct abstract_po_reader_ty *pop, const char *s);
/* What to do with a file position seen in a comment (i.e. a message
location comment extracted by xgettext) - the expectation is that
they will be accumulated, and added to the next message
definition seen. Or completely ignored. */
- void (*comment_filepos) (struct po_ty *pop, const char *s, size_t line);
+ void (*comment_filepos) (struct abstract_po_reader_ty *pop,
+ const char *s, size_t line);
/* What to do with a comment that starts with a ',' or '!' - this is a
special comment. One of the possible uses is to indicate a
inexact translation. */
- void (*comment_special) (struct po_ty *pop, const char *s);
+ void (*comment_special) (struct abstract_po_reader_ty *pop, const char *s);
};
/* This next structure defines the base class passed to the methods.
Derived methods will often need to cast their first argument before
- using it (this corresponds to the implicit ``this'' argument of many
- C++ implementations).
+ using it (this corresponds to the implicit ``this'' argument in C++).
- When declaring derived classes, use the PO_BASE_TY define at the
- start of the structure, to declare inherited instance variables,
+ When declaring derived classes, use the ABSTRACT_PO_READER_TY define
+ at the start of the structure, to declare inherited instance variables,
etc. */
-#define PO_BASE_TY \
- po_method_ty *method;
+#define ABSTRACT_PO_READER_TY \
+ abstract_po_reader_class_ty *methods;
-typedef struct po_ty po_ty;
-struct po_ty
+typedef struct abstract_po_reader_ty abstract_po_reader_ty;
+struct abstract_po_reader_ty
{
- PO_BASE_TY
+ ABSTRACT_PO_READER_TY
};
-/* Allocate a fresh po_ty (or derived class) instance and call its
- constructor. */
-extern po_ty *po_alloc (po_method_ty *jtable);
+/* Allocate a fresh abstract_po_reader_ty (or derived class) instance and
+ call its constructor. */
+extern abstract_po_reader_ty *
+ po_reader_alloc (abstract_po_reader_class_ty *method_table);
-/* Prepare for use of po_method_ty methods. */
-extern void po_scan_start (po_ty *pop);
+/* Prepare for use of abstract_po_reader_class_ty methods. */
+extern void
+ po_scan_start (abstract_po_reader_ty *pop);
-/* Terminate the use of po_method_ty methods. */
-extern void po_scan_end (po_ty *pop);
+/* Terminate the use of abstract_po_reader_class_ty methods. */
+extern void
+ po_scan_end (abstract_po_reader_ty *pop);
-/* Read a PO file from a stream, and dispatch to the various po_method_ty
- methods. */
-extern void po_scan (po_ty *pop, FILE *fp, const char *real_filename,
- const char *logical_filename);
+/* Read a PO file from a stream, and dispatch to the various
+ abstract_po_reader_class_ty methods. */
+extern void
+ po_scan (abstract_po_reader_ty *pop, FILE *fp,
+ const char *real_filename, const char *logical_filename);
-/* Locate a PO file, open it, read it, dispatching to the various po_method_ty
- methods, and close it. */
-extern void po_scan_file (po_ty *pop, const char *filename);
+/* Locate a PO file, open it, read it, dispatching to the various
+ abstract_po_reader_class_ty methods, and close it. */
+extern void
+ po_scan_file (abstract_po_reader_ty *pop, const char *filename);
-/* Call the destructor and deallocate a po_ty (or derived class)
- instance. */
-extern void po_free (po_ty *pop);
+/* Call the destructor and deallocate a abstract_po_reader_ty (or derived
+ class) instance. */
+extern void
+ po_reader_free (abstract_po_reader_ty *pop);
/* Callbacks used by po-gram.y or po-hash.y or po-lex.c, indirectly
enum is_format formatp[NFORMATS],
enum is_wrap *wrapp);
-#endif /* _PO_H */
+#endif /* _READ_PO_ABSTRACT_H */
#include <stdlib.h>
#include <string.h>
-#include "po.h"
#include "xmalloc.h"
#include "gettext.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;
+/* ========================================================================= */
+/* Inline functions to invoke the methods. */
-/* If false, duplicate msgids in the same domain and file generate an error.
- If true, such msgids are allowed; the caller should treat them
- appropriately. Defaults to false. */
-bool allow_duplicates = false;
+static inline void
+call_set_domain (struct default_po_reader_ty *this, char *name)
+{
+ default_po_reader_class_ty *methods =
+ (default_po_reader_class_ty *) this->methods;
+ if (methods->set_domain)
+ methods->set_domain (this, name);
+}
-/* 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
+static inline void
+call_add_message (struct default_po_reader_ty *this,
+ char *msgid, lex_pos_ty *msgid_pos, char *msgid_plural,
+ char *msgstr, size_t msgstr_len, lex_pos_ty *msgstr_pos,
+ bool obsolete)
{
- /* inherited instance variables, etc. */
- PO_BASE_TY
+ default_po_reader_class_ty *methods =
+ (default_po_reader_class_ty *) this->methods;
- /* List of messages already appeared in the current file. */
- msgdomain_list_ty *mdlp;
+ if (methods->add_message)
+ methods->add_message (this, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos, obsolete);
+}
- /* Name of domain we are currently examining. */
- char *domain;
+static inline void
+call_frob_new_message (struct default_po_reader_ty *this, message_ty *mp,
+ const lex_pos_ty *msgid_pos,
+ const lex_pos_ty *msgstr_pos)
+{
+ default_po_reader_class_ty *methods =
+ (default_po_reader_class_ty *) this->methods;
- /* List of messages belonging to the current domain. */
- message_list_ty *mlp;
+ if (methods->frob_new_message)
+ methods->frob_new_message (this, mp, msgid_pos, msgstr_pos);
+}
- /* Accumulate comments for next message directive. */
- string_list_ty *comment;
- string_list_ty *comment_dot;
- /* Flags transported in special comments. */
- bool is_fuzzy;
- enum is_format is_format[NFORMATS];
- enum is_wrap do_wrap;
+/* ========================================================================= */
+/* Implementation of default_po_reader_ty's methods. */
- /* Accumulate filepos comments for the next message directive. */
- size_t filepos_count;
- lex_pos_ty *filepos;
-};
+
+/* Implementation of methods declared in the superclass. */
/* Prepare for first message. */
-static void
-readall_constructor (po_ty *that)
+void
+default_constructor (abstract_po_reader_ty *that)
{
- readall_class_ty *this = (readall_class_ty *) that;
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
size_t i;
- this->mdlp = msgdomain_list_alloc (!allow_duplicates);
this->domain = MESSAGE_DOMAIN_DEFAULT;
- this->mlp = msgdomain_list_sublist (this->mdlp, this->domain, true);
this->comment = NULL;
this->comment_dot = NULL;
this->filepos_count = 0;
}
-static void
-readall_destructor (po_ty *that)
+void
+default_destructor (abstract_po_reader_ty *that)
{
- readall_class_ty *this = (readall_class_ty *) that;
- size_t j;
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
/* Do not free this->mdlp and 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);
+ if (this->handle_comments)
+ {
+ if (this->comment != NULL)
+ string_list_free (this->comment);
+ if (this->comment_dot != NULL)
+ string_list_free (this->comment_dot);
+ }
+ if (this->handle_filepos_comments)
+ {
+ size_t j;
+
+ for (j = 0; j < this->filepos_count; ++j)
+ free (this->filepos[j].file_name);
+ if (this->filepos != NULL)
+ free (this->filepos);
+ }
}
-/* Process 'domain' directive from .po file. */
-static void
-readall_directive_domain (po_ty *that, char *name)
+void
+default_parse_brief (abstract_po_reader_ty *that)
{
- size_t j;
+ /* We need to parse comments, because even if this->handle_comments and
+ this->handle_filepos_comments are false, we need to know which messages
+ are fuzzy. */
+ po_lex_pass_comments (true);
+}
- 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;
+void
+default_parse_debrief (abstract_po_reader_ty *that)
+{
}
-/* Process 'msgid'/'msgstr' pair from .po file. */
+/* Add the accumulated comments to the message. */
static void
-readall_directive_message (po_ty *that,
- char *msgid,
- lex_pos_ty *msgid_pos,
- char *msgid_plural,
- char *msgstr, size_t msgstr_len,
- lex_pos_ty *msgstr_pos,
- bool obsolete)
+default_copy_comment_state (default_po_reader_ty *this, message_ty *mp)
{
- readall_class_ty *this = (readall_class_ty *) that;
- message_ty *mp;
size_t j, i;
- /* Select the appropriate sublist of this->mdlp. */
- this->mlp = msgdomain_list_sublist (this->mdlp, this->domain, true);
-
- if (allow_duplicates && msgid[0] != '\0')
- /* Doesn't matter if this message ID has been seen before. */
- mp = NULL;
- else
- /* See if this message ID has been seen before. */
- mp = message_list_search (this->mlp, msgid);
-
- if (mp)
- {
- po_gram_error_at_line (msgid_pos, _("duplicate message definition"));
- po_gram_error_at_line (&mp->pos, _("\
-...this is the location of the first definition"));
- free (msgstr);
- free (msgid);
- }
- else
- {
- mp = message_alloc (msgid, msgid_plural, msgstr, msgstr_len, msgstr_pos);
- message_list_append (this->mlp, mp);
- mp->obsolete = obsolete;
- }
-
- /* Add the accumulated comments to the message. */
- if (this->comment != NULL)
- {
- for (j = 0; j < this->comment->nitems; ++j)
- message_comment_append (mp, this->comment->item[j]);
- }
- if (this->comment_dot != NULL)
+ if (this->handle_comments)
{
- for (j = 0; j < this->comment_dot->nitems; ++j)
- message_comment_dot_append (mp, this->comment_dot->item[j]);
+ if (this->comment != NULL)
+ for (j = 0; j < this->comment->nitems; ++j)
+ message_comment_append (mp, this->comment->item[j]);
+ if (this->comment_dot != NULL)
+ for (j = 0; j < this->comment_dot->nitems; ++j)
+ message_comment_dot_append (mp, this->comment_dot->item[j]);
}
- for (j = 0; j < this->filepos_count; ++j)
+ if (this->handle_filepos_comments)
{
- lex_pos_ty *pp;
+ 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);
+ pp = &this->filepos[j];
+ message_comment_filepos (mp, pp->file_name, pp->line_number);
+ }
}
mp->is_fuzzy = this->is_fuzzy;
for (i = 0; i < NFORMATS; i++)
mp->is_format[i] = this->is_format[i];
mp->do_wrap = this->do_wrap;
+}
- /* Prepare for next message. */
- if (this->comment != NULL)
- {
- string_list_free (this->comment);
- this->comment = NULL;
- }
- if (this->comment_dot != NULL)
+
+static void
+default_reset_comment_state (default_po_reader_ty *this)
+{
+ size_t j, i;
+
+ if (this->handle_comments)
{
- string_list_free (this->comment_dot);
- this->comment_dot = NULL;
+ 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)
+ if (this->handle_filepos_comments)
{
- lex_pos_ty *pp;
-
- pp = &this->filepos[j];
- free (pp->file_name);
+ 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;
}
- if (this->filepos != NULL)
- free (this->filepos);
- this->filepos_count = 0;
- this->filepos = NULL;
this->is_fuzzy = false;
for (i = 0; i < NFORMATS; i++)
this->is_format[i] = undecided;
}
-static void
-readall_parse_brief (po_ty *that)
+/* Process 'domain' directive from .po file. */
+void
+default_directive_domain (abstract_po_reader_ty *that, char *name)
{
- po_lex_pass_comments (true);
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
+
+ call_set_domain (this, 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. */
+ default_reset_comment_state (this);
}
-static void
-readall_comment (po_ty *that, const char *s)
+/* Process 'msgid'/'msgstr' pair from .po file. */
+void
+default_directive_message (abstract_po_reader_ty *that,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ bool obsolete)
{
- readall_class_ty *this = (readall_class_ty *) that;
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
+
+ call_add_message (this, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos, obsolete);
- if (this->comment == NULL)
- this->comment = string_list_alloc ();
- string_list_append (this->comment, s);
+ /* Prepare for next message. */
+ default_reset_comment_state (this);
}
-static void
-readall_comment_dot (po_ty *that, const char *s)
+void
+default_comment (abstract_po_reader_ty *that, const char *s)
+{
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
+
+ if (this->handle_comments)
+ {
+ if (this->comment == NULL)
+ this->comment = string_list_alloc ();
+ string_list_append (this->comment, s);
+ }
+}
+
+
+void
+default_comment_dot (abstract_po_reader_ty *that, const char *s)
{
- readall_class_ty *this = (readall_class_ty *) that;
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
- if (this->comment_dot == NULL)
- this->comment_dot = string_list_alloc ();
- string_list_append (this->comment_dot, s);
+ if (this->handle_comments)
+ {
+ if (this->comment_dot == NULL)
+ this->comment_dot = string_list_alloc ();
+ string_list_append (this->comment_dot, s);
+ }
+}
+
+
+void
+default_comment_filepos (abstract_po_reader_ty *that,
+ const char *name, size_t line)
+{
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
+
+ if (this->handle_filepos_comments)
+ {
+ size_t nbytes;
+ lex_pos_ty *pp;
+
+ 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;
+ }
}
/* Test for '#, fuzzy' comments and warn. */
-static void
-readall_comment_special (po_ty *that, const char *s)
+void
+default_comment_special (abstract_po_reader_ty *that, const char *s)
{
- readall_class_ty *this = (readall_class_ty *) that;
+ default_po_reader_ty *this = (default_po_reader_ty *) that;
po_parse_comment_special (s, &this->is_fuzzy, this->is_format,
&this->do_wrap);
}
-static void
-readall_comment_filepos (po_ty *that, const char *name, size_t line)
+/* Default implementation of methods not inherited from the superclass. */
+
+
+void
+default_set_domain (default_po_reader_ty *this, char *name)
+{
+ if (this->allow_domain_directives)
+ /* Override current domain name. Don't free memory. */
+ this->domain = name;
+ else
+ {
+ po_gram_error_at_line (&gram_pos,
+ _("this file may not contain domain directives"));
+
+ /* NAME was allocated in po-gram-gen.y but is not used anywhere. */
+ free (name);
+ }
+}
+
+void
+default_add_message (default_po_reader_ty *this,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ bool obsolete)
{
- 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;
+ message_ty *mp;
+
+ if (this->mdlp != NULL)
+ /* Select the appropriate sublist of this->mdlp. */
+ this->mlp = msgdomain_list_sublist (this->mdlp, this->domain, true);
+
+ if (this->allow_duplicates && msgid[0] != '\0')
+ /* Doesn't matter if this message ID has been seen before. */
+ mp = NULL;
+ else
+ /* See if this message ID has been seen before. */
+ mp = message_list_search (this->mlp, msgid);
+
+ if (mp)
+ {
+ if (!(this->allow_duplicates_if_same_msgstr
+ && msgstr_len == mp->msgstr_len
+ && memcmp (msgstr, mp->msgstr, msgstr_len) == 0))
+ {
+ /* We give a fatal error about this, regardless whether the
+ translations are equal or different. This is for consistency
+ with msgmerge, msgcat and others. The user can use the
+ msguniq program to get rid of duplicates. */
+ po_gram_error_at_line (msgid_pos, _("duplicate message definition"));
+ po_gram_error_at_line (&mp->pos, _("\
+...this is the location of the first definition"));
+ }
+ /* We don't need the just constructed entries' parameter string
+ (allocated in po-gram-gen.y). */
+ free (msgstr);
+ free (msgid);
+
+ /* Add the accumulated comments to the message. */
+ default_copy_comment_state (this, mp);
+ }
+ else
+ {
+ /* Construct message to add to the list.
+ Obsolete message go into the list at least for duplicate checking.
+ It's the caller's responsibility to ignore obsolete messages when
+ appropriate. */
+ mp = message_alloc (msgid, msgid_plural, msgstr, msgstr_len, msgstr_pos);
+ mp->obsolete = obsolete;
+ default_copy_comment_state (this, mp);
+
+ call_frob_new_message (this, mp, msgid_pos, msgstr_pos);
+
+ message_list_append (this->mlp, mp);
+ }
}
and all actions resulting from the parse will be through
invocations of method functions of that object. */
-static po_method_ty readall_methods =
+static default_po_reader_class_ty default_methods =
{
- sizeof (readall_class_ty),
- readall_constructor,
- readall_destructor,
- readall_directive_domain,
- readall_directive_message,
- readall_parse_brief,
- NULL, /* parse_debrief */
- readall_comment,
- readall_comment_dot,
- readall_comment_filepos,
- readall_comment_special
+ {
+ sizeof (default_po_reader_ty),
+ default_constructor,
+ default_destructor,
+ default_parse_brief,
+ default_parse_debrief,
+ default_directive_domain,
+ default_directive_message,
+ default_comment,
+ default_comment_dot,
+ default_comment_filepos,
+ default_comment_special
+ },
+ default_set_domain, /* set_domain */
+ default_add_message, /* add_message */
+ NULL /* frob_new_message */
};
+default_po_reader_ty *
+default_po_reader_alloc (default_po_reader_class_ty *method_table)
+{
+ return (default_po_reader_ty *) po_reader_alloc (&method_table->super);
+}
+
+
+/* ========================================================================= */
+/* Exported functions. */
+
+
+/* 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;
+
+/* If false, duplicate msgids in the same domain and file generate an error.
+ If true, such msgids are allowed; the caller should treat them
+ appropriately. Defaults to false. */
+bool allow_duplicates = false;
+
+
msgdomain_list_ty *
read_po (FILE *fp, const char *real_filename, const char *logical_filename)
{
- po_ty *pop;
+ default_po_reader_ty *pop;
msgdomain_list_ty *mdlp;
- pop = po_alloc (&readall_methods);
+ pop = default_po_reader_alloc (&default_methods);
+ pop->handle_comments = true;
+ pop->handle_filepos_comments = (line_comment != 0);
+ pop->allow_domain_directives = true;
+ pop->allow_duplicates = allow_duplicates;
+ pop->allow_duplicates_if_same_msgstr = false;
+ pop->mdlp = msgdomain_list_alloc (!pop->allow_duplicates);
+ pop->mlp = msgdomain_list_sublist (pop->mdlp, pop->domain, true);
po_lex_pass_obsolete_entries (true);
- po_scan (pop, fp, real_filename, logical_filename);
- mdlp = ((readall_class_ty *) pop)->mdlp;
- po_free (pop);
+ po_scan ((abstract_po_reader_ty *) pop, fp, real_filename, logical_filename);
+ mdlp = pop->mdlp;
+ po_reader_free ((abstract_po_reader_ty *) pop);
return mdlp;
}
msgdomain_list_ty *
read_po_file (const char *filename)
{
- po_ty *pop;
+ default_po_reader_ty *pop;
msgdomain_list_ty *mdlp;
- pop = po_alloc (&readall_methods);
+ pop = default_po_reader_alloc (&default_methods);
+ pop->handle_comments = true;
+ pop->handle_filepos_comments = (line_comment != 0);
+ pop->allow_domain_directives = true;
+ pop->allow_duplicates = allow_duplicates;
+ pop->allow_duplicates_if_same_msgstr = false;
+ pop->mdlp = msgdomain_list_alloc (!pop->allow_duplicates);
+ pop->mlp = msgdomain_list_sublist (pop->mdlp, pop->domain, true);
po_lex_pass_obsolete_entries (true);
- po_scan_file (pop, filename);
- mdlp = ((readall_class_ty *) pop)->mdlp;
- po_free (pop);
+ po_scan_file ((abstract_po_reader_ty *) pop, filename);
+ mdlp = pop->mdlp;
+ po_reader_free ((abstract_po_reader_ty *) pop);
return mdlp;
}
#define _READ_PO_H
#include "message.h"
+#include "read-po-abstract.h"
#include <stdbool.h>
#include <stdio.h>
+/* The following pair of structures cooperate to create a derived class from
+ class abstract_po_reader_ty. (See read-po-abstract.h for an explanation.)
+ It implements the default behaviour of reading a PO file and converting it
+ to an 'msgdomain_list_ty *'. */
+
+/* Forward declaration. */
+struct default_po_reader_ty;
+
+
+typedef struct default_po_reader_class_ty default_po_reader_class_ty;
+struct default_po_reader_class_ty
+{
+ /* Methods inherited from superclass. */
+ struct abstract_po_reader_class_ty super;
+
+ /* How to change the current domain. */
+ void (*set_domain) (struct default_po_reader_ty *pop, char *name);
+
+ /* How to add a message to the list. */
+ void (*add_message) (struct default_po_reader_ty *pop,
+ char *msgid, lex_pos_ty *msgid_pos, char *msgid_plural,
+ char *msgstr, size_t msgstr_len, lex_pos_ty *msgstr_pos,
+ bool obsolete);
+
+ /* How to modify a new message before adding it to the list. */
+ void (*frob_new_message) (struct default_po_reader_ty *pop, message_ty *mp,
+ const lex_pos_ty *msgid_pos,
+ const lex_pos_ty *msgstr_pos);
+};
+
+
+#define DEFAULT_PO_READER_TY \
+ ABSTRACT_PO_READER_TY \
+ \
+ /* If true, pay attention to comments and filepos comments. */ \
+ bool handle_comments; \
+ \
+ /* If true, remember comments for file name and line number for each \
+ msgid, if present in the reference input. */ \
+ bool handle_filepos_comments; \
+ \
+ /* If false, domain directives lead to an error messsage. */ \
+ bool allow_domain_directives; \
+ \
+ /* If false, duplicate msgids in the same domain and file generate an \
+ error. If true, such msgids are allowed; the caller should treat \
+ them appropriately. */ \
+ bool allow_duplicates; \
+ \
+ /* If true, allow duplicates if they have the same translation. */ \
+ bool allow_duplicates_if_same_msgstr; \
+ \
+ /* List of messages already appeared in the current file. */ \
+ msgdomain_list_ty *mdlp; \
+ \
+ /* Name of domain we are currently examining. */ \
+ const char *domain; \
+ \
+ /* List of messages belonging to the current domain. */ \
+ message_list_ty *mlp; \
+ \
+ /* Accumulate comments for next message directive. */ \
+ string_list_ty *comment; \
+ string_list_ty *comment_dot; \
+ \
+ /* Accumulate filepos comments for the next message directive. */ \
+ size_t filepos_count; \
+ lex_pos_ty *filepos; \
+ \
+ /* Flags transported in special comments. */ \
+ bool is_fuzzy; \
+ enum is_format is_format[NFORMATS]; \
+ enum is_wrap do_wrap; \
+
+typedef struct default_po_reader_ty default_po_reader_ty;
+struct default_po_reader_ty
+{
+ DEFAULT_PO_READER_TY
+};
+
+extern void default_constructor (abstract_po_reader_ty *that);
+extern void default_destructor (abstract_po_reader_ty *that);
+extern void default_parse_brief (abstract_po_reader_ty *that);
+extern void default_parse_debrief (abstract_po_reader_ty *that);
+extern void default_directive_domain (abstract_po_reader_ty *that, char *name);
+extern void default_directive_message (abstract_po_reader_ty *that,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ bool obsolete);
+extern void default_comment (abstract_po_reader_ty *that, const char *s);
+extern void default_comment_dot (abstract_po_reader_ty *that, const char *s);
+extern void default_comment_filepos (abstract_po_reader_ty *that,
+ const char *name, size_t line);
+extern void default_comment_special (abstract_po_reader_ty *that,
+ const char *s);
+extern void default_set_domain (default_po_reader_ty *this, char *name);
+extern void default_add_message (default_po_reader_ty *this,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ bool obsolete);
+
+/* Allocate a fresh default_po_reader_ty (or derived class) instance and
+ call its constructor. */
+extern default_po_reader_ty *
+ default_po_reader_alloc (default_po_reader_class_ty *method_table);
+
+
/* 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;
#include "x-po.h"
#include "xgettext.h"
#include "xmalloc.h"
-#include "po.h"
+#include "read-po.h"
#include "po-lex.h"
#include "gettext.h"
#define _(str) gettext (str)
-typedef struct extract_class_ty extract_class_ty;
-struct extract_class_ty
-{
- /* Inherited instance variables and methods. */
- PO_BASE_TY
-
- /* Cumulative list of messages. */
- message_list_ty *mlp;
-
- /* Cumulative comments for next message. */
- string_list_ty *comment;
- string_list_ty *comment_dot;
-
- bool is_fuzzy;
- enum is_format is_format[NFORMATS];
- enum is_wrap do_wrap;
-
- size_t filepos_count;
- lex_pos_ty *filepos;
-};
-
-
-static void
-extract_constructor (po_ty *that)
-{
- extract_class_ty *this = (extract_class_ty *) that;
- size_t i;
-
- this->mlp = NULL; /* actually set in extract_po, below */
- this->comment = NULL;
- this->comment_dot = NULL;
- this->is_fuzzy = false;
- for (i = 0; i < NFORMATS; i++)
- this->is_format[i] = undecided;
- this->do_wrap = undecided;
- this->filepos_count = 0;
- this->filepos = NULL;
-}
-
-
-static void
-extract_directive_domain (po_ty *that, char *name)
-{
- po_gram_error_at_line (&gram_pos,
- _("this file may not contain domain directives"));
-}
-
+/* Define a subclass extract_po_reader_ty of default_po_reader_ty. */
static void
-extract_directive_message (po_ty *that,
- char *msgid,
- lex_pos_ty *msgid_pos,
- char *msgid_plural,
- char *msgstr, size_t msgstr_len,
- lex_pos_ty *msgstr_pos,
- bool obsolete)
+extract_add_message (default_po_reader_ty *this,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ bool obsolete)
{
- extract_class_ty *this = (extract_class_ty *)that;
- message_ty *mp;
- size_t j, i;
-
/* See whether we shall exclude this message. */
if (exclude != NULL && message_list_search (exclude, msgid) != NULL)
goto discard;
discard:
free (msgid);
free (msgstr);
- if (this->comment != NULL)
- string_list_free (this->comment);
- if (this->comment_dot != NULL)
- string_list_free (this->comment_dot);
- if (this->filepos != NULL)
- free (this->filepos);
- this->comment = NULL;
- this->comment_dot = NULL;
- this->filepos_count = 0;
- this->filepos = NULL;
- this->is_fuzzy = false;
- for (i = 0; i < NFORMATS; i++)
- this->is_format[i] = undecided;
- this->do_wrap = undecided;
return;
}
- /* See if this message ID has been seen before. */
- mp = message_list_search (this->mlp, msgid);
- if (mp)
- {
- if (msgstr_len != mp->msgstr_len
- || memcmp (msgstr, mp->msgstr, msgstr_len) != 0)
- {
- po_gram_error_at_line (msgid_pos, _("duplicate message definition"));
- po_gram_error_at_line (&mp->pos, _("\
-...this is the location of the first definition"));
- }
- free (msgid);
- free (msgstr);
- }
- else
- {
- mp = message_alloc (msgid, msgid_plural, msgstr, msgstr_len, msgstr_pos);
- message_list_append (this->mlp, mp);
- }
-
- /* Add the accumulated comments to the message. */
- if (this->comment != NULL)
- {
- for (j = 0; j < this->comment->nitems; ++j)
- message_comment_append (mp, this->comment->item[j]);
- }
- if (this->comment_dot != NULL)
- {
- for (j = 0; j < this->comment_dot->nitems; ++j)
- message_comment_dot_append (mp, this->comment_dot->item[j]);
- }
- mp->is_fuzzy = this->is_fuzzy;
- for (i = 0; i < NFORMATS; i++)
- mp->is_format[i] = this->is_format[i];
- mp->do_wrap = this->do_wrap;
- 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);
- }
-
- /* Prepare for 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)
- {
- lex_pos_ty *pp;
-
- pp = &this->filepos[j];
- free (pp->file_name);
- }
- if (this->filepos != NULL)
- free (this->filepos);
- this->filepos_count = 0;
- this->filepos = NULL;
- this->is_fuzzy = false;
- for (i = 0; i < NFORMATS; i++)
- this->is_format[i] = undecided;
- this->do_wrap = undecided;
-}
-
-
-static void
-extract_parse_brief (po_ty *that)
-{
- po_lex_pass_comments (true);
-}
-
-
-static void
-extract_comment (po_ty *that, const char *s)
-{
- extract_class_ty *this = (extract_class_ty *) that;
-
- if (this->comment == NULL)
- this->comment = string_list_alloc ();
- string_list_append (this->comment, s);
-}
-
-
-static void
-extract_comment_dot (po_ty *that, const char *s)
-{
- extract_class_ty *this = (extract_class_ty *) that;
-
- if (this->comment_dot == NULL)
- this->comment_dot = string_list_alloc ();
- string_list_append (this->comment_dot, s);
-}
-
-
-static void
-extract_comment_filepos (po_ty *that, const char *name, size_t line)
-{
- extract_class_ty *this = (extract_class_ty *) that;
- size_t nbytes;
- lex_pos_ty *pp;
-
- /* Write line numbers only if -n option is given. */
- if (line_comment != 0)
- {
- 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;
- }
-}
-
-
-static void
-extract_comment_special (po_ty *that, const char *s)
-{
- extract_class_ty *this = (extract_class_ty *) that;
-
- po_parse_comment_special (s, &this->is_fuzzy, this->is_format,
- &this->do_wrap);
+ /* Invoke superclass method. */
+ default_add_message (this, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos, obsolete);
}
and all actions resulting from the parse will be through
invocations of method functions of that object. */
-static po_method_ty extract_methods =
+static default_po_reader_class_ty extract_methods =
{
- sizeof (extract_class_ty),
- extract_constructor,
- NULL, /* destructor */
- extract_directive_domain,
- extract_directive_message,
- extract_parse_brief,
- NULL, /* parse_debrief */
- extract_comment,
- extract_comment_dot,
- extract_comment_filepos,
- extract_comment_special
+ {
+ sizeof (default_po_reader_ty),
+ default_constructor,
+ default_destructor,
+ default_parse_brief,
+ default_parse_debrief,
+ default_directive_domain,
+ default_directive_message,
+ default_comment,
+ default_comment_dot,
+ default_comment_filepos,
+ default_comment_special
+ },
+ default_set_domain, /* set_domain */
+ extract_add_message, /* add_message */
+ NULL /* frob_new_message */
};
const char *real_filename, const char *logical_filename,
msgdomain_list_ty *mdlp)
{
- po_ty *pop = po_alloc (&extract_methods);
- ((extract_class_ty *) pop)->mlp = mdlp->item[0]->messages;
- po_scan (pop, fp, real_filename, logical_filename);
- po_free (pop);
+ default_po_reader_ty *pop;
+
+ pop = default_po_reader_alloc (&extract_methods);
+ pop->handle_comments = true;
+ pop->handle_filepos_comments = (line_comment != 0);
+ pop->allow_domain_directives = false;
+ pop->allow_duplicates = false;
+ pop->allow_duplicates_if_same_msgstr = true;
+ pop->mdlp = NULL;
+ pop->mlp = mdlp->item[0]->messages;
+ po_scan ((abstract_po_reader_ty *) pop, fp, real_filename, logical_filename);
+ po_reader_free ((abstract_po_reader_ty *) pop);
}
#include "pathname.h"
#include "strcase.h"
#include "stpcpy.h"
-#include "po.h"
+#include "read-po-abstract.h"
#include "message.h"
#include "po-charset.h"
#include "msgl-iconv.h"
static void
-exclude_directive_domain (po_ty *pop, char *name)
+exclude_directive_domain (abstract_po_reader_ty *pop, char *name)
{
po_gram_error_at_line (&gram_pos,
_("this file may not contain domain directives"));
static void
-exclude_directive_message (po_ty *pop,
+exclude_directive_message (abstract_po_reader_ty *pop,
char *msgid,
lex_pos_ty *msgid_pos,
char *msgid_plural,
and all actions resulting from the parse will be through
invocations of method functions of that object. */
-static po_method_ty exclude_methods =
+static abstract_po_reader_class_ty exclude_methods =
{
- sizeof (po_ty),
+ sizeof (abstract_po_reader_ty),
NULL, /* constructor */
NULL, /* destructor */
- exclude_directive_domain,
- exclude_directive_message,
NULL, /* parse_brief */
NULL, /* parse_debrief */
+ exclude_directive_domain,
+ exclude_directive_message,
NULL, /* comment */
NULL, /* comment_dot */
NULL, /* comment_filepos */
static void
read_exclusion_file (char *file_name)
{
- po_ty *pop;
+ abstract_po_reader_ty *pop;
- pop = po_alloc (&exclude_methods);
+ pop = po_reader_alloc (&exclude_methods);
po_scan_file (pop, file_name);
- po_free (pop);
+ po_reader_free (pop);
}