1 /* Reading C# satellite assemblies. 2 Copyright (C) 2003-2004, 2006 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 2, or (at your option) 8 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, write to the Free Software Foundation, 17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 18 19 #ifdef HAVE_CONFIG_H 20 # include <config.h> 21 #endif 22 23 /* Specification. */ 24 #include "read-csharp.h" 25 26 #include <stdbool.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <errno.h> 30 31 #include "msgunfmt.h" 32 #include "relocatable.h" 33 #include "csharpexec.h" 34 #include "pipe.h" 35 #include "wait-process.h" 36 #include "read-catalog.h" 37 #include "read-po.h" 38 #include "xalloc.h" 39 #include "pathname.h" 40 #include "error.h" 41 #include "exit.h" 42 #include "gettext.h" 43 44 #define _(str) gettext (str) 45 46 47 /* A C# satellite assembly can only be manipulated by a C# execution engine. 48 So we start a C# process to execute the DumpResource program, and read its 49 output, which is .po format without comments. */ 50 51 struct locals 52 { 53 /* OUT */ 54 msgdomain_list_ty *mdlp; 55 }; 56 57 static bool 58 execute_and_read_po_output (const char *progname, 59 const char *prog_path, char **prog_argv, 60 void *private_data) 61 { 62 struct locals *l = (struct locals *) private_data; 63 pid_t child; 64 int fd[1]; 65 FILE *fp; 66 int exitstatus; 67 68 /* Open a pipe to the C# execution engine. */ 69 child = create_pipe_in (progname, prog_path, prog_argv, DEV_NULL, false, 70 true, true, fd); 71 72 fp = fdopen (fd[0], "r"); 73 if (fp == NULL) 74 error (EXIT_FAILURE, errno, _("fdopen() failed")); 75 76 /* Read the message list. */ 77 l->mdlp = read_catalog_stream (fp, "(pipe)", "(pipe)", &input_format_po); 78 79 fclose (fp); 80 81 /* Remove zombie process from process list, and retrieve exit status. */ 82 exitstatus = wait_subprocess (child, progname, false, false, true, true); 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 = concatenated_pathname (gettextexedir, "msgunfmt.net", ".exe"); 156 libdirs[0] = gettextlibdir; 157 if (execute_csharp_program (assembly_path, libdirs, 1, 158 args, 159 verbose, false, 160 execute_and_read_po_output, &locals)) 161 /* An error message should already have been provided. */ 162 exit (EXIT_FAILURE); 163 164 free (assembly_path); 165 free (culture_name); 166 167 return locals.mdlp; 168 } 169