#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <errno.h>
#include "closeout.h"
#include "error.h"
#include "progname.h"
#include "relocatable.h"
#include "basename.h"
#include "xalloc.h"
#include "exit.h"
#include "gettext.h"
#define _(str) gettext (str)
static int do_expand;
static const struct option long_options[] =
{
{ "domain", required_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
static void usage (int status)
#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
__attribute__ ((noreturn))
#endif
;
static const char *expand_escape (const char *str);
int
main (int argc, char *argv[])
{
int optchar;
const char *msgid;
const char *msgid_plural;
const char *count;
unsigned long n;
bool do_help = false;
bool do_version = false;
const char *domain = getenv ("TEXTDOMAIN");
const char *domaindir = getenv ("TEXTDOMAINDIR");
do_expand = false;
set_program_name (argv[0]);
#ifdef HAVE_SETLOCALE
setlocale (LC_ALL, "");
#endif
bindtextdomain (PACKAGE, relocate (LOCALEDIR));
textdomain (PACKAGE);
atexit (close_stdout);
while ((optchar = getopt_long (argc, argv, "+d:eEhV", long_options, NULL))
!= EOF)
switch (optchar)
{
case '\0':
break;
case 'd':
domain = optarg;
break;
case 'e':
do_expand = true;
break;
case 'E':
break;
case 'h':
do_help = true;
break;
case 'V':
do_version = true;
break;
default:
usage (EXIT_FAILURE);
}
if (do_version)
{
printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"),
"1995-1997, 2000-2003");
printf (_("Written by %s.\n"), "Ulrich Drepper");
exit (EXIT_SUCCESS);
}
if (do_help)
usage (EXIT_SUCCESS);
switch (argc - optind)
{
default:
error (EXIT_FAILURE, 0, _("too many arguments"));
case 4:
domain = argv[optind++];
case 3:
break;
case 2:
case 1:
case 0:
error (EXIT_FAILURE, 0, _("missing arguments"));
}
msgid = argv[optind++];
msgid_plural = argv[optind++];
count = argv[optind++];
if (optind != argc)
abort ();
{
char *endp;
unsigned long tmp_val;
errno = 0;
tmp_val = strtoul (count, &endp, 10);
if (errno == 0 && count[0] != '\0' && endp[0] == '\0')
n = tmp_val;
else
n = 99;
}
if (do_expand)
{
msgid = expand_escape (msgid);
msgid_plural = expand_escape (msgid_plural);
}
if (domain == NULL || domain[0] == '\0')
fputs (n == 1 ? msgid : msgid_plural, stdout);
else
{
if (domaindir != NULL && domaindir[0] != '\0')
bindtextdomain (domain, domaindir);
fputs (dngettext (domain, msgid, msgid_plural, n), stdout);
}
exit (EXIT_SUCCESS);
}
static void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
printf (_("\
Usage: %s [OPTION] [TEXTDOMAIN] MSGID MSGID-PLURAL COUNT\n\
"), program_name);
printf ("\n");
printf (_("\
Display native language translation of a textual message whose grammatical\n\
form depends on a number.\n"));
printf ("\n");
printf (_("\
-d, --domain=TEXTDOMAIN retrieve translated message from TEXTDOMAIN\n\
-e enable expansion of some escape sequences\n\
-E (ignored for compatibility)\n\
-h, --help display this help and exit\n\
-V, --version display version information and exit\n\
[TEXTDOMAIN] retrieve translated message from TEXTDOMAIN\n\
MSGID MSGID-PLURAL translate MSGID (singular) / MSGID-PLURAL (plural)\n\
COUNT choose singular/plural form based on this value\n"));
printf ("\n");
printf (_("\
If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
environment variable TEXTDOMAIN. If the message catalog is not found in the\n\
regular directory, another location can be specified with the environment\n\
variable TEXTDOMAINDIR.\n\
Standard search directory: %s\n"),
getenv ("IN_HELP2MAN") == NULL ? LOCALEDIR : "@localedir@");
printf ("\n");
fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), stdout);
}
exit (status);
}
static const char *
expand_escape (const char *str)
{
char *retval, *rp;
const char *cp = str;
do
{
while (cp[0] != '\0' && cp[0] != '\\')
++cp;
}
while (cp[0] != '\0' && cp[1] != '\0'
&& strchr ("bfnrt\\01234567", cp[1]) == NULL);
if (cp[0] == '\0')
return str;
retval = (char *) xmalloc (strlen (str));
rp = retval + (cp - str);
memcpy (retval, str, cp - str);
do
{
switch (*++cp)
{
case 'b':
*rp++ = '\b';
++cp;
break;
case 'f':
*rp++ = '\f';
++cp;
break;
case 'n':
*rp++ = '\n';
++cp;
break;
case 'r':
*rp++ = '\r';
++cp;
break;
case 't':
*rp++ = '\t';
++cp;
break;
case '\\':
*rp = '\\';
++cp;
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
{
int ch = *cp++ - '0';
if (*cp >= '0' && *cp <= '7')
{
ch *= 8;
ch += *cp++ - '0';
if (*cp >= '0' && *cp <= '7')
{
ch *= 8;
ch += *cp++ - '0';
}
}
*rp = ch;
}
break;
default:
*rp = '\\';
break;
}
while (cp[0] != '\0' && cp[0] != '\\')
*rp++ = *cp++;
}
while (cp[0] != '\0');
*rp = '\0';
return (const char *) retval;
}