diff options
Diffstat (limited to 'gettext-tools/src/x-po.c')
-rw-r--r-- | gettext-tools/src/x-po.c | 240 |
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); +} |