(root)/
gettext-0.22.4/
gettext-tools/
src/
write-resources.c
       1  /* Writing C# .resources files.
       2     Copyright (C) 2003-2005, 2007-2009, 2010-2011, 2016, 2020 Free Software
       3     Foundation, Inc.
       4     Written by Bruno Haible <bruno@clisp.org>, 2003.
       5  
       6     This program is free software: you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifdef HAVE_CONFIG_H
      20  # include <config.h>
      21  #endif
      22  
      23  /* Specification.  */
      24  #include "write-resources.h"
      25  
      26  #include <errno.h>
      27  #include <stdbool.h>
      28  #include <stdlib.h>
      29  #include <stdio.h>
      30  #include <string.h>
      31  
      32  #include "error.h"
      33  #include "xerror.h"
      34  #include "relocatable.h"
      35  #include "csharpexec.h"
      36  #include "spawn-pipe.h"
      37  #include "wait-process.h"
      38  #include "message.h"
      39  #include "msgfmt.h"
      40  #include "msgl-iconv.h"
      41  #include "msgl-header.h"
      42  #include "po-charset.h"
      43  #include "xalloc.h"
      44  #include "concat-filename.h"
      45  #include "fwriteerror.h"
      46  #include "gettext.h"
      47  
      48  #define _(str) gettext (str)
      49  
      50  
      51  /* A .resources file has such a complex format that it's most easily generated
      52     through the C# class ResourceWriter.  So we start a C# process to execute
      53     the WriteResource program, sending it the msgid/msgstr pairs as
      54     NUL-terminated UTF-8 encoded strings.  */
      55  
      56  struct locals
      57  {
      58    /* IN */
      59    message_list_ty *mlp;
      60  };
      61  
      62  static bool
      63  execute_writing_input (const char *progname,
      64                         const char *prog_path, const char * const *prog_argv,
      65                         void *private_data)
      66  {
      67    struct locals *l = (struct locals *) private_data;
      68    pid_t child;
      69    int fd[1];
      70    FILE *fp;
      71    int exitstatus;
      72  
      73    /* Open a pipe to the C# execution engine.  */
      74    child = create_pipe_out (progname, prog_path, prog_argv, NULL,
      75                             NULL, false, true, true, fd);
      76  
      77    fp = fdopen (fd[0], "wb");
      78    if (fp == NULL)
      79      error (EXIT_FAILURE, errno, _("fdopen() failed"));
      80  
      81    /* Write the message list.  */
      82    {
      83      message_list_ty *mlp = l->mlp;
      84      size_t j;
      85  
      86      for (j = 0; j < mlp->nitems; j++)
      87        {
      88          message_ty *mp = mlp->item[j];
      89  
      90          fwrite (mp->msgid, 1, strlen (mp->msgid) + 1, fp);
      91          fwrite (mp->msgstr, 1, strlen (mp->msgstr) + 1, fp);
      92        }
      93    }
      94  
      95    if (fwriteerror (fp))
      96      error (EXIT_FAILURE, 0, _("error while writing to %s subprocess"),
      97             progname);
      98  
      99    /* Remove zombie process from process list, and retrieve exit status.  */
     100    /* He we can ignore SIGPIPE because WriteResource either writes to a file
     101       - then it never gets SIGPIPE - or to standard output, and in the latter
     102       case it has no side effects other than writing to standard output.  */
     103    exitstatus =
     104      wait_subprocess (child, progname, true, false, true, true, NULL);
     105    if (exitstatus != 0)
     106      error (EXIT_FAILURE, 0, _("%s subprocess failed with exit code %d"),
     107             progname, exitstatus);
     108  
     109    return false;
     110  }
     111  
     112  int
     113  msgdomain_write_csharp_resources (message_list_ty *mlp,
     114                                    const char *canon_encoding,
     115                                    const char *domain_name,
     116                                    const char *file_name)
     117  {
     118    /* If no entry for this domain don't even create the file.  */
     119    if (mlp->nitems != 0)
     120      {
     121        /* Determine whether mlp has entries with context.  */
     122        {
     123          bool has_context;
     124          size_t j;
     125  
     126          has_context = false;
     127          for (j = 0; j < mlp->nitems; j++)
     128            if (mlp->item[j]->msgctxt != NULL)
     129              has_context = true;
     130          if (has_context)
     131            {
     132              multiline_error (xstrdup (""),
     133                               xstrdup (_("\
     134  message catalog has context dependent translations\n\
     135  but the C# .resources format doesn't support contexts\n")));
     136              return 1;
     137            }
     138        }
     139  
     140        /* Determine whether mlp has plural entries.  */
     141        {
     142          bool has_plural;
     143          size_t j;
     144  
     145          has_plural = false;
     146          for (j = 0; j < mlp->nitems; j++)
     147            if (mlp->item[j]->msgid_plural != NULL)
     148              has_plural = true;
     149          if (has_plural)
     150            {
     151              multiline_error (xstrdup (""),
     152                               xstrdup (_("\
     153  message catalog has plural form translations\n\
     154  but the C# .resources format doesn't support plural handling\n")));
     155              return 1;
     156            }
     157        }
     158  
     159        /* Convert the messages to Unicode.  */
     160        iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL);
     161  
     162        /* Support for "reproducible builds": Delete information that may vary
     163           between builds in the same conditions.  */
     164        message_list_delete_header_field (mlp, "POT-Creation-Date:");
     165  
     166        /* Execute the WriteResource program.  */
     167        {
     168          const char *args[2];
     169          const char *gettextexedir;
     170          char *assembly_path;
     171          struct locals locals;
     172  
     173          /* Prepare arguments.  */
     174          args[0] = file_name;
     175          args[1] = NULL;
     176  
     177          /* Make it possible to override the .exe location.  This is
     178             necessary for running the testsuite before "make install".  */
     179          gettextexedir = getenv ("GETTEXTCSHARPEXEDIR");
     180          if (gettextexedir == NULL || gettextexedir[0] == '\0')
     181            gettextexedir = relocate (LIBDIR "/gettext");
     182  
     183          assembly_path =
     184            xconcatenated_filename (gettextexedir, "msgfmt.net", ".exe");
     185  
     186          locals.mlp = mlp;
     187  
     188          if (execute_csharp_program (assembly_path, NULL, 0,
     189                                      args,
     190                                      verbose > 0, false,
     191                                      execute_writing_input, &locals))
     192            /* An error message should already have been provided.  */
     193            exit (EXIT_FAILURE);
     194  
     195          free (assembly_path);
     196        }
     197      }
     198  
     199    return 0;
     200  }