1 /* gettext - retrieve text string from message catalog and print it.
2 Copyright (C) 1995-1997, 2000-2007, 2012 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 3 of the License, or
8 (at your option) 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, see <http://www.gnu.org/licenses/>. */
32 #include "relocatable.h"
35 #include "propername.h"
38 #define _(str) gettext (str)
40 /* If true, add newline after last string. This makes only sense in
41 the 'echo' emulation mode. */
42 static bool add_newline;
44 /* If true, expand escape sequences in strings before looking in the
46 static bool do_expand;
49 static const struct option long_options[] =
51 { "domain", required_argument, NULL, 'd' },
52 { "help", no_argument, NULL, 'h' },
53 { "shell-script", no_argument, NULL, 's' },
54 { "version", no_argument, NULL, 'V' },
58 /* Forward declaration of local functions. */
59 static void usage (int status)
60 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
61 __attribute__ ((noreturn))
64 static const char *expand_escape (const char *str);
67 main (int argc, char *argv[])
72 /* Default values for command line options. */
74 bool do_shell = false;
75 bool do_version = false;
76 const char *domain = getenv ("TEXTDOMAIN");
77 const char *domaindir = getenv ("TEXTDOMAINDIR");
81 /* Set program name for message texts. */
82 set_program_name (argv[0]);
85 /* Set locale via LC_ALL. */
86 setlocale (LC_ALL, "");
89 /* Set the text message domain. */
90 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
93 /* Ensure that write errors on stdout are detected. */
94 atexit (close_stdout);
96 /* Parse command line options. */
97 while ((optchar = getopt_long (argc, argv, "+d:eEhnsV", long_options, NULL))
101 case '\0': /* Long option. */
110 /* Ignore. Just for compatibility. */
125 usage (EXIT_FAILURE);
128 /* Version information is requested. */
131 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
132 /* xgettext: no-wrap */
133 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
134 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
135 This is free software: you are free to change and redistribute it.\n\
136 There is NO WARRANTY, to the extent permitted by law.\n\
138 "1995-1997, 2000-2007");
139 printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
143 /* Help is requested. */
145 usage (EXIT_SUCCESS);
147 /* We have two major modes: use following Uniforum spec and as
148 internationalized 'echo' program. */
151 /* We have to write a single strings translation to stdout. */
154 switch (argc - optind)
157 error (EXIT_FAILURE, 0, _("too many arguments"));
160 domain = argv[optind++];
167 error (EXIT_FAILURE, 0, _("missing arguments"));
170 msgid = argv[optind++];
172 /* Expand escape sequences if enabled. */
174 msgid = expand_escape (msgid);
176 /* If no domain name is given we don't translate. */
177 if (domain == NULL || domain[0] == '\0')
179 fputs (msgid, stdout);
183 /* Bind domain to appropriate directory. */
184 if (domaindir != NULL && domaindir[0] != '\0')
185 bindtextdomain (domain, domaindir);
187 /* Write out the result. */
188 fputs (dgettext (domain, msgid), stdout);
195 /* If no domain name is given we print the original string.
196 We mark this assigning NULL to domain. */
197 if (domain == NULL || domain[0] == '\0')
200 /* Bind domain to appropriate directory. */
201 if (domaindir != NULL && domaindir[0] != '\0')
202 bindtextdomain (domain, domaindir);
204 /* We have to simulate 'echo'. All arguments are strings. */
207 msgid = argv[optind++];
209 /* Expand escape sequences if enabled. */
211 msgid = expand_escape (msgid);
213 /* Write out the result. */
214 fputs (domain == NULL ? msgid : dgettext (domain, msgid),
217 /* We separate the arguments by a single ' '. */
221 while (optind < argc);
224 /* If not otherwise told: add trailing newline. */
226 fputc ('\n', stdout);
233 /* Display usage information and exit. */
237 if (status != EXIT_SUCCESS)
238 fprintf (stderr, _("Try '%s --help' for more information.\n"),
242 /* xgettext: no-wrap */
244 Usage: %s [OPTION] [[TEXTDOMAIN] MSGID]\n\
245 or: %s [OPTION] -s [MSGID]...\n\
246 "), program_name, program_name);
248 /* xgettext: no-wrap */
250 Display native language translation of a textual message.\n"));
252 /* xgettext: no-wrap */
254 -d, --domain=TEXTDOMAIN retrieve translated messages from TEXTDOMAIN\n\
255 -e enable expansion of some escape sequences\n\
256 -E (ignored for compatibility)\n\
257 -h, --help display this help and exit\n\
258 -n suppress trailing newline\n\
259 -V, --version display version information and exit\n\
260 [TEXTDOMAIN] MSGID retrieve translated message corresponding\n\
261 to MSGID from TEXTDOMAIN\n"));
263 /* xgettext: no-wrap */
265 If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
266 environment variable TEXTDOMAIN. If the message catalog is not found in the\n\
267 regular directory, another location can be specified with the environment\n\
268 variable TEXTDOMAINDIR.\n\
269 When used with the -s option the program behaves like the 'echo' command.\n\
270 But it does not simply copy its arguments to stdout. Instead those messages\n\
271 found in the selected catalog are translated.\n\
272 Standard search directory: %s\n"),
273 getenv ("IN_HELP2MAN") == NULL ? LOCALEDIR : "@localedir@");
275 /* TRANSLATORS: The placeholder indicates the bug-reporting address
276 for this package. Please add _another line_ saying
277 "Report translation bugs to <...>\n" with the address for translation
278 bugs (typically your translation team's web or email address). */
279 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), stdout);
286 /* Expand some escape sequences found in the argument string. */
288 expand_escape (const char *str)
291 const char *cp = str;
295 while (cp[0] != '\0' && cp[0] != '\\')
299 /* Found a backslash. */
302 if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL)
307 retval = XNMALLOC (strlen (str), char);
309 rp = retval + (cp - str);
310 memcpy (retval, str, cp - str);
314 /* Here cp[0] == '\\'. */
317 case 'a': /* alert */
321 case 'b': /* backspace */
325 case 'c': /* suppress trailing newline */
329 case 'f': /* form feed */
333 case 'n': /* new line */
337 case 'r': /* carriage return */
341 case 't': /* horizontal tab */
345 case 'v': /* vertical tab */
353 case '0': case '1': case '2': case '3':
354 case '4': case '5': case '6': case '7':
356 int ch = *cp++ - '0';
358 if (*cp >= '0' && *cp <= '7')
363 if (*cp >= '0' && *cp <= '7')
377 while (cp[0] != '\0' && cp[0] != '\\')
380 while (cp[0] != '\0');
382 /* Terminate string. */
385 return (const char *) retval;