Blame gettext-tools/src/x-po.c

Packit Bot 06c835
/* xgettext PO and JavaProperties backends.
Packit Bot 06c835
   Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008-2009, 2015 Free
Packit Bot 06c835
   Software Foundation, Inc.
Packit Bot 06c835
Packit Bot 06c835
   This file was written by Peter Miller <millerp@canb.auug.org.au>
Packit Bot 06c835
Packit Bot 06c835
   This program is free software: you can redistribute it and/or modify
Packit Bot 06c835
   it under the terms of the GNU General Public License as published by
Packit Bot 06c835
   the Free Software Foundation; either version 3 of the License, or
Packit Bot 06c835
   (at your option) any later version.
Packit Bot 06c835
Packit Bot 06c835
   This program is distributed in the hope that it will be useful,
Packit Bot 06c835
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Bot 06c835
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Bot 06c835
   GNU General Public License for more details.
Packit Bot 06c835
Packit Bot 06c835
   You should have received a copy of the GNU General Public License
Packit Bot 06c835
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Bot 06c835
Packit Bot 06c835
#ifdef HAVE_CONFIG_H
Packit Bot 06c835
# include <config.h>
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
/* Specification.  */
Packit Bot 06c835
#include "x-po.h"
Packit Bot 06c835
#include "x-properties.h"
Packit Bot 06c835
#include "x-stringtable.h"
Packit Bot 06c835
Packit Bot 06c835
#include <stdio.h>
Packit Bot 06c835
#include <stdlib.h>
Packit Bot 06c835
#include <stdbool.h>
Packit Bot 06c835
#include <string.h>
Packit Bot 06c835
Packit Bot 06c835
#include "message.h"
Packit Bot 06c835
#include "xgettext.h"
Packit Bot 06c835
#include "xalloc.h"
Packit Bot 06c835
#include "read-catalog.h"
Packit Bot 06c835
#include "read-po.h"
Packit Bot 06c835
#include "read-properties.h"
Packit Bot 06c835
#include "read-stringtable.h"
Packit Bot 06c835
#include "po-lex.h"
Packit Bot 06c835
#include "gettext.h"
Packit Bot 06c835
Packit Bot 06c835
/* A convenience macro.  I don't like writing gettext() every time.  */
Packit Bot 06c835
#define _(str) gettext (str)
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
/* The charset found in the header entry.  */
Packit Bot 06c835
static char *header_charset;
Packit Bot 06c835
Packit Bot 06c835
/* Define a subclass extract_catalog_reader_ty of default_catalog_reader_ty.  */
Packit Bot 06c835
Packit Bot 06c835
static void
Packit Bot 06c835
extract_add_message (default_catalog_reader_ty *this,
Packit Bot 06c835
                     char *msgctxt,
Packit Bot 06c835
                     char *msgid,
Packit Bot 06c835
                     lex_pos_ty *msgid_pos,
Packit Bot 06c835
                     char *msgid_plural,
Packit Bot 06c835
                     char *msgstr, size_t msgstr_len,
Packit Bot 06c835
                     lex_pos_ty *msgstr_pos,
Packit Bot 06c835
                     char *prev_msgctxt,
Packit Bot 06c835
                     char *prev_msgid,
Packit Bot 06c835
                     char *prev_msgid_plural,
Packit Bot 06c835
                     bool force_fuzzy, bool obsolete)
