summaryrefslogtreecommitdiff
path: root/gettext-tools/src/x-po.c
diff options
context:
space:
mode:
Diffstat (limited to 'gettext-tools/src/x-po.c')
-rw-r--r--gettext-tools/src/x-po.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/gettext-tools/src/x-po.c b/gettext-tools/src/x-po.c
new file mode 100644
index 0000000..89824e2
--- /dev/null
+++ b/gettext-tools/src/x-po.c
@@ -0,0 +1,240 @@
+/* xgettext PO and JavaProperties backends.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "x-po.h"
+#include "x-properties.h"
+#include "x-stringtable.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "message.h"
+#include "xgettext.h"
+#include "xalloc.h"
+#include "read-catalog.h"
+#include "read-po.h"
+#include "read-properties.h"
+#include "read-stringtable.h"
+#include "po-lex.h"
+#include "gettext.h"
+
+/* A convenience macro. I don't like writing gettext() every time. */
+#define _(str) gettext (str)
+
+
+/* The charset found in the header entry. */
+static char *header_charset;
+
+/* Define a subclass extract_catalog_reader_ty of default_catalog_reader_ty. */
+
+static void
+extract_add_message (default_catalog_reader_ty *this,
+ char *msgctxt,
+ char *msgid,
+ lex_pos_ty *msgid_pos,
+ char *msgid_plural,
+ char *msgstr, size_t msgstr_len,
+ lex_pos_ty *msgstr_pos,
+ char *prev_msgctxt,
+ char *prev_msgid,
+ char *prev_msgid_plural,
+ bool force_fuzzy, bool obsolete)
+{
+ /* See whether we shall exclude this message. */
+ if (exclude != NULL && message_list_search (exclude, msgctxt, 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. Only remember its charset.
+ But if no new one was constructed, keep the old header. This is useful
+ because the old header may contain a charset= directive. */
+ if (msgctxt == NULL && *msgid == '\0' && !xgettext_omit_header)
+ {
+ {
+ const char *charsetstr = strstr (msgstr, "charset=");
+
+ if (charsetstr != NULL)
+ {
+ size_t len;
+ char *charset;
+
+ charsetstr += strlen ("charset=");
+ len = strcspn (charsetstr, " \t\n");
+ charset = XNMALLOC (len + 1, char);
+ memcpy (charset, charsetstr, len);
+ charset[len] = '\0';
+
+ if (header_charset != NULL)
+ free (header_charset);
+ header_charset = charset;
+ }
+ }
+
+ discard:
+ if (msgctxt != NULL)
+ free (msgctxt);
+ free (msgid);
+ if (msgid_plural != NULL)
+ free (msgid_plural);
+ free (msgstr);
+ if (prev_msgctxt != NULL)
+ free (prev_msgctxt);
+ if (prev_msgid != NULL)
+ free (prev_msgid);
+ if (prev_msgid_plural != NULL)
+ free (prev_msgid_plural);
+ return;
+ }
+
+ /* Invoke superclass method. */
+ default_add_message (this, msgctxt, msgid, msgid_pos, msgid_plural,
+ msgstr, msgstr_len, msgstr_pos,
+ prev_msgctxt, prev_msgid, prev_msgid_plural,
+ force_fuzzy, obsolete);
+}
+
+
+/* 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 default_catalog_reader_class_ty extract_methods =
+{
+ {
+ sizeof (default_catalog_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 */
+};
+
+
+static void
+extract (FILE *fp,
+ const char *real_filename, const char *logical_filename,
+ catalog_input_format_ty input_syntax,
+ msgdomain_list_ty *mdlp)
+{
+ default_catalog_reader_ty *pop;
+
+ header_charset = NULL;
+
+ pop = default_catalog_reader_alloc (&extract_methods);
+ pop->handle_comments = true;
+ pop->allow_domain_directives = false;
+ pop->allow_duplicates = false;
+ pop->allow_duplicates_if_same_msgstr = true;
+ pop->file_name = real_filename;
+ pop->mdlp = NULL;
+ pop->mlp = mdlp->item[0]->messages;
+ catalog_reader_parse ((abstract_catalog_reader_ty *) pop, fp, real_filename,
+ logical_filename, input_syntax);
+ catalog_reader_free ((abstract_catalog_reader_ty *) pop);
+
+ if (header_charset != NULL)
+ {
+ if (!xgettext_omit_header)
+ {
+ /* Put the old charset into the freshly constructed header entry. */
+ message_ty *mp =
+ message_list_search (mdlp->item[0]->messages, NULL, "");
+
+ if (mp != NULL && !mp->obsolete)
+ {
+ const char *header = mp->msgstr;
+
+ if (header != NULL)
+ {
+ const char *charsetstr = strstr (header, "charset=");
+
+ if (charsetstr != NULL)
+ {
+ size_t len, len1, len2, len3;
+ char *new_header;
+
+ charsetstr += strlen ("charset=");
+ len = strcspn (charsetstr, " \t\n");
+
+ len1 = charsetstr - header;
+ len2 = strlen (header_charset);
+ len3 = (header + strlen (header)) - (charsetstr + len);
+ new_header = XNMALLOC (len1 + len2 + len3 + 1, char);
+ memcpy (new_header, header, len1);
+ memcpy (new_header + len1, header_charset, len2);
+ memcpy (new_header + len1 + len2, charsetstr + len, len3 + 1);
+ mp->msgstr = new_header;
+ mp->msgstr_len = len1 + len2 + len3 + 1;
+ }
+ }
+ }
+ }
+
+ free (header_charset);
+ }
+}
+
+
+void
+extract_po (FILE *fp,
+ const char *real_filename, const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp)
+{
+ extract (fp, real_filename, logical_filename, &input_format_po, mdlp);
+}
+
+
+void
+extract_properties (FILE *fp,
+ const char *real_filename, const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp)
+{
+ extract (fp, real_filename, logical_filename, &input_format_properties,
+ mdlp);
+}
+
+
+void
+extract_stringtable (FILE *fp,
+ const char *real_filename, const char *logical_filename,
+ flag_context_list_table_ty *flag_table,
+ msgdomain_list_ty *mdlp)
+{
+ extract (fp, real_filename, logical_filename, &input_format_stringtable,
+ mdlp);
+}