1 /* gettext - retrieve text string from message catalog and print it.
2 Copyright (C) 1995-1997, 2000-2007, 2012, 2015 Free Software
4 Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, May 1995.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
33 #include "relocatable.h"
36 #include "propername.h"
39 #define _(str) gettext (str)
41 /* If true, add newline after last string. This makes only sense in
42 the 'echo' emulation mode. */
43 static bool add_newline;
45 /* If true, expand escape sequences in strings before looking in the
47 static bool do_expand;
50 static const struct option long_options[] =
52 { "domain", required_argument, NULL, 'd' },
53 { "help", no_argument, NULL, 'h' },
54 { "shell-script", no_argument, NULL, 's' },
55 { "version", no_argument, NULL, 'V' },
59 /* Forward declaration of local functions. */
60 static void usage (int status)
61 #if defined __GNUC__ && ((__GNUC__ == 2 && __GNUC_MINOR__ >= 5) || __GNUC__ > 2)
62 __attribute__ ((noreturn))
65 static const char *expand_escape (const char *str);
68 main (int argc, char *argv[])
73 /* Default values for command line options. */
75 bool do_shell = false;
76 bool do_version = false;
77 const char *domain = getenv ("TEXTDOMAIN");
78 const char *domaindir = getenv ("TEXTDOMAINDIR");
82 /* Set program name for message texts. */
83 set_program_name (argv[0]);
86 /* Set locale via LC_ALL. */
87 setlocale (LC_ALL, "");
90 /* Set the text message domain. */
91 bindtextdomain (PACKAGE, relocate (LOCALEDIR));
94 /* Ensure that write errors on stdout are detected. */
95 atexit (close_stdout);
97 /* Parse command line options. */
98 while ((optchar = getopt_long (argc, argv, "+d:eEhnsV", long_options, NULL))
102 case '\0': /* Long option. */
111 /* Ignore. Just for compatibility. */
126 usage (EXIT_FAILURE);
129 /* Version information is requested. */
132 printf ("%s (GNU %s) %s\n", basename (program_name), PACKAGE, VERSION);
133 /* xgettext: no-wrap */
134 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
135 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
136 This is free software: you are free to change and redistribute it.\n\
137 There is NO WARRANTY, to the extent permitted by law.\n\
139 "1995-1997, 2000-2007");
140 printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper"));
144 /* Help is requested. */
146 usage (EXIT_SUCCESS);
148 /* We have two major modes: use following Uniforum spec and as
149 internationalized 'echo' program. */
152 /* We have to write a single strings translation to stdout. */
155 switch (argc - optind)
158 error (EXIT_FAILURE, 0, _("too many arguments"));
161 domain = argv[optind++];
168 error (EXIT_FAILURE, 0, _("missing arguments"));
171 msgid = argv[optind++];
173 /* Expand escape sequences if enabled. */
175 msgid = expand_escape (msgid);
177 /* If no domain name is given we don't translate. */
178 if (domain == NULL || domain[0] == '\0')
180 fputs (msgid, stdout);
184 /* Bind domain to appropriate directory. */
185 if (domaindir != NULL && domaindir[0] != '\0')
186 bindtextdomain (domain, domaindir);
188 /* Write out the result. */
189 fputs (dgettext (domain, msgid), stdout);
196 /* If no domain name is given we print the original string.
197 We mark this assigning NULL to domain. */
198 if (domain == NULL || domain[0] == '\0')
201 /* Bind domain to appropriate directory. */
202 if (domaindir != NULL && domaindir[0] != '\0')
203 bindtextdomain (domain, domaindir);
205 /* We have to simulate 'echo'. All arguments are strings. */
208 msgid = argv[optind++];
210 /* Expand escape sequences if enabled. */
212 msgid = expand_escape (msgid);
214 /* Write out the result. */
215 fputs (domain == NULL ? msgid : dgettext (domain, msgid),
218 /* We separate the arguments by a single ' '. */
222 while (optind < argc);
225 /* If not otherwise told: add trailing newline. */
227 fputc ('\n', stdout);
234 /* Display usage information and exit. */
238 if (status != EXIT_SUCCESS)
239 fprintf (stderr, _("Try '%s --help' for more information.\n"),
243 /* xgettext: no-wrap */
245 Usage: %s [OPTION] [[TEXTDOMAIN] MSGID]\n\
246 or: %s [OPTION] -s [MSGID]...\n\
247 "), program_name, program_name);
249 /* xgettext: no-wrap */
251 Display native language translation of a textual message.\n"));
253 /* xgettext: no-wrap */
255 -d, --domain=TEXTDOMAIN retrieve translated messages from TEXTDOMAIN\n\
256 -e enable expansion of some escape sequences\n\
257 -E (ignored for compatibility)\n\
258 -h, --help display this help and exit\n\
259 -n suppress trailing newline\n\
260 -V, --version display version information and exit\n\
261 [TEXTDOMAIN] MSGID retrieve translated message corresponding\n\
262 to MSGID from TEXTDOMAIN\n"));
264 /* xgettext: no-wrap */
266 If the TEXTDOMAIN parameter is not given, the domain is determined from the\n\
267 environment variable TEXTDOMAIN. If the message catalog is not found in the\n\
268 regular directory, another location can be specified with the environment\n\
269 variable TEXTDOMAINDIR.\n\
270 When used with the -s option the program behaves like the 'echo' command.\n\
271 But it does not simply copy its arguments to stdout. Instead those messages\n\
272 found in the selected catalog are translated.\n\
273 Standard search directory: %s\n"),
274 getenv ("IN_HELP2MAN") == NULL ? LOCALEDIR : "@localedir@");
276 /* TRANSLATORS: The placeholder indicates the bug-reporting address
277 for this package. Please add _another line_ saying
278 "Report translation bugs to <...>\n" with the address for translation
279 bugs (typically your translation team's web or email address). */
280 fputs (_("Report bugs to <bug-gnu-gettext@gnu.org>.\n"), stdout);
287 /* Expand some escape sequences found in the argument string. */
289 expand_escape (const char *str)
292 const char *cp = str;
296 while (cp[0] != '\0' && cp[0] != '\\')
300 /* Found a backslash. */
303 if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL)
308 retval = XNMALLOC (strlen (str), char);
310 rp = retval + (cp - str);
311 memcpy (retval, str, cp - str);
315 /* Here cp[0] == '\\'. */
318 case 'a': /* alert */
322 case 'b': /* backspace */
326 case 'c': /* suppress trailing newline */
330 case 'f': /* form feed */
334 case 'n': /* new line */
338 case 'r': /* carriage return */
342 case 't': /* horizontal tab */
346 case 'v': /* vertical tab */
354 case '0': case '1': case '2': case '3':
355 case '4': case '5': case '6': case '7':
357 int ch = *cp++ - '0';
359 if (*cp >= '0' && *cp <= '7')
364 if (*cp >= '0' && *cp <= '7')
378 while (cp[0] != '\0' && cp[0] != '\\')
381 while (cp[0] != '\0');
383 /* Terminate string. */
386 return (const char *) retval;