No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gettext / gettext-tools / tests / tstgettext.c
blob681a4ff0ee94b037144b388e08e108c025d198c5
1 /* gettext - retrieve text string from message catalog and print it.
2 Copyright (C) 1995-1997, 2000-2005 Free Software Foundation, Inc.
3 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, May 1995.
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 2, or (at your option)
8 any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #include <getopt.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <locale.h>
30 #include "closeout.h"
31 #include "error.h"
32 #include "progname.h"
33 #include "relocatable.h"
34 #include "basename.h"
35 #include "xalloc.h"
36 #include "exit.h"
37 #include "xsetenv.h"
39 #define HAVE_SETLOCALE 1
40 /* Make sure we use the included libintl, not the system's one. */
41 #undef _LIBINTL_H
42 #include "libgnuintl.h"
44 #define _(str) gettext (str)
46 /* If true, add newline after last string. This makes only sense in
47 the `echo' emulation mode. */
48 static bool add_newline;
50 /* If true, expand escape sequences in strings before looking in the
51 message catalog. */
52 static bool do_expand;
54 /* Long options. */
55 static const struct option long_options[] =
57 { "domain", required_argument, NULL, 'd' },
58 { "env", required_argument, NULL, '=' },
59 { "help", no_argument, NULL, 'h' },
60 { "shell-script", no_argument, NULL, 's' },
61 { "version", no_argument, NULL, 'V' },
62 { NULL, 0, NULL, 0 }
65 /* Forward declaration of local functions. */
66 static void usage (int status)
67 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
68 __attribute__ ((noreturn))
69 #endif
71 static const char *expand_escape (const char *str);
73 int
74 main (int argc, char *argv[])
76 int optchar;
77 const char *msgid;
79 /* Default values for command line options. */
80 bool do_help = false;
81 bool do_shell = false;
82 bool do_version = false;
83 bool environ_changed = false;
84 const char *domain = getenv ("TEXTDOMAIN");
85 const char *domaindir = getenv ("TEXTDOMAINDIR");
86 add_newline = true;
87 do_expand = false;
89 /* Set program name for message texts. */
90 set_program_name (argv[0]);
92 #ifdef HAVE_SETLOCALE
93 /* Set locale via LC_ALL. */
94 setlocale (LC_ALL, "");
95 #endif
97 /* Set the text message domain. */
98 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
99 textdomain (PACKAGE);
101 /* Ensure that write errors on stdout are detected. */
102 atexit (close_stdout);
104 /* Parse command line options. */
105 while ((optchar = getopt_long (argc, argv, "+d:eEhnsV", long_options, NULL))
106 != EOF)
107 switch (optchar)
109 case '\0': /* Long option. */
110 break;
111 case 'd':
112 domain = optarg;
113 break;
114 case 'e':
115 do_expand = true;
116 break;
117 case 'E':
118 /* Ignore. Just for compatibility. */
119 break;
120 case 'h':
121 do_help = true;
122 break;
123 case 'n':
124 add_newline = false;
125 break;
126 case 's':
127 do_shell = true;
128 break;
129 case 'V':
130 do_version = true;
131 break;
132 case '=':
134 /* Undocumented option --env sets an environment variable. */
135 char *separator = strchr (optarg, '=');
136 if (separator != NULL)
138 *separator = '\0';
139 xsetenv (optarg, separator + 1, 1);
140 environ_changed = true;
141 break;
144 /*FALLTHROUGH*/
145 default:
146 usage (EXIT_FAILURE);
149 #ifdef HAVE_SETLOCALE
150 if (environ_changed)
151 /* Set locale again via LC_ALL. */
152 setlocale (LC_ALL, "");
153 #endif
155 /* Version information is requested. */
156 if (do_version)
158 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
159 /* xgettext: no-wrap */
160 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
161 This is free software; see the source for copying conditions. There is NO\n\
162 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
164 "1995-1997, 2000-2005");
165 printf (_("Written by %s.\n"), "Ulrich Drepper");
166 exit (EXIT_SUCCESS);
169 /* Help is requested. */
170 if (do_help)
171 usage (EXIT_SUCCESS);
173 /* We have two major modes: use following Uniforum spec and as
174 internationalized `echo' program. */
175 if (!do_shell)
177 /* We have to write a single strings translation to stdout. */
179 /* Get arguments. */
180 switch (argc - optind)
182 default:
183 error (EXIT_FAILURE, 0, _("too many arguments"));
185 case 2:
186 domain = argv[optind++];
187 /* FALLTHROUGH */
189 case 1:
190 break;
192 case 0:
193 error (EXIT_FAILURE, 0, _("missing arguments"));
196 msgid = argv[optind++];
198 /* Expand escape sequences if enabled. */
199 if (do_expand)
200 msgid = expand_escape (msgid);
202 /* If no domain name is given we don't translate. */
203 if (domain == NULL || domain[0] == '\0')
205 fputs (msgid, stdout);
207 else
209 /* Bind domain to appropriate directory. */
210 if (domaindir != NULL && domaindir[0] != '\0')
211 bindtextdomain (domain, domaindir);
213 /* Write out the result. */
214 fputs (dgettext (domain, msgid), stdout);
217 else
219 if (optind < argc)
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);
230 /* We have to simulate `echo'. All arguments are strings. */
233 msgid = argv[optind++];
235 /* Expand escape sequences if enabled. */
236 if (do_expand)
237 msgid = expand_escape (msgid);
239 /* Write out the result. */
240 fputs (domain == NULL ? msgid : dgettext (domain, msgid),
241 stdout);
243 /* We separate the arguments by a single ' '. */
244 if (optind < argc)
245 fputc (' ', stdout);
247 while (optind < argc);
250 /* If not otherwise told: add trailing newline. */
251 if (add_newline)
252 fputc ('\n', stdout);
255 exit (EXIT_SUCCESS);
259 /* Display usage information and exit. */
260 static void
261 usage (int status)
263 if (status != EXIT_SUCCESS)
264 fprintf (stderr, _("Try `%s --help' for more information.\n"),
265 program_name);
266 else
268 /* xgettext: no-wrap */
269 printf (_("\
270 Usage: %s [OPTION] [[TEXTDOMAIN] MSGID]\n\
271 or: %s [OPTION] -s [MSGID]...\n\
272 "), program_name, program_name);
273 printf ("\n");
274 /* xgettext: no-wrap */
275 printf (_("\
276 Display 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 (_("\
291 If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
292 environment variable TEXTDOMAIN. If the message catalog is not found in the\n\
293 regular directory, another location can be specified with the environment\n\
294 variable TEXTDOMAINDIR.\n\
295 When used with the -s option the program behaves like the `echo' command.\n\
296 But it does not simply copy its arguments to stdout. Instead those messages\n\
297 found in the selected catalog are translated.\n\
298 Standard search directory: %s\n"),
299 getenv ("IN_HELP2MAN") == NULL ? LOCALEDIR : "@localedir@");
300 printf ("\n");
301 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), stdout);
304 exit (status);
308 /* Expand some escape sequences found in the argument string. */
309 static const char *
310 expand_escape (const char *str)
312 char *retval, *rp;
313 const char *cp = str;
315 for (;;)
317 while (cp[0] != '\0' && cp[0] != '\\')
318 ++cp;
319 if (cp[0] == '\0')
320 return str;
321 /* Found a backslash. */
322 if (cp[1] == '\0')
323 return str;
324 if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL)
325 break;
326 ++cp;
329 retval = (char *) xmalloc (strlen (str));
331 rp = retval + (cp - str);
332 memcpy (retval, str, cp - str);
336 /* Here cp[0] == '\\'. */
337 switch (*++cp)
339 case 'a': /* alert */
340 *rp++ = '\a';
341 ++cp;
342 break;
343 case 'b': /* backspace */
344 *rp++ = '\b';
345 ++cp;
346 break;
347 case 'c': /* suppress trailing newline */
348 add_newline = false;
349 ++cp;
350 break;
351 case 'f': /* form feed */
352 *rp++ = '\f';
353 ++cp;
354 break;
355 case 'n': /* new line */
356 *rp++ = '\n';
357 ++cp;
358 break;
359 case 'r': /* carriage return */
360 *rp++ = '\r';
361 ++cp;
362 break;
363 case 't': /* horizontal tab */
364 *rp++ = '\t';
365 ++cp;
366 break;
367 case 'v': /* vertical tab */
368 *rp++ = '\v';
369 ++cp;
370 break;
371 case '\\':
372 *rp = '\\';
373 ++cp;
374 break;
375 case '0': case '1': case '2': case '3':
376 case '4': case '5': case '6': case '7':
378 int ch = *cp++ - '0';
380 if (*cp >= '0' && *cp <= '7')
382 ch *= 8;
383 ch += *cp++ - '0';
385 if (*cp >= '0' && *cp <= '7')
387 ch *= 8;
388 ch += *cp++ - '0';
391 *rp = ch;
393 break;
394 default:
395 *rp = '\\';
396 break;
399 while (cp[0] != '\0' && cp[0] != '\\')
400 *rp++ = *cp++;
402 while (cp[0] != '\0');
404 /* Terminate string. */
405 *rp = '\0';
407 return (const char *) retval;