nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* gettext - retrieve text string from message catalog and print it. |
2 | Copyright (C) 1995-1997, 2000-2007, 2012, 2015-2016 Free Software |
||
3 | Foundation, Inc. |
||
4 | Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, May 1995. |
||
5 | |||
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. |
||
10 | |||
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. |
||
15 | |||
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/>. */ |
||
18 | |||
19 | #ifdef HAVE_CONFIG_H |
||
20 | # include <config.h> |
||
21 | #endif |
||
22 | |||
23 | #include <getopt.h> |
||
24 | #include <stdbool.h> |
||
25 | #include <stdio.h> |
||
26 | #include <stdlib.h> |
||
27 | #include <string.h> |
||
28 | #include <locale.h> |
||
29 | |||
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 "propername.h" |
||
37 | #include "gettext.h" |
||
38 | |||
39 | #define _(str) gettext (str) |
||
40 | |||
41 | /* If true, add newline after last string. This makes only sense in |
||
42 | the 'echo' emulation mode. */ |
||
43 | static bool add_newline; |
||
44 | |||
45 | /* If true, expand escape sequences in strings before looking in the |
||
46 | message catalog. */ |
||
47 | static bool do_expand; |
||
48 | |||
49 | /* Long options. */ |
||
50 | static const struct option long_options[] = |
||
51 | { |
||
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' }, |
||
56 | { NULL, 0, NULL, 0 } |
||
57 | }; |
||
58 | |||
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)) |
||
63 | #endif |
||
64 | ; |
||
65 | static const char *expand_escape (const char *str); |
||
66 | |||
67 | int |
||
68 | main (int argc, char *argv[]) |
||
69 | { |
||
70 | int optchar; |
||
71 | const char *msgid; |
||
72 | |||
73 | /* Default values for command line options. */ |
||
74 | bool do_help = false; |
||
75 | bool do_shell = false; |
||
76 | bool do_version = false; |
||
77 | const char *domain = getenv ("TEXTDOMAIN"); |
||
78 | const char *domaindir = getenv ("TEXTDOMAINDIR"); |
||
79 | add_newline = true; |
||
80 | do_expand = false; |
||
81 | |||
82 | /* Set program name for message texts. */ |
||
83 | set_program_name (argv[0]); |
||
84 | |||
85 | #ifdef HAVE_SETLOCALE |
||
86 | /* Set locale via LC_ALL. */ |
||
87 | setlocale (LC_ALL, ""); |
||
88 | #endif |
||
89 | |||
90 | /* Set the text message domain. */ |
||
91 | bindtextdomain (PACKAGE, relocate (LOCALEDIR)); |
||
92 | textdomain (PACKAGE); |
||
93 | |||
94 | /* Ensure that write errors on stdout are detected. */ |
||
95 | atexit (close_stdout); |
||
96 | |||
97 | /* Parse command line options. */ |
||
98 | while ((optchar = getopt_long (argc, argv, "+d:eEhnsV", long_options, NULL)) |
||
99 | != EOF) |
||
100 | switch (optchar) |
||
101 | { |
||
102 | case '\0': /* Long option. */ |
||
103 | break; |
||
104 | case 'd': |
||
105 | domain = optarg; |
||
106 | break; |
||
107 | case 'e': |
||
108 | do_expand = true; |
||
109 | break; |
||
110 | case 'E': |
||
111 | /* Ignore. Just for compatibility. */ |
||
112 | break; |
||
113 | case 'h': |
||
114 | do_help = true; |
||
115 | break; |
||
116 | case 'n': |
||
117 | add_newline = false; |
||
118 | break; |
||
119 | case 's': |
||
120 | do_shell = true; |
||
121 | break; |
||
122 | case 'V': |
||
123 | do_version = true; |
||
124 | break; |
||
125 | default: |
||
126 | usage (EXIT_FAILURE); |
||
127 | } |
||
128 | |||
129 | /* Version information is requested. */ |
||
130 | if (do_version) |
||
131 | { |
||
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\ |
||
138 | "), |
||
139 | "1995-1997, 2000-2007"); |
||
140 | printf (_("Written by %s.\n"), proper_name ("Ulrich Drepper")); |
||
141 | exit (EXIT_SUCCESS); |
||
142 | } |
||
143 | |||
144 | /* Help is requested. */ |
||
145 | if (do_help) |
||
146 | usage (EXIT_SUCCESS); |
||
147 | |||
148 | /* We have two major modes: use following Uniforum spec and as |
||
149 | internationalized 'echo' program. */ |
||
150 | if (!do_shell) |
||
151 | { |
||
152 | /* We have to write a single strings translation to stdout. */ |
||
153 | |||
154 | /* Get arguments. */ |
||
155 | switch (argc - optind) |
||
156 | { |
||
157 | default: |
||
158 | error (EXIT_FAILURE, 0, _("too many arguments")); |
||
159 | |||
160 | case 2: |
||
161 | domain = argv[optind++]; |
||
162 | /* FALLTHROUGH */ |
||
163 | |||
164 | case 1: |
||
165 | break; |
||
166 | |||
167 | case 0: |
||
168 | error (EXIT_FAILURE, 0, _("missing arguments")); |
||
169 | } |
||
170 | |||
171 | msgid = argv[optind++]; |
||
172 | |||
173 | /* Expand escape sequences if enabled. */ |
||
174 | if (do_expand) |
||
175 | msgid = expand_escape (msgid); |
||
176 | |||
177 | /* If no domain name is given we don't translate. */ |
||
178 | if (domain == NULL || domain[0] == '\0') |
||
179 | { |
||
180 | fputs (msgid, stdout); |
||
181 | } |
||
182 | else |
||
183 | { |
||
184 | /* Bind domain to appropriate directory. */ |
||
185 | if (domaindir != NULL && domaindir[0] != '\0') |
||
186 | bindtextdomain (domain, domaindir); |
||
187 | |||
188 | /* Write out the result. */ |
||
189 | fputs (dgettext (domain, msgid), stdout); |
||
190 | } |
||
191 | } |
||
192 | else |
||
193 | { |
||
194 | if (optind < argc) |
||
195 | { |
||
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') |
||
199 | domain = NULL; |
||
200 | else |
||
201 | /* Bind domain to appropriate directory. */ |
||
202 | if (domaindir != NULL && domaindir[0] != '\0') |
||
203 | bindtextdomain (domain, domaindir); |
||
204 | |||
205 | /* We have to simulate 'echo'. All arguments are strings. */ |
||
206 | do |
||
207 | { |
||
208 | msgid = argv[optind++]; |
||
209 | |||
210 | /* Expand escape sequences if enabled. */ |
||
211 | if (do_expand) |
||
212 | msgid = expand_escape (msgid); |
||
213 | |||
214 | /* Write out the result. */ |
||
215 | fputs (domain == NULL ? msgid : dgettext (domain, msgid), |
||
216 | stdout); |
||
217 | |||
218 | /* We separate the arguments by a single ' '. */ |
||
219 | if (optind < argc) |
||
220 | fputc (' ', stdout); |
||
221 | } |
||
222 | while (optind < argc); |
||
223 | } |
||
224 | |||
225 | /* If not otherwise told: add trailing newline. */ |
||
226 | if (add_newline) |
||
227 | fputc ('\n', stdout); |
||
228 | } |
||
229 | |||
230 | exit (EXIT_SUCCESS); |
||
231 | } |
||
232 | |||
233 | |||
234 | /* Display usage information and exit. */ |
||
235 | static void |
||
236 | usage (int status) |
||
237 | { |
||
238 | if (status != EXIT_SUCCESS) |
||
239 | fprintf (stderr, _("Try '%s --help' for more information.\n"), |
||
240 | program_name); |
||
241 | else |
||
242 | { |
||
243 | /* xgettext: no-wrap */ |
||
244 | printf (_("\ |
||
245 | Usage: %s [OPTION] [[TEXTDOMAIN] MSGID]\n\ |
||
246 | or: %s [OPTION] -s [MSGID]...\n\ |
||
247 | "), program_name, program_name); |
||
248 | printf ("\n"); |
||
249 | /* xgettext: no-wrap */ |
||
250 | printf (_("\ |
||
251 | Display native language translation of a textual message.\n")); |
||
252 | printf ("\n"); |
||
253 | /* xgettext: no-wrap */ |
||
254 | printf (_("\ |
||
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")); |
||
263 | printf ("\n"); |
||
264 | /* xgettext: no-wrap */ |
||
265 | printf (_("\ |
||
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@"); |
||
275 | printf ("\n"); |
||
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); |
||
281 | } |
||
282 | |||
283 | exit (status); |
||
284 | } |
||
285 | |||
286 | |||
287 | /* Expand some escape sequences found in the argument string. */ |
||
288 | static const char * |
||
289 | expand_escape (const char *str) |
||
290 | { |
||
291 | char *retval, *rp; |
||
292 | const char *cp = str; |
||
293 | |||
294 | for (;;) |
||
295 | { |
||
296 | while (cp[0] != '\0' && cp[0] != '\\') |
||
297 | ++cp; |
||
298 | if (cp[0] == '\0') |
||
299 | return str; |
||
300 | /* Found a backslash. */ |
||
301 | if (cp[1] == '\0') |
||
302 | return str; |
||
303 | if (strchr ("abcfnrtv\\01234567", cp[1]) != NULL) |
||
304 | break; |
||
305 | ++cp; |
||
306 | } |
||
307 | |||
308 | retval = XNMALLOC (strlen (str), char); |
||
309 | |||
310 | rp = retval + (cp - str); |
||
311 | memcpy (retval, str, cp - str); |
||
312 | |||
313 | do |
||
314 | { |
||
315 | /* Here cp[0] == '\\'. */ |
||
316 | switch (*++cp) |
||
317 | { |
||
318 | case 'a': /* alert */ |
||
319 | *rp++ = '\a'; |
||
320 | ++cp; |
||
321 | break; |
||
322 | case 'b': /* backspace */ |
||
323 | *rp++ = '\b'; |
||
324 | ++cp; |
||
325 | break; |
||
326 | case 'c': /* suppress trailing newline */ |
||
327 | add_newline = false; |
||
328 | ++cp; |
||
329 | break; |
||
330 | case 'f': /* form feed */ |
||
331 | *rp++ = '\f'; |
||
332 | ++cp; |
||
333 | break; |
||
334 | case 'n': /* new line */ |
||
335 | *rp++ = '\n'; |
||
336 | ++cp; |
||
337 | break; |
||
338 | case 'r': /* carriage return */ |
||
339 | *rp++ = '\r'; |
||
340 | ++cp; |
||
341 | break; |
||
342 | case 't': /* horizontal tab */ |
||
343 | *rp++ = '\t'; |
||
344 | ++cp; |
||
345 | break; |
||
346 | case 'v': /* vertical tab */ |
||
347 | *rp++ = '\v'; |
||
348 | ++cp; |
||
349 | break; |
||
350 | case '\\': |
||
351 | *rp = '\\'; |
||
352 | ++cp; |
||
353 | break; |
||
354 | case '0': case '1': case '2': case '3': |
||
355 | case '4': case '5': case '6': case '7': |
||
356 | { |
||
357 | int ch = *cp++ - '0'; |
||
358 | |||
359 | if (*cp >= '0' && *cp <= '7') |
||
360 | { |
||
361 | ch *= 8; |
||
362 | ch += *cp++ - '0'; |
||
363 | |||
364 | if (*cp >= '0' && *cp <= '7') |
||
365 | { |
||
366 | ch *= 8; |
||
367 | ch += *cp++ - '0'; |
||
368 | } |
||
369 | } |
||
370 | *rp = ch; |
||
371 | } |
||
372 | break; |
||
373 | default: |
||
374 | *rp = '\\'; |
||
375 | break; |
||
376 | } |
||
377 | |||
378 | while (cp[0] != '\0' && cp[0] != '\\') |
||
379 | *rp++ = *cp++; |
||
380 | } |
||
381 | while (cp[0] != '\0'); |
||
382 | |||
383 | /* Terminate string. */ |
||
384 | *rp = '\0'; |
||
385 | |||
386 | return (const char *) retval; |
||
387 | } |