(root)/
gettext-0.22.4/
gettext-tools/
src/
read-csharp.c
       1  /* Reading C# satellite assemblies.
       2     Copyright (C) 2003-2004, 2006-2008, 2010-2011, 2020 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2003.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation; either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifdef HAVE_CONFIG_H
      19  # include <config.h>
      20  #endif
      21  
      22  /* Specification.  */
      23  #include "read-csharp.h"
      24  
      25  #include <stdbool.h>
      26  #include <stdio.h>
      27  #include <stdlib.h>
      28  #include <errno.h>
      29  
      30  #include "msgunfmt.h"
      31  #include "relocatable.h"
      32  #include "csharpexec.h"
      33  #include "spawn-pipe.h"
      34  #include "wait-process.h"
      35  #include "read-catalog.h"
      36  #include "read-po.h"
      37  #include "xalloc.h"
      38  #include "concat-filename.h"
      39  #include "error.h"
      40  #include "gettext.h"
      41  
      42  #define _(str) gettext (str)
      43  
      44  
      45  /* A C# satellite assembly can only be manipulated by a C# execution engine.
      46     So we start a C# process to execute the DumpResource program, and read its
      47     output, which is .po format without comments.  */
      48  
      49  struct locals
      50  {
      51    /* OUT */
      52    msgdomain_list_ty *mdlp;
      53  };
      54  
      55  static bool
      56  execute_and_read_po_output (const char *progname,
      57                              const char *prog_path,
      58                              const char * const *prog_argv,
      59                              void *private_data)
      60  {
      61    struct locals *l = (struct locals *) private_data;
      62    pid_t child;
      63    int fd[1];
      64    FILE *fp;
      65    int exitstatus;
      66  
      67    /* Open a pipe to the C# execution engine.  */
      68    child = create_pipe_in (progname, prog_path, prog_argv, NULL,
      69                            DEV_NULL, false, true, true, fd);
      70  
      71    fp = fdopen (fd[0], "r");
      72    if (fp == NULL)
      73      error (EXIT_FAILURE, errno, _("fdopen() failed"));
      74  
      75    /* Read the message list.  */
      76    l->mdlp = read_catalog_stream (fp, "(pipe)", "(pipe)", &input_format_po);
      77  
      78    fclose (fp);
      79  
      80    /* Remove zombie process from process list, and retrieve exit status.  */
      81    exitstatus =
      82      wait_subprocess (child, progname, false, false, true, true, NULL);
      83    if (exitstatus != 0)
      84      error (EXIT_FAILURE, 0, _("%s subprocess failed with exit code %d"),
      85             progname, exitstatus);
      86  
      87    return false;
      88  }
      89  
      90  
      91  msgdomain_list_ty *
      92  msgdomain_read_csharp (const char *resource_name, const char *locale_name,
      93                         const char *directory)
      94  {
      95    char *culture_name;
      96    const char *args[4];
      97    const char *gettextexedir;
      98    const char *gettextlibdir;
      99    char *assembly_path;
     100    const char *libdirs[1];
     101    struct locals locals;
     102  
     103    /* Assign a default value to the resource name.  */
     104    if (resource_name == NULL)
     105      resource_name = "Messages";
     106  
     107    /* Convert the locale name to a .NET specific culture name.  */
     108    culture_name = xstrdup (locale_name);
     109    {
     110      char *p;
     111      for (p = culture_name; *p != '\0'; p++)
     112        if (*p == '_')
     113          *p = '-';
     114      if (strncmp (culture_name, "sr-CS", 5) == 0)
     115        memcpy (culture_name, "sr-SP", 5);
     116      p = strchr (culture_name, '@');
     117      if (p != NULL)
     118        {
     119          if (strcmp (p, "@latin") == 0)
     120            strcpy (p, "-Latn");
     121          else if (strcmp (p, "@cyrillic") == 0)
     122            strcpy (p, "-Cyrl");
     123        }
     124      if (strcmp (culture_name, "sr-SP") == 0)
     125        {
     126          free (culture_name);
     127          culture_name = xstrdup ("sr-SP-Latn");
     128        }
     129      else if (strcmp (culture_name, "uz-UZ") == 0)
     130        {
     131          free (culture_name);
     132          culture_name = xstrdup ("uz-UZ-Latn");
     133        }
     134    }
     135  
     136    /* Prepare arguments.  */
     137    args[0] = directory;
     138    args[1] = resource_name;
     139    args[2] = culture_name;
     140    args[3] = NULL;
     141  
     142    /* Make it possible to override the .exe location.  This is
     143       necessary for running the testsuite before "make install".  */
     144    gettextexedir = getenv ("GETTEXTCSHARPEXEDIR");
     145    if (gettextexedir == NULL || gettextexedir[0] == '\0')
     146      gettextexedir = relocate (LIBDIR "/gettext");
     147  
     148    /* Make it possible to override the .dll location.  This is
     149       necessary for running the testsuite before "make install".  */
     150    gettextlibdir = getenv ("GETTEXTCSHARPLIBDIR");
     151    if (gettextlibdir == NULL || gettextlibdir[0] == '\0')
     152      gettextlibdir = relocate (LIBDIR);
     153  
     154    /* Dump the resource and retrieve the resulting output.  */
     155    assembly_path =
     156      xconcatenated_filename (gettextexedir, "msgunfmt.net", ".exe");
     157    libdirs[0] = gettextlibdir;
     158    if (execute_csharp_program (assembly_path, libdirs, 1,
     159                                args,
     160                                verbose, false,
     161                                execute_and_read_po_output, &locals))
     162      /* An error message should already have been provided.  */
     163      exit (EXIT_FAILURE);
     164  
     165    free (assembly_path);
     166    free (culture_name);
     167  
     168    return locals.mdlp;
     169  }