#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 "closeout.h"
#include "error.h"
#include "progname.h"
#include "relocatable.h"
#include "basename.h"
#include "xalloc.h"
#include "exit.h"
#include "xsetenv.h"
#define HAVE_SETLOCALE 1
#undef _LIBINTL_H
#include "libgnuintl.h"
#define _(str) gettext (str)
static bool add_newline;
static bool do_expand;
static const struct option long_options[] =
{
{ "domain", required_argument, NULL, 'd' },
{ "env", required_argument, NULL, '=' },
{ "help", no_argument, NULL, 'h' },
{ "shell-script", no_argument, NULL, 's' },
{ "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;
bool do_help = false;
bool do_shell = false;
bool do_version = false;
bool environ_changed = false;
const char *domain = getenv ("TEXTDOMAIN");
const char *domaindir = getenv ("TEXTDOMAINDIR");
add_newline = true;
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:eEhnsV", 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 'n':
add_newline = false;
break;
case 's':
do_shell = true;
break;
case 'V':
do_version = true;
break;
case '=':
{
char *separator = strchr (optarg, '=');
if (separator != NULL)
{
*separator = '\0';
xsetenv (optarg, separator + 1, 1);
environ_changed = true;
break;
}
}
default:
usage (EXIT_FAILURE);
}
#ifdef HAVE_SETLOCALE
if (environ_changed)
setlocale (LC_ALL, "");
#endif
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);
if (!do_shell)
{
switch (argc - optind)
{
default:
error (EXIT_FAILURE, 0, _("too many arguments"));
case 2:
domain = argv[optind++];
case 1:
break;
case 0:
error (EXIT_FAILURE, 0, _("missing arguments"));
}
msgid = argv[optind++];
if (do_expand)
msgid = expand_escape (msgid);
if (domain == NULL || domain[0] == '\0')
{
fputs (msgid, stdout);
}
else
{
if (domaindir != NULL && domaindir[0] != '\0')
bindtextdomain (domain, domaindir);
fputs (dgettext (domain, msgid), stdout);
}
}
else
{
if (optind < argc)
{
if (domain == NULL || domain[0] == '\0')
domain = NULL;
else
if (domaindir != NULL && domaindir[0] != '\0')
bindtextdomain (domain, domaindir);
do
{
msgid = argv[optind++];
if (do_expand)
msgid = expand_escape (msgid);
fputs (domain == NULL ? msgid : dgettext (domain, msgid),
stdout);
if (optind < argc)
fputc (' ', stdout);
}
while (optind < argc);
}
if (add_newline)
fputc ('\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]\n\
or: %s [OPTION] -s [MSGID]...\n\
"), program_name, program_name);
printf ("\n");
printf (_("\
Display native language translation of a textual message.\n"));
printf ("\n");
printf (_("\
-d, --domain=TEXTDOMAIN retrieve translated messages from TEXTDOMAIN\n\
-e enable expansion of some escape sequences\n\
-E (ignored for compatibility)\n\
-h, --help display this help and exit\n\
-n suppress trailing newline\n\
-V, --version display version information and exit\n\
[TEXTDOMAIN] MSGID retrieve translated message corresponding\n\
to MSGID from TEXTDOMAIN\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\
When used with the -s option the program behaves like the `echo' command.\n\
But it does not simply copy its arguments to stdout. Instead those messages\n\
found in the selected catalog are translated.\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 ("bcfnrt\\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 'c':
add_newline = false;
++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;
}