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