1
/* ngettext - retrieve plural form string from message catalog and print it.
2
Copyright (C) 1995-1997, 2000-2007 Free Software Foundation, Inc.
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.
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.
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/>. */
32
#include "relocatable.h"
35
#include "propername.h"
38
#define _(str) gettext (str)
40
/* If true, expand escape sequences in strings before looking in the
45
static const struct option long_options[] =
47
{ "domain", required_argument, NULL, 'd' },
48
{ "help", no_argument, NULL, 'h' },
49
{ "version", no_argument, NULL, 'V' },
53
/* Forward declaration of local functions. */
54
static void usage (int status)
55
#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
56
__attribute__ ((noreturn))
59
static const char *expand_escape (const char *str);
62
main (int argc, char *argv[])
66
const char *msgid_plural;
70
/* Default values for command line options. */
72
bool do_version = false;
73
const char *domain = getenv ("TEXTDOMAIN");
74
const char *domaindir = getenv ("TEXTDOMAINDIR");
77
/* Set program name for message texts. */
78
set_program_name (argv[0]);
81
/* Set locale via LC_ALL. */
82
setlocale (LC_ALL, "");
85
/* Set the text message domain. */
86
bindtextdomain (PACKAGE, relocate (LOCALEDIR));
89
/* Ensure that write errors on stdout are detected. */
90
atexit (close_stdout);
92
/* Parse command line options. */
93
while ((optchar = getopt_long (argc, argv, "+d:eEhV", long_options, NULL))
97
case '\0': /* Long option. */
106
/* Ignore. Just for compatibility. */
115
usage (EXIT_FAILURE);
118
/* Version information is requested. */
121
printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
122
/* xgettext: no-wrap */
123
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
124
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
125
This is free software: you are free to change and redistribute it.\n\
126
There is NO WARRANTY, to the extent permitted by law.\n\
128
"1995-1997, 2000-2007");
129
printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
133
/* Help is requested. */
135
usage (EXIT_SUCCESS);
137
/* More optional command line options. */
138
switch (argc - optind)
141
error (EXIT_FAILURE, 0, _("too many arguments"));
144
domain = argv[optind++];
153
error (EXIT_FAILURE, 0, _("missing arguments"));
156
/* Now the mandatory command line options. */
157
msgid = argv[optind++];
158
msgid_plural = argv[optind++];
159
count = argv[optind++];
166
unsigned long tmp_val;
169
tmp_val = strtoul (count, &endp, 10);
170
if (errno == 0 && count[0] != '\0' && endp[0] == '\0')
173
/* When COUNT is not valid, use plural. */
177
/* Expand escape sequences if enabled. */
180
msgid = expand_escape (msgid);
181
msgid_plural = expand_escape (msgid_plural);
184
/* If no domain name is given we don't translate, and we use English
185
plural form handling. */
186
if (domain == NULL || domain[0] == '\0')
187
fputs (n == 1 ? msgid : msgid_plural, stdout);
190
/* Bind domain to appropriate directory. */
191
if (domaindir != NULL && domaindir[0] != '\0')
192
bindtextdomain (domain, domaindir);
194
/* Write out the result. */
195
fputs (dngettext (domain, msgid, msgid_plural, n), stdout);
202
/* Display usage information and exit. */
206
if (status != EXIT_SUCCESS)
207
fprintf (stderr, _("Try `%s --help' for more information.\n"),
211
/* xgettext: no-wrap */
213
Usage: %s [OPTION] [TEXTDOMAIN] MSGID MSGID-PLURAL COUNT\n\
216
/* xgettext: no-wrap */
218
Display native language translation of a textual message whose grammatical\n\
219
form depends on a number.\n"));
221
/* xgettext: no-wrap */
223
-d, --domain=TEXTDOMAIN retrieve translated message from TEXTDOMAIN\n\
224
-e enable expansion of some escape sequences\n\
225
-E (ignored for compatibility)\n\
226
-h, --help display this help and exit\n\
227
-V, --version display version information and exit\n\
228
[TEXTDOMAIN] retrieve translated message from TEXTDOMAIN\n\
229
MSGID MSGID-PLURAL translate MSGID (singular) / MSGID-PLURAL (plural)\n\
230
COUNT choose singular/plural form based on this value\n"));
232
/* xgettext: no-wrap */
234
If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
235
environment variable TEXTDOMAIN. If the message catalog is not found in the\n\
236
regular directory, another location can be specified with the environment\n\
237
variable TEXTDOMAINDIR.\n\
238
Standard search directory: %s\n"),
239
getenv ("IN_HELP2MAN") == NULL ? LOCALEDIR : "@localedir@");
241
/* TRANSLATORS: The placeholder indicates the bug-reporting address
242
for this package. Please add _another line_ saying
243
"Report translation bugs to <...>\n" with the address for translation
244
bugs (typically your translation team's web or email address). */
245
fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), stdout);
252
/* Expand some escape sequences found in the argument string. */
254
expand_escape (const char *str)
257
const char *cp = str;
261
while (cp[0] != '\0' && cp[0] != '\\')
265
/* Found a backslash. */
268
if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL)
273
retval = XNMALLOC (strlen (str), char);
275
rp = retval + (cp - str);
276
memcpy (retval, str, cp - str);
280
/* Here cp[0] == '\\'. */
283
case 'a': /* alert */
287
case 'b': /* backspace */
291
case 'f': /* form feed */
295
case 'n': /* new line */
299
case 'r': /* carriage return */
303
case 't': /* horizontal tab */
307
case 'v': /* vertical tab */
315
case '0': case '1': case '2': case '3':
316
case '4': case '5': case '6': case '7':
318
int ch = *cp++ - '0';
320
if (*cp >= '0' && *cp <= '7')
325
if (*cp >= '0' && *cp <= '7')
339
while (cp[0] != '\0' && cp[0] != '\\')
342
while (cp[0] != '\0');
344
/* Terminate string. */
347
return (const char *) retval;