• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/ap/gpl/timemachine/gettext-0.17/gettext-tools/tests/
1/* gettext - retrieve text string from message catalog and print it.
2   Copyright (C) 1995-1997, 2000-2007 Free Software Foundation, Inc.
3   Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, May 1995.
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
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 <string.h>
27#include <locale.h>
28
29#include "closeout.h"
30#include "error.h"
31#include "progname.h"
32#include "relocatable.h"
33#include "basename.h"
34#include "xalloc.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/* If true, add newline after last string.  This makes only sense in
46   the `echo' emulation mode.  */
47static bool add_newline;
48
49/* If true, expand escape sequences in strings before looking in the
50   message catalog.  */
51static bool do_expand;
52
53/* Long options.  */
54static const struct option long_options[] =
55{
56  { "domain", required_argument, NULL, 'd' },
57  { "env", required_argument, NULL, '=' },
58  { "help", no_argument, NULL, 'h' },
59  { "shell-script", no_argument, NULL, 's' },
60  { "version", no_argument, NULL, 'V' },
61  { NULL, 0, NULL, 0 }
62};
63
64/* Forward declaration of local functions.  */
65static void usage (int status)
66#if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
67     __attribute__ ((noreturn))
68#endif
69;
70static const char *expand_escape (const char *str);
71
72int
73main (int argc, char *argv[])
74{
75  int optchar;
76  const char *msgid;
77
78  /* Default values for command line options.  */
79  bool do_help = false;
80  bool do_shell = false;
81  bool do_version = false;
82  bool environ_changed = false;
83  const char *domain = getenv ("TEXTDOMAIN");
84  const char *domaindir = getenv ("TEXTDOMAINDIR");
85  add_newline = true;
86  do_expand = false;
87
88  /* Set program name for message texts.  */
89  set_program_name (argv[0]);
90
91#ifdef HAVE_SETLOCALE
92  /* Set locale via LC_ALL.  */
93  setlocale (LC_ALL, "");
94#endif
95
96  /* Set the text message domain.  */
97  bindtextdomain (PACKAGE, relocate (LOCALEDIR));
98  textdomain (PACKAGE);
99
100  /* Ensure that write errors on stdout are detected.  */
101  atexit (close_stdout);
102
103  /* Parse command line options.  */
104  while ((optchar = getopt_long (argc, argv, "+d:eEhnsV", long_options, NULL))
105	 != EOF)
106    switch (optchar)
107    {
108    case '\0':		/* Long option.  */
109      break;
110    case 'd':
111      domain = optarg;
112      break;
113    case 'e':
114      do_expand = true;
115      break;
116    case 'E':
117      /* Ignore.  Just for compatibility.  */
118      break;
119    case 'h':
120      do_help = true;
121      break;
122    case 'n':
123      add_newline = false;
124      break;
125    case 's':
126      do_shell = true;
127      break;
128    case 'V':
129      do_version = true;
130      break;
131    case '=':
132      {
133	/* Undocumented option --env sets an environment variable.  */
134	char *separator = strchr (optarg, '=');
135	if (separator != NULL)
136	  {
137	    *separator = '\0';
138	    xsetenv (optarg, separator + 1, 1);
139	    environ_changed = true;
140	    break;
141	  }
142      }
143      /*FALLTHROUGH*/
144    default:
145      usage (EXIT_FAILURE);
146    }
147
148#ifdef HAVE_SETLOCALE
149  if (environ_changed)
150    /* Set locale again via LC_ALL.  */
151    setlocale (LC_ALL, "");
152#endif
153
154  /* Version information is requested.  */
155  if (do_version)
156    {
157      printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
158      /* xgettext: no-wrap */
159      printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
160License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
161This is free software: you are free to change and redistribute it.\n\
162There is NO WARRANTY, to the extent permitted by law.\n\
163"),
164	      "1995-1997, 2000-2006");
165      printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
166      exit (EXIT_SUCCESS);
167    }
168
169  /* Help is requested.  */
170  if (do_help)
171    usage (EXIT_SUCCESS);
172
173  /* We have two major modes: use following Uniforum spec and as
174     internationalized `echo' program.  */
175  if (!do_shell)
176    {
177      /* We have to write a single strings translation to stdout.  */
178
179      /* Get arguments.  */
180      switch (argc - optind)
181	{
182	  default:
183	    error (EXIT_FAILURE, 0, _("too many arguments"));
184
185	  case 2:
186	    domain = argv[optind++];
187	    /* FALLTHROUGH */
188
189	  case 1:
190	    break;
191
192	  case 0:
193	    error (EXIT_FAILURE, 0, _("missing arguments"));
194	}
195
196      msgid = argv[optind++];
197
198      /* Expand escape sequences if enabled.  */
199      if (do_expand)
200	msgid = expand_escape (msgid);
201
202      /* If no domain name is given we don't translate.  */
203      if (domain == NULL || domain[0] == '\0')
204	{
205	  fputs (msgid, stdout);
206	}
207      else
208	{
209	  /* Bind domain to appropriate directory.  */
210	  if (domaindir != NULL && domaindir[0] != '\0')
211	    bindtextdomain (domain, domaindir);
212
213	  /* Write out the result.  */
214	  fputs (dgettext (domain, msgid), stdout);
215	}
216    }
217  else
218    {
219      if (optind < argc)
220	{
221	  /* If no domain name is given we print the original string.
222	     We mark this assigning NULL to domain.  */
223	  if (domain == NULL || domain[0] == '\0')
224	    domain = NULL;
225	  else
226	    /* Bind domain to appropriate directory.  */
227	    if (domaindir != NULL && domaindir[0] != '\0')
228	      bindtextdomain (domain, domaindir);
229
230	  /* We have to simulate `echo'.  All arguments are strings.  */
231	  do
232	    {
233	      msgid = argv[optind++];
234
235	      /* Expand escape sequences if enabled.  */
236	      if (do_expand)
237		msgid = expand_escape (msgid);
238
239	      /* Write out the result.  */
240	      fputs (domain == NULL ? msgid : dgettext (domain, msgid),
241		     stdout);
242
243	      /* We separate the arguments by a single ' '.  */
244	      if (optind < argc)
245		fputc (' ', stdout);
246	    }
247	  while (optind < argc);
248	}
249
250      /* If not otherwise told: add trailing newline.  */
251      if (add_newline)
252	fputc ('\n', stdout);
253    }
254
255  exit (EXIT_SUCCESS);
256}
257
258
259/* Display usage information and exit.  */
260static void
261usage (int status)
262{
263  if (status != EXIT_SUCCESS)
264    fprintf (stderr, _("Try `%s --help' for more information.\n"),
265	     program_name);
266  else
267    {
268      /* xgettext: no-wrap */
269      printf (_("\
270Usage: %s [OPTION] [[TEXTDOMAIN] MSGID]\n\
271or:    %s [OPTION] -s [MSGID]...\n\
272"), program_name, program_name);
273      printf ("\n");
274      /* xgettext: no-wrap */
275      printf (_("\
276Display native language translation of a textual message.\n"));
277      printf ("\n");
278      /* xgettext: no-wrap */
279      printf (_("\
280  -d, --domain=TEXTDOMAIN   retrieve translated messages from TEXTDOMAIN\n\
281  -e                        enable expansion of some escape sequences\n\
282  -E                        (ignored for compatibility)\n\
283  -h, --help                display this help and exit\n\
284  -n                        suppress trailing newline\n\
285  -V, --version             display version information and exit\n\
286  [TEXTDOMAIN] MSGID        retrieve translated message corresponding\n\
287                            to MSGID from TEXTDOMAIN\n"));
288      printf ("\n");
289      /* xgettext: no-wrap */
290      printf (_("\
291If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
292environment variable TEXTDOMAIN.  If the message catalog is not found in the\n\
293regular directory, another location can be specified with the environment\n\
294variable TEXTDOMAINDIR.\n\
295When used with the -s option the program behaves like the `echo' command.\n\
296But it does not simply copy its arguments to stdout.  Instead those messages\n\
297found in the selected catalog are translated.\n\
298Standard search directory: %s\n"),
299	      getenv ("IN_HELP2MAN") == NULL ? LOCALEDIR : "@localedir@");
300      printf ("\n");
301      /* TRANSLATORS: The placeholder indicates the bug-reporting address
302         for this package.  Please add _another line_ saying
303         "Report translation bugs to <...>\n" with the address for translation
304         bugs (typically your translation team's web or email address).  */
305      fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), stdout);
306    }
307
308  exit (status);
309}
310
311
312/* Expand some escape sequences found in the argument string.  */
313static const char *
314expand_escape (const char *str)
315{
316  char *retval, *rp;
317  const char *cp = str;
318
319  for (;;)
320    {
321      while (cp[0] != '\0' && cp[0] != '\\')
322	++cp;
323      if (cp[0] == '\0')
324	return str;
325      /* Found a backslash.  */
326      if (cp[1] == '\0')
327	return str;
328      if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL)
329	break;
330      ++cp;
331    }
332
333  retval = XNMALLOC (strlen (str), char);
334
335  rp = retval + (cp - str);
336  memcpy (retval, str, cp - str);
337
338  do
339    {
340      /* Here cp[0] == '\\'.  */
341      switch (*++cp)
342	{
343	case 'a':		/* alert */
344	  *rp++ = '\a';
345	  ++cp;
346	  break;
347	case 'b':		/* backspace */
348	  *rp++ = '\b';
349	  ++cp;
350	  break;
351	case 'c':		/* suppress trailing newline */
352	  add_newline = false;
353	  ++cp;
354	  break;
355	case 'f':		/* form feed */
356	  *rp++ = '\f';
357	  ++cp;
358	  break;
359	case 'n':		/* new line */
360	  *rp++ = '\n';
361	  ++cp;
362	  break;
363	case 'r':		/* carriage return */
364	  *rp++ = '\r';
365	  ++cp;
366	  break;
367	case 't':		/* horizontal tab */
368	  *rp++ = '\t';
369	  ++cp;
370	  break;
371	case 'v':		/* vertical tab */
372	  *rp++ = '\v';
373	  ++cp;
374	  break;
375	case '\\':
376	  *rp = '\\';
377	  ++cp;
378	  break;
379	case '0': case '1': case '2': case '3':
380	case '4': case '5': case '6': case '7':
381	  {
382	    int ch = *cp++ - '0';
383
384	    if (*cp >= '0' && *cp <= '7')
385	      {
386		ch *= 8;
387		ch += *cp++ - '0';
388
389		if (*cp >= '0' && *cp <= '7')
390		  {
391		    ch *= 8;
392		    ch += *cp++ - '0';
393		  }
394	      }
395	    *rp = ch;
396	  }
397	  break;
398	default:
399	  *rp = '\\';
400	  break;
401	}
402
403      while (cp[0] != '\0' && cp[0] != '\\')
404	*rp++ = *cp++;
405    }
406  while (cp[0] != '\0');
407
408  /* Terminate string.  */
409  *rp = '\0';
410
411  return (const char *) retval;
412}
413