Packit Bot 06c835
{
Packit Bot 06c835
  /* See whether we shall exclude this message.  */
Packit Bot 06c835
  if (exclude != NULL && message_list_search (exclude, msgctxt, msgid) != NULL)
Packit Bot 06c835
    goto discard;
Packit Bot 06c835
Packit Bot 06c835
  /* If the msgid is the empty string, it is the old header.  Throw it
Packit Bot 06c835
     away, we have constructed a new one.  Only remember its charset.
Packit Bot 06c835
     But if no new one was constructed, keep the old header.  This is useful
Packit Bot 06c835
     because the old header may contain a charset= directive.  */
Packit Bot 06c835
  if (msgctxt == NULL && *msgid == '\0' && !xgettext_omit_header)
Packit Bot 06c835
    {
Packit Bot 06c835
      {
Packit Bot 06c835
        const char *charsetstr = strstr (msgstr, "charset=");
Packit Bot 06c835
Packit Bot 06c835
        if (charsetstr != NULL)
Packit Bot 06c835
          {
Packit Bot 06c835
            size_t len;
Packit Bot 06c835
            char *charset;
Packit Bot 06c835
Packit Bot 06c835
            charsetstr += strlen ("charset=");
Packit Bot 06c835
            len = strcspn (charsetstr, " \t\n");
Packit Bot 06c835
            charset = XNMALLOC (len + 1, char);
Packit Bot 06c835
            memcpy (charset, charsetstr, len);
Packit Bot 06c835
            charset[len] = '\0';
Packit Bot 06c835
Packit Bot 06c835
            if (header_charset != NULL)
Packit Bot 06c835
              free (header_charset);
Packit Bot 06c835
            header_charset = charset;
Packit Bot 06c835
          }
Packit Bot 06c835
      }
Packit Bot 06c835
Packit Bot 06c835
     discard:
Packit Bot 06c835
      if (msgctxt != NULL)
Packit Bot 06c835
        free (msgctxt);
Packit Bot 06c835
      free (msgid);
Packit Bot 06c835
      if (msgid_plural != NULL)
Packit Bot 06c835
        free (msgid_plural);
Packit Bot 06c835
      free (msgstr);
Packit Bot 06c835
      if (prev_msgctxt != NULL)
Packit Bot 06c835
        free (prev_msgctxt);
Packit Bot 06c835
      if (prev_msgid != NULL)
Packit Bot 06c835
        free (prev_msgid);
Packit Bot 06c835
      if (prev_msgid_plural != NULL)
Packit Bot 06c835
        free (prev_msgid_plural);
Packit Bot 06c835
      return;
Packit Bot 06c835
    }
Packit Bot 06c835
Packit Bot 06c835
  /* Invoke superclass method.  */
Packit Bot 06c835
  default_add_message (this, msgctxt, msgid, msgid_pos, msgid_plural,
Packit Bot 06c835
                       msgstr, msgstr_len, msgstr_pos,
Packit Bot 06c835
                       prev_msgctxt, prev_msgid, prev_msgid_plural,
Packit Bot 06c835
                       force_fuzzy, obsolete);
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
/* So that the one parser can be used for multiple programs, and also
Packit Bot 06c835
   use good data hiding and encapsulation practices, an object
Packit Bot 06c835
   oriented approach has been taken.  An object instance is allocated,
Packit Bot 06c835
   and all actions resulting from the parse will be through
Packit Bot 06c835
   invocations of method functions of that object.  */
Packit Bot 06c835
Packit Bot 06c835
static default_catalog_reader_class_ty extract_methods =
Packit Bot 06c835
{
Packit Bot 06c835
  {
Packit Bot 06c835
    sizeof (default_catalog_reader_ty),
Packit Bot 06c835
    default_constructor,
Packit Bot 06c835
    default_destructor,
Packit Bot 06c835
    default_parse_brief,
Packit Bot 06c835
    default_parse_debrief,
Packit Bot 06c835
    default_directive_domain,
Packit Bot 06c835
    default_directive_message,
Packit Bot 06c835
    default_comment,
Packit Bot 06c835
    default_comment_dot,
Packit Bot 06c835
    default_comment_filepos,
Packit Bot 06c835
    default_comment_special
Packit Bot 06c835
  },
Packit Bot 06c835
  default_set_domain, /* set_domain */
Packit Bot 06c835
  extract_add_message, /* add_message */
Packit Bot 06c835
  NULL /* frob_new_message */
Packit Bot 06c835
};
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
static void
Packit Bot 06c835
extract (FILE *fp,
Packit Bot 06c835
         const char *real_filename, const char *logical_filename,
Packit Bot 06c835
         catalog_input_format_ty input_syntax,
Packit Bot 06c835
         msgdomain_list_ty *mdlp)
Packit Bot 06c835
{
Packit Bot 06c835
  default_catalog_reader_ty *pop;
Packit Bot 06c835
Packit Bot 06c835
  header_charset = NULL;
Packit Bot 06c835
Packit Bot 06c835
  pop = default_catalog_reader_alloc (&extract_methods);
Packit Bot 06c835
  pop->handle_comments = true;
Packit Bot 06c835
  pop->allow_domain_directives = false;
Packit Bot 06c835
  pop->allow_duplicates = false;
Packit Bot 06c835
  pop->allow_duplicates_if_same_msgstr = true;
Packit Bot 06c835
  pop->file_name = real_filename;
Packit Bot 06c835
  pop->mdlp = NULL;
Packit Bot 06c835
  pop->mlp = mdlp->item[0]->messages;
Packit Bot 06c835
  catalog_reader_parse ((abstract_catalog_reader_ty *) pop, fp, real_filename,
Packit Bot 06c835
                        logical_filename, input_syntax);
Packit Bot 06c835
  catalog_reader_free ((abstract_catalog_reader_ty *) pop);
Packit Bot 06c835
Packit Bot 06c835
  if (header_charset != NULL)
Packit Bot 06c835
    {
Packit Bot 06c835
      if (!xgettext_omit_header)
Packit Bot 06c835
        {
Packit Bot 06c835
          /* Put the old charset into the freshly constructed header entry.  */
Packit Bot 06c835
          message_ty *mp =
Packit Bot 06c835
            message_list_search (mdlp->item[0]->messages, NULL, "");
Packit Bot 06c835
Packit Bot 06c835
          if (mp != NULL && !mp->obsolete)
Packit Bot 06c835
            {
Packit Bot 06c835
              const char *header = mp->msgstr;
Packit Bot 06c835
Packit Bot 06c835
              if (header != NULL)
Packit Bot 06c835
                {
Packit Bot 06c835
                  const char *charsetstr = strstr (header, "charset=");
Packit Bot 06c835
Packit Bot 06c835
                  if (charsetstr != NULL)
Packit Bot 06c835
                    {
Packit Bot 06c835
                      size_t len, len1, len2, len3;
Packit Bot 06c835
                      char *new_header;
Packit Bot 06c835
Packit Bot 06c835
                      charsetstr += strlen ("charset=");
Packit Bot 06c835
                      len = strcspn (charsetstr, " \t\n");
Packit Bot 06c835
Packit Bot 06c835
                      len1 = charsetstr - header;
Packit Bot 06c835
                      len2 = strlen (header_charset);
Packit Bot 06c835
                      len3 = (header + strlen (header)) - (charsetstr + len);
Packit Bot 06c835
                      new_header = XNMALLOC (len1 + len2 + len3 + 1, char);
Packit Bot 06c835
                      memcpy (new_header, header, len1);
Packit Bot 06c835
                      memcpy (new_header + len1, header_charset, len2);
Packit Bot 06c835
                      memcpy (new_header + len1 + len2, charsetstr + len, len3 + 1);
Packit Bot 06c835
                      mp->msgstr = new_header;
Packit Bot 06c835
                      mp->msgstr_len = len1 + len2 + len3 + 1;
Packit Bot 06c835
                    }
Packit Bot 06c835
                }
Packit Bot 06c835
            }
Packit Bot 06c835
        }
Packit Bot 06c835
Packit Bot 06c835
      free (header_charset);
Packit Bot 06c835
    }
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
void
Packit Bot 06c835
extract_po (FILE *fp,
Packit Bot 06c835
            const char *real_filename, const char *logical_filename,
Packit Bot 06c835
            flag_context_list_table_ty *flag_table,
Packit Bot 06c835
            msgdomain_list_ty *mdlp)
Packit Bot 06c835
{
Packit Bot 06c835
  extract (fp, real_filename,  logical_filename, &input_format_po, mdlp);
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
void
Packit Bot 06c835
extract_properties (FILE *fp,
Packit Bot 06c835
                    const char *real_filename, const char *logical_filename,
Packit Bot 06c835
                    flag_context_list_table_ty *flag_table,
Packit Bot 06c835
                    msgdomain_list_ty *mdlp)
Packit Bot 06c835
{
Packit Bot 06c835
  extract (fp, real_filename,  logical_filename, &input_format_properties,
Packit Bot 06c835
           mdlp);
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
void
Packit Bot 06c835
extract_stringtable (FILE *fp,
Packit Bot 06c835
                     const char *real_filename, const char *logical_filename,
Packit Bot 06c835
                     flag_context_list_table_ty *flag_table,
Packit Bot 06c835
                     msgdomain_list_ty *mdlp)
Packit Bot 06c835
{
Packit Bot 06c835
  extract (fp, real_filename,  logical_filename, &input_format_stringtable,
Packit Bot 06c835
           mdlp);
Packit Bot 06c835
}