+2001-07-28 Bruno Haible <haible@clisp.cons.org>
+
+ * po-lex.h (lex_start, lex_end): New declarations.
+ * po-lex.c (lex_start): New function.
+ (lex_end): New function.
+ (lex_open): Call lex_start.
+ (lex_close): Call lex_end.
+ * open-po.h (open_po_file): Nop.
+ * open-po.c (open_po_file): Small optimization.
+ * po.h (po_scan): New declaration.
+ (po_scan_file): Renamed from po_scan.
+ * po.c (po_scan): New function.
+ (po_scan_file): Renamed from po_scan.
+ * msgcmp.c (grammar): Update po_scan_file call.
+ * msgfmt.c (grammar): Likewise.
+ * read-po.c (read_po_file): Likewise.
+ * x-po.h: New file.
+ * x-po.c: New file.
+ (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,
+ extract_methods): Moved here from xgettext.c.
+ (extract_po): New function, extracted from read_po_file.
+ * xgettext.h (line_comment, exclude): New declarations.
+ * xgettext.c: Include x-po.h.
+ (line_comment): Make non-static.
+ (exclude): Likewise.
+ (main): Update scan_po_file call.
+ (read_exclusion_file): Update po_scan_file call.
+ (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,
+ extract_methods): Move to x-po.c.
+ (scan_po_file): Renamed from read_po_file. Call xgettext_open and
+ extract_po.
+ (language_to_scanner): Use SCANNERS_PO.
+ (extension_to_language): Use EXTENSIONS_PO.
+ * Makefile.am (noinst_HEADERS): Add x-po.h.
+ (xgettext_SOURCES): Add x-po.c.
+
2001-07-27 Bruno Haible <haible@clisp.cons.org>
* x-c.h: New file.
noinst_HEADERS = pos.h message.h po-gram.h po-hash.h po-charset.h po-lex.h \
po.h open-po.h read-po.h str-list.h write-po.h dir-list.h file-list.h \
po-gram-gen.h po-hash-gen.h msgl-charset.h msgl-iconv.h msgl-ascii.h \
-msgl-cat.h xgettext.h x-c.h
+msgl-cat.h xgettext.h x-c.h x-po.h
EXTRA_DIST = FILES
msgunfmt_SOURCES = message.c msgunfmt.c str-list.c write-po.c msgl-ascii.c
xgettext_SOURCES = message.c open-po.c po-gram-gen.y po-hash-gen.y \
po-charset.c po-lex.c po.c str-list.c xgettext.c dir-list.c write-po.c \
-msgl-ascii.c file-list.c x-c.c
+msgl-ascii.c file-list.c x-c.c x-po.c
msgcat_SOURCES = msgcat.c message.c open-po.c po-gram-gen.y po-hash-gen.y \
po-charset.c po-lex.c po.c read-po.c str-list.c dir-list.c write-po.c \
msgl-ascii.c msgl-iconv.c msgl-cat.c file-list.c
msgdomain_list_ty *mdlp;
pop = po_alloc (&compare_methods);
- po_scan (pop, filename);
+ po_scan_file (pop, filename);
mdlp = ((compare_class_ty *)pop)->mdlp;
po_free (pop);
return mdlp;
po_ty *pop;
pop = po_alloc (&format_methods);
- po_scan (pop, filename);
+ po_scan_file (pop, filename);
po_free (pop);
}
/* Open 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. The
- file's pathname is returned in *FILE_NAME, for error message purposes. */
+ file's pathname is returned in *REAL_FILE_NAME_P, for error message
+ purposes. */
FILE *
-open_po_file (input_name, file_name)
+open_po_file (input_name, real_file_name_p)
const char *input_name;
- char **file_name;
+ char **real_file_name_p;
{
static const char *extension[] = { "", ".po", ".pot", };
+ char *file_name;
FILE *ret_val;
int j, k;
const char *dir;
if (strcmp (input_name, "-") == 0 || strcmp (input_name, "/dev/stdin") == 0)
{
- *file_name = xstrdup (_("<stdin>"));
+ *real_file_name_p = xstrdup (_("<stdin>"));
return stdin;
}
{
for (k = 0; k < SIZEOF (extension); ++k)
{
- *file_name = concatenated_pathname ("", input_name, extension[k]);
+ file_name = concatenated_pathname ("", input_name, extension[k]);
- ret_val = fopen (*file_name, "r");
+ ret_val = fopen (file_name, "r");
if (ret_val != NULL || errno != ENOENT)
- /* We found the file. */
- return ret_val;
+ {
+ /* We found the file. */
+ *real_file_name_p = file_name;
+ return ret_val;
+ }
- free (*file_name);
+ free (file_name);
}
}
else
for (j = 0; (dir = dir_list_nth (j)) != NULL; ++j)
for (k = 0; k < SIZEOF (extension); ++k)
{
- *file_name = concatenated_pathname (dir, input_name, extension[k]);
+ file_name = concatenated_pathname (dir, input_name, extension[k]);
- ret_val = fopen (*file_name, "r");
+ ret_val = fopen (file_name, "r");
if (ret_val != NULL || errno != ENOENT)
- return ret_val;
+ {
+ *real_file_name_p = file_name;
+ return ret_val;
+ }
- free (*file_name);
+ free (file_name);
}
}
/* File does not exist. */
- *file_name = xstrdup (input_name);
+ *real_file_name_p = xstrdup (input_name);
errno = ENOENT;
return NULL;
}
/* Open 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. The
- file's pathname is returned in *FILE_NAME, for error message purposes. */
-extern FILE *open_po_file PARAMS ((const char *input_name, char **file_name));
+ file's pathname is returned in *REAL_FILE_NAME_P, for error message
+ purposes. */
+extern FILE *open_po_file PARAMS ((const char *input_name,
+ char **real_file_name_p));
#endif /* _OPEN_PO_H */
static int control_sequence PARAMS ((void));
-/* Open the PO file FNAME and prepare its lexical analysis. */
+/* Prepare lexical analysis. */
void
-lex_open (fname)
- const char *fname;
+lex_start (fp, real_filename, logical_filename)
+ FILE *fp;
+ const char *real_filename;
+ const char *logical_filename;
{
- FILE *fp = open_po_file (fname, &gram_pos.file_name);
- if (!fp)
- error (EXIT_FAILURE, errno,
- _("error while opening \"%s\" for reading"), fname);
+ /* Ignore the logical_filename, because PO file entries already have
+ their file names attached. But use real_filename for error messages. */
+ gram_pos.file_name = xstrdup (real_filename);
+
mbfile_init (mbf, fp);
gram_pos.line_number = 1;
po_lex_charset_init ();
}
-
-/* Terminate lexical analysis and close the current PO file. */
-void
-lex_close ()
+/* Terminate lexical analysis. */
+FILE *
+lex_end ()
{
+ FILE *fp;
+
if (error_message_count > 0)
error (EXIT_FAILURE, 0,
ngettext ("found %d fatal error", "found %d fatal errors",
error_message_count),
error_message_count);
- if (mbf->fp != stdin)
- fclose (mbf->fp);
+ fp = mbf->fp;
mbf->fp = NULL;
gram_pos.file_name = NULL;
gram_pos.line_number = 0;
error_message_count = 0;
po_lex_obsolete = false;
po_lex_charset_close ();
+
+ return fp;
+}
+
+
+/* Open the PO file FNAME and prepare its lexical analysis. */
+void
+lex_open (fname)
+ const char *fname;
+{
+ char *real_filename;
+ FILE *fp = open_po_file (fname, &real_filename);
+ if (!fp)
+ error (EXIT_FAILURE, errno,
+ _("error while opening \"%s\" for reading"), fname);
+
+ lex_start (fp, real_filename, fname);
+}
+
+/* Terminate lexical analysis and close the current PO file. */
+void
+lex_close ()
+{
+ FILE *fp;
+
+ fp = lex_end ();
+
+ if (fp != stdin)
+ fclose (fp);
}
#define _PO_LEX_H
#include <sys/types.h>
+#include <stdio.h>
#include <stdbool.h>
#include "error.h"
#include "progname.h"
extern bool pass_obsolete_entries;
+/* Prepare lexical analysis. */
+extern void lex_start PARAMS ((FILE *fp, const char *real_filename,
+ const char *logical_filename));
+
+/* Terminate lexical analysis. */
+extern FILE *lex_end PARAMS ((void));
+
/* Open the PO file FNAME and prepare its lexical analysis. */
extern void lex_open PARAMS ((const char *fname));
void
-po_scan (pop, filename)
+po_scan (pop, fp, real_filename, logical_filename)
+ po_ty *pop;
+ FILE *fp;
+ const char *real_filename;
+ const char *logical_filename;
+{
+ extern int po_gram_parse PARAMS ((void));
+
+ /* The parse will call the po_callback_... functions (see below)
+ when the various directive are recognised. The callback_arg
+ variable is used to tell these functions which instance is to
+ have the relevant method invoked. */
+ callback_arg = pop;
+
+ /* Parse the stream's content. */
+ lex_start (fp, real_filename, logical_filename);
+ po_parse_brief (pop);
+ po_gram_parse ();
+ po_parse_debrief (pop);
+ lex_end ();
+ callback_arg = NULL;
+}
+
+
+void
+po_scan_file (pop, filename)
po_ty *pop;
const char *filename;
{
constructor. */
extern po_ty *po_alloc PARAMS ((po_method_ty *jtable));
-/* Read a PO file, and dispatch to the various po_method_ty methods. */
-extern void po_scan PARAMS ((po_ty *pop, const char *filename));
+/* Read a PO file from a stream, and dispatch to the various po_method_ty
+ methods. */
+extern void po_scan PARAMS ((po_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 PARAMS ((po_ty *pop, const char *filename));
/* Call the destructor and deallocate a po_ty (or derived class)
instance. */
pop = po_alloc (&readall_methods);
po_lex_pass_obsolete_entries (true);
- po_scan (pop, filename);
+ po_scan_file (pop, filename);
mdlp = ((readall_class_ty *) pop)->mdlp;
po_free (pop);
return mdlp;
-/* GNU gettext - internationalization aids
+/* xgettext C/C++/ObjectiveC backend.
Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
This file was written by Peter Miller <millerp@canb.auug.org.au>
--- /dev/null
+/* xgettext PO backend.
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "message.h"
+#include "x-po.h"
+#include "xgettext.h"
+#include "system.h"
+#include "po.h"
+#include "po-lex.h"
+#include "libgettext.h"
+
+/* A convenience macro. I don't like writing gettext() every time. */
+#define _(str) gettext (str)
+
+
+/* Prototypes for local functions. Needed to ensure compiler checking of
+ function argument counts despite of K&R C function definition syntax. */
+static void extract_constructor PARAMS ((po_ty *that));
+static void extract_directive_domain PARAMS ((po_ty *that, char *name));
+static void extract_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,
+ bool obsolete));
+static void extract_parse_brief PARAMS ((po_ty *that));
+static void extract_comment PARAMS ((po_ty *that, const char *s));
+static void extract_comment_dot PARAMS ((po_ty *that, const char *s));
+static void extract_comment_filepos PARAMS ((po_ty *that, const char *name,
+ int line));
+static void extract_comment_special PARAMS ((po_ty *that, const char *s));
+
+
+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_c_format is_c_format;
+ enum is_wrap do_wrap;
+
+ size_t filepos_count;
+ lex_pos_ty *filepos;
+};
+
+
+static void
+extract_constructor (that)
+ po_ty *that;
+{
+ extract_class_ty *this = (extract_class_ty *) that;
+
+ this->mlp = NULL; /* actually set in read_po_file, below */
+ this->comment = NULL;
+ this->comment_dot = NULL;
+ this->is_fuzzy = false;
+ this->is_c_format = undecided;
+ this->do_wrap = undecided;
+ this->filepos_count = 0;
+ this->filepos = NULL;
+}
+
+
+static void
+extract_directive_domain (that, name)
+ po_ty *that;
+ char *name;
+{
+ po_gram_error_at_line (&gram_pos,
+ _("this file may not contain domain directives"));
+}
+
+
+static void
+extract_directive_message (that, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos, obsolete)
+ 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_class_ty *this = (extract_class_ty *)that;
+ message_ty *mp;
+ size_t j;
+
+ /* See whether we shall exclude this message. */
+ if (exclude != NULL && message_list_search (exclude, msgid) != NULL)
+ goto discard;
+
+ /* If the msgid is the empty string, it is the old header.
+ Throw it away, we have constructed a new one. */
+ if (*msgid == '\0')
+ {
+ 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;
+ this->is_c_format = 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. 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;
+ }
+ mp->is_fuzzy = this->is_fuzzy;
+ mp->is_c_format = this->is_c_format;
+ 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);
+ free (pp->file_name);
+ }
+ if (this->filepos != NULL)
+ free (this->filepos);
+ this->filepos_count = 0;
+ this->filepos = NULL;
+ this->is_fuzzy = false;
+ this->is_c_format = undecided;
+ this->do_wrap = undecided;
+}
+
+
+static void
+extract_parse_brief (that)
+ po_ty *that;
+{
+ po_lex_pass_comments (true);
+}
+
+
+static void
+extract_comment (that, s)
+ 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 (that, s)
+ 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 (that, name, line)
+ po_ty *that;
+ const char *name;
+ int 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 (that, s)
+ po_ty *that;
+ const char *s;
+{
+ extract_class_ty *this = (extract_class_ty *) that;
+
+ if (strstr (s, "fuzzy") != NULL)
+ this->is_fuzzy = true;
+ this->is_c_format = parse_c_format_description_string (s);
+ this->do_wrap = parse_c_width_description_string (s);
+}
+
+
+/* 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 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
+};
+
+
+void
+extract_po (fp, real_filename, logical_filename, mdlp)
+ FILE *fp;
+ 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);
+}
--- /dev/null
+/* xgettext PO backend.
+ Copyright (C) 2001 Free Software Foundation, Inc.
+ Written by Bruno Haible <haible@clisp.cons.org>, 2001.
+
+ 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. */
+
+
+#define EXTENSIONS_PO \
+ { "po", "PO", }, \
+ { "pot", "PO", }, \
+
+#define SCANNERS_PO \
+ { "PO", scan_po_file, }, \
+
+/* Scan a PO file and add its translatable strings to mdlp. */
+extern void extract_po PARAMS ((FILE *fp, const char *real_filename,
+ const char *logical_filename,
+ msgdomain_list_ty *mdlp));
#include "x-c.h"
+#include "x-po.h"
/* If nonzero add all comments immediately preceding one of the keywords. */
static bool add_all_comments = false;
/* If nonzero add comments for file name and line number for each msgid. */
-static int line_comment;
+int line_comment;
/* Tag used in comment of prevailing domain. */
static char *comment_tag;
static int do_debug;
/* Content of .po files with symbols to be excluded. */
-static message_list_ty *exclude;
+message_list_ty *exclude;
/* Force output of PO file even if empty. */
static int force_po;
char **real_file_name_p));
static void scan_c_file PARAMS ((const char *file_name,
msgdomain_list_ty *mdlp));
-static void extract_constructor PARAMS ((po_ty *that));
-static void extract_directive_domain PARAMS ((po_ty *that, char *name));
-static void extract_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,
- bool obsolete));
-static void extract_parse_brief PARAMS ((po_ty *that));
-static void extract_comment PARAMS ((po_ty *that, const char *s));
-static void extract_comment_dot PARAMS ((po_ty *that, const char *s));
-static void extract_comment_filepos PARAMS ((po_ty *that, const char *name,
- int line));
-static void extract_comment_special PARAMS ((po_ty *that, const char *s));
-static void read_po_file PARAMS ((const char *file_name,
+static void scan_po_file PARAMS ((const char *file_name,
msgdomain_list_ty *mdlp));
static long difftm PARAMS ((const struct tm *a, const struct tm *b));
static message_ty *construct_header PARAMS ((void));
/* Read in the old messages, so that we can add to them. */
if (join_existing)
- read_po_file (file_name, mdlp);
+ scan_po_file (file_name, mdlp);
/* Process all input files. */
for (cnt = 0; cnt < file_list->nitems; ++cnt)
po_ty *pop;
pop = po_alloc (&exclude_methods);
- po_scan (pop, file_name);
+ po_scan_file (pop, file_name);
po_free (pop);
}
}
-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_c_format is_c_format;
- enum is_wrap do_wrap;
-
- size_t filepos_count;
- lex_pos_ty *filepos;
-};
-
-
-static void
-extract_constructor (that)
- po_ty *that;
-{
- extract_class_ty *this = (extract_class_ty *) that;
-
- this->mlp = NULL; /* actually set in read_po_file, below */
- this->comment = NULL;
- this->comment_dot = NULL;
- this->is_fuzzy = false;
- this->is_c_format = undecided;
- this->do_wrap = undecided;
- this->filepos_count = 0;
- this->filepos = NULL;
-}
-
-
-static void
-extract_directive_domain (that, name)
- po_ty *that;
- char *name;
-{
- po_gram_error_at_line (&gram_pos,
- _("this file may not contain domain directives"));
-}
-
-
-static void
-extract_directive_message (that, msgid, msgid_pos, msgid_plural,
- msgstr, msgstr_len, msgstr_pos, obsolete)
- 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_class_ty *this = (extract_class_ty *)that;
- message_ty *mp;
- size_t j;
-
- /* See whether we shall exclude this message. */
- if (exclude != NULL && message_list_search (exclude, msgid) != NULL)
- goto discard;
-
- /* If the msgid is the empty string, it is the old header.
- Throw it away, we have constructed a new one. */
- if (*msgid == '\0')
- {
- 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;
- this->is_c_format = 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. 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;
- }
- mp->is_fuzzy = this->is_fuzzy;
- mp->is_c_format = this->is_c_format;
- 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);
- free (pp->file_name);
- }
- if (this->filepos != NULL)
- free (this->filepos);
- this->filepos_count = 0;
- this->filepos = NULL;
- this->is_fuzzy = false;
- this->is_c_format = undecided;
- this->do_wrap = undecided;
-}
-
-
-static void
-extract_parse_brief (that)
- po_ty *that;
-{
- po_lex_pass_comments (true);
-}
-
-
-static void
-extract_comment (that, s)
- 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 (that, s)
- 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 (that, name, line)
- po_ty *that;
- const char *name;
- int 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 (that, s)
- po_ty *that;
- const char *s;
-{
- extract_class_ty *this = (extract_class_ty *) that;
-
- if (strstr (s, "fuzzy") != NULL)
- this->is_fuzzy = true;
- this->is_c_format = parse_c_format_description_string (s);
- this->do_wrap = parse_c_width_description_string (s);
-}
-
-
-/* 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 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
-};
-
-
/* Read the contents of the specified .po file into a message list. */
static void
-read_po_file (file_name, mdlp)
+scan_po_file (file_name, mdlp)
const char *file_name;
msgdomain_list_ty *mdlp;
{
- po_ty *pop = po_alloc (&extract_methods);
- ((extract_class_ty *) pop)->mlp = mdlp->item[0]->messages;
- po_scan (pop, file_name);
- po_free (pop);
+ char *logical_filename;
+ char *real_filename;
+ FILE *fp = xgettext_open (file_name, &logical_filename, &real_filename);
+
+ extract_po (fp, real_filename, logical_filename, mdlp);
+
+ if (fp != stdin)
+ fclose (fp);
+ free (logical_filename);
+ free (real_filename);
}
static table_ty table[] =
{
SCANNERS_C
- { "PO", read_po_file, },
+ SCANNERS_PO
/* Here will follow more languages and their scanners: awk, perl,
etc... Make sure new scanners honor the --exlude-file option. */
};
static table_ty table[] =
{
EXTENSIONS_C
- { "po", "PO", },
- { "pot", "PO", },
- { "pox", "PO", },
+ EXTENSIONS_PO
/* Here will follow more file extensions: sh, pl, tcl, lisp ... */
};
#include "message.h"
#include "pos.h"
+extern int line_comment;
+
+extern message_list_ty *exclude;
+
extern void xgettext_comment_add PARAMS ((const char *str));
extern const char *xgettext_comment PARAMS ((size_t n));
extern void xgettext_comment_reset PARAMS ((void));