1/* ngettext - retrieve plural form strings from message catalog and print them. 2 Copyright (C) 1995-1997, 2000-2007 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17#ifdef HAVE_CONFIG_H 18# include <config.h> 19#endif 20 21#include <getopt.h> 22#include <stdbool.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <locale.h> 26#include <errno.h> 27 28#include "closeout.h" 29#include "error.h" 30#include "progname.h" 31#include "relocatable.h" 32#include "basename.h" 33#include "propername.h" 34#include "xsetenv.h" 35 36#define HAVE_SETLOCALE 1 37/* Make sure we use the included libintl, not the system's one. */ 38#undef _LIBINTL_H 39#include "libgnuintl.h" 40 41#define _(str) gettext (str) 42 43/* Long options. */ 44static const struct option long_options[] = 45{ 46 { "domain", required_argument, NULL, 'd' }, 47 { "env", required_argument, NULL, '=' }, 48 { "help", no_argument, NULL, 'h' }, 49 { "version", no_argument, NULL, 'V' }, 50 { NULL, 0, NULL, 0 } 51}; 52 53/* Forward declaration of local functions. */ 54static void usage (int __status) 55#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2) 56 __attribute__ ((noreturn)) 57#endif 58; 59 60int 61main (int argc, char *argv[]) 62{ 63 int optchar; 64 const char *msgid; 65 const char *msgid_plural; 66 const char *count; 67 unsigned long n; 68 69 /* Default values for command line options. */ 70 bool do_help = false; 71 bool do_version = false; 72 bool environ_changed = false; 73 const char *domain = getenv ("TEXTDOMAIN"); 74 const char *domaindir = getenv ("TEXTDOMAINDIR"); 75 76 /* Set program name for message texts. */ 77 set_program_name (argv[0]); 78 79#ifdef HAVE_SETLOCALE 80 /* Set locale via LC_ALL. */ 81 setlocale (LC_ALL, ""); 82#endif 83 84 /* Set the text message domain. */ 85 bindtextdomain (PACKAGE, relocate (LOCALEDIR)); 86 textdomain (PACKAGE); 87 88 /* Ensure that write errors on stdout are detected. */ 89 atexit (close_stdout); 90 91 /* Parse command line options. */ 92 while ((optchar = getopt_long (argc, argv, "+d:hV", long_options, NULL)) 93 != EOF) 94 switch (optchar) 95 { 96 case '\0': /* Long option. */ 97 break; 98 case 'd': 99 domain = optarg; 100 break; 101 case 'h': 102 do_help = true; 103 break; 104 case 'V': 105 do_version = true; 106 break; 107 case '=': 108 { 109 /* Undocumented option --env sets an environment variable. */ 110 char *separator = strchr (optarg, '='); 111 if (separator != NULL) 112 { 113 *separator = '\0'; 114 xsetenv (optarg, separator + 1, 1); 115 environ_changed = true; 116 break; 117 } 118 } 119 /*FALLTHROUGH*/ 120 default: 121 usage (EXIT_FAILURE); 122 } 123 124#ifdef HAVE_SETLOCALE 125 if (environ_changed) 126 /* Set locale again via LC_ALL. */ 127 setlocale (LC_ALL, ""); 128#endif 129 130 /* Version information is requested. */ 131 if (do_version) 132 { 133 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION); 134 /* xgettext: no-wrap */ 135 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\ 136License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\ 137This is free software: you are free to change and redistribute it.\n\ 138There is NO WARRANTY, to the extent permitted by law.\n\ 139"), 140 "1995-1997, 2000-2006"); 141 printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper")); 142 exit (EXIT_SUCCESS); 143 } 144 145 /* Help is requested. */ 146 if (do_help) 147 usage (EXIT_SUCCESS); 148 149 /* More optional command line options. */ 150 if (argc - optind <= 2) 151 error (EXIT_FAILURE, 0, _("missing arguments")); 152 153 /* Now the mandatory command line options. */ 154 msgid = argv[optind++]; 155 msgid_plural = argv[optind++]; 156 157 /* If no domain name is given we print the original string. 158 We mark this assigning NULL to domain. */ 159 if (domain == NULL || domain[0] == '\0') 160 domain = NULL; 161 else 162 /* Bind domain to appropriate directory. */ 163 if (domaindir != NULL && domaindir[0] != '\0') 164 bindtextdomain (domain, domaindir); 165 166 /* To speed up the plural-2 test, we accept more than one COUNT in one 167 call. */ 168 while (optind < argc) 169 { 170 count = argv[optind++]; 171 172 { 173 char *endp; 174 unsigned long tmp_val; 175 176 errno = 0; 177 tmp_val = strtoul (count, &endp, 10); 178 if (errno == 0 && count[0] != '\0' && endp[0] == '\0') 179 n = tmp_val; 180 else 181 /* When COUNT is not valid, use plural. */ 182 n = 99; 183 } 184 185 /* If no domain name is given we don't translate, and we use English 186 plural form handling. */ 187 if (domain == NULL) 188 fputs (n == 1 ? msgid : msgid_plural, stdout); 189 else 190 /* Write out the result. */ 191 fputs (dngettext (domain, msgid, msgid_plural, n), stdout); 192 } 193 194 exit (EXIT_SUCCESS); 195} 196 197 198/* Display usage information and exit. */ 199static void 200usage (int status) 201{ 202 if (status != EXIT_SUCCESS) 203 fprintf (stderr, _("Try `%s --help' for more information.\n"), 204 program_name); 205 else 206 { 207 /* xgettext: no-wrap */ 208 printf (_("\ 209Usage: %s [OPTION] MSGID MSGID-PLURAL COUNT...\n\ 210 -d, --domain=TEXTDOMAIN retrieve translated message from TEXTDOMAIN\n\ 211 -h, --help display this help and exit\n\ 212 -V, --version display version information and exit\n\ 213 MSGID MSGID-PLURAL translate MSGID (singular) / MSGID-PLURAL (plural)\n\ 214 COUNT choose singular/plural form based on this value\n"), 215 program_name); 216 /* xgettext: no-wrap */ 217 printf (_("\ 218\n\ 219If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\ 220environment variable TEXTDOMAIN. If the message catalog is not found in the\n\ 221regular directory, another location can be specified with the environment\n\ 222variable TEXTDOMAINDIR.\n\ 223Standard search directory: %s\n"), LOCALEDIR); 224 /* TRANSLATORS: The placeholder indicates the bug-reporting address 225 for this package. Please add _another line_ saying 226 "Report translation bugs to <...>\n" with the address for translation 227 bugs (typically your translation team's web or email address). */ 228 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), stdout); 229 } 230 231 exit (status); 232} 233