]> git.ipfire.org Git - thirdparty/bash.git/blob - locale.c
fix for SIGINT in sourced script
[thirdparty/bash.git] / locale.c
1 /* locale.c - Miscellaneous internationalization functions. */
2
3 /* Copyright (C) 1996-2009,2012 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24
25 #if defined (HAVE_UNISTD_H)
26 # include <unistd.h>
27 #endif
28
29 #if HAVE_LANGINFO_CODESET
30 # include <langinfo.h>
31 #endif
32
33 #include "bashintl.h"
34 #include "bashansi.h"
35 #include <stdio.h>
36 #include "chartypes.h"
37 #include <errno.h>
38
39 #include "shell.h"
40 #include "input.h" /* For bash_input */
41
42 #ifndef errno
43 extern int errno;
44 #endif
45
46 int locale_utf8locale; /* unused for now */
47 int locale_mb_cur_max; /* value of MB_CUR_MAX for current locale (LC_CTYPE) */
48
49 extern int dump_translatable_strings, dump_po_strings;
50
51 /* The current locale when the program begins */
52 static char *default_locale;
53
54 /* The current domain for textdomain(3). */
55 static char *default_domain;
56 static char *default_dir;
57
58 /* tracks the value of LC_ALL; used to override values for other locale
59 categories */
60 static char *lc_all;
61
62 /* tracks the value of LC_ALL; used to provide defaults for locale
63 categories */
64 static char *lang;
65
66 /* Called to reset all of the locale variables to their appropriate values
67 if (and only if) LC_ALL has not been assigned a value. */
68 static int reset_locale_vars __P((void));
69
70 static void locale_setblanks __P((void));
71 static int locale_isutf8 __P((char *));
72
73 /* Set the value of default_locale and make the current locale the
74 system default locale. This should be called very early in main(). */
75 void
76 set_default_locale ()
77 {
78 #if defined (HAVE_SETLOCALE)
79 default_locale = setlocale (LC_ALL, "");
80 if (default_locale)
81 default_locale = savestring (default_locale);
82 #endif /* HAVE_SETLOCALE */
83 bindtextdomain (PACKAGE, LOCALEDIR);
84 textdomain (PACKAGE);
85
86 locale_mb_cur_max = MB_CUR_MAX;
87 }
88
89 /* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and
90 LC_TIME if they are not specified in the environment, but LC_ALL is. This
91 should be called from main() after parsing the environment. */
92 void
93 set_default_locale_vars ()
94 {
95 char *val;
96
97 #if defined (HAVE_SETLOCALE)
98
99 # if defined (LC_CTYPE)
100 val = get_string_value ("LC_CTYPE");
101 if (val == 0 && lc_all && *lc_all)
102 {
103 setlocale (LC_CTYPE, lc_all);
104 locale_setblanks ();
105 locale_mb_cur_max = MB_CUR_MAX;
106 u32reset ();
107 }
108 # endif
109
110 # if defined (LC_COLLATE)
111 val = get_string_value ("LC_COLLATE");
112 if (val == 0 && lc_all && *lc_all)
113 setlocale (LC_COLLATE, lc_all);
114 # endif /* LC_COLLATE */
115
116 # if defined (LC_MESSAGES)
117 val = get_string_value ("LC_MESSAGES");
118 if (val == 0 && lc_all && *lc_all)
119 setlocale (LC_MESSAGES, lc_all);
120 # endif /* LC_MESSAGES */
121
122 # if defined (LC_NUMERIC)
123 val = get_string_value ("LC_NUMERIC");
124 if (val == 0 && lc_all && *lc_all)
125 setlocale (LC_NUMERIC, lc_all);
126 # endif /* LC_NUMERIC */
127
128 # if defined (LC_TIME)
129 val = get_string_value ("LC_TIME");
130 if (val == 0 && lc_all && *lc_all)
131 setlocale (LC_TIME, lc_all);
132 # endif /* LC_TIME */
133
134 #endif /* HAVE_SETLOCALE */
135
136 val = get_string_value ("TEXTDOMAIN");
137 if (val && *val)
138 {
139 FREE (default_domain);
140 default_domain = savestring (val);
141 if (default_dir && *default_dir)
142 bindtextdomain (default_domain, default_dir);
143 }
144
145 val = get_string_value ("TEXTDOMAINDIR");
146 if (val && *val)
147 {
148 FREE (default_dir);
149 default_dir = savestring (val);
150 if (default_domain && *default_domain)
151 bindtextdomain (default_domain, default_dir);
152 }
153 }
154
155 /* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
156 if successful, 0 otherwise. */
157 int
158 set_locale_var (var, value)
159 char *var, *value;
160 {
161 int r;
162 char *x;
163
164 x = "";
165 errno = 0;
166 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
167 {
168 FREE (default_domain);
169 default_domain = value ? savestring (value) : (char *)NULL;
170 if (default_dir && *default_dir)
171 bindtextdomain (default_domain, default_dir);
172 return (1);
173 }
174 else if (var[0] == 'T') /* TEXTDOMAINDIR */
175 {
176 FREE (default_dir);
177 default_dir = value ? savestring (value) : (char *)NULL;
178 if (default_domain && *default_domain)
179 bindtextdomain (default_domain, default_dir);
180 return (1);
181 }
182
183 /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
184
185 else if (var[3] == 'A') /* LC_ALL */
186 {
187 FREE (lc_all);
188 if (value)
189 lc_all = savestring (value);
190 else
191 {
192 lc_all = (char *)xmalloc (1);
193 lc_all[0] = '\0';
194 }
195 #if defined (HAVE_SETLOCALE)
196 r = *lc_all ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
197 if (x == 0)
198 {
199 if (errno == 0)
200 internal_warning(_("setlocale: LC_ALL: cannot change locale (%s)"), lc_all);
201 else
202 internal_warning(_("setlocale: LC_ALL: cannot change locale (%s): %s"), lc_all, strerror (errno));
203 }
204 locale_setblanks ();
205 locale_mb_cur_max = MB_CUR_MAX;
206 u32reset ();
207 return r;
208 #else
209 return (1);
210 #endif
211 }
212
213 #if defined (HAVE_SETLOCALE)
214 else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
215 {
216 # if defined (LC_CTYPE)
217 if (lc_all == 0 || *lc_all == '\0')
218 {
219 x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
220 locale_setblanks ();
221 locale_mb_cur_max = MB_CUR_MAX;
222 u32reset ();
223 }
224 # endif
225 }
226 else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
227 {
228 # if defined (LC_COLLATE)
229 if (lc_all == 0 || *lc_all == '\0')
230 x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
231 # endif /* LC_COLLATE */
232 }
233 else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
234 {
235 # if defined (LC_MESSAGES)
236 if (lc_all == 0 || *lc_all == '\0')
237 x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
238 # endif /* LC_MESSAGES */
239 }
240 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
241 {
242 # if defined (LC_NUMERIC)
243 if (lc_all == 0 || *lc_all == '\0')
244 x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
245 # endif /* LC_NUMERIC */
246 }
247 else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
248 {
249 # if defined (LC_TIME)
250 if (lc_all == 0 || *lc_all == '\0')
251 x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
252 # endif /* LC_TIME */
253 }
254 #endif /* HAVE_SETLOCALE */
255
256 if (x == 0)
257 {
258 if (errno == 0)
259 internal_warning(_("setlocale: %s: cannot change locale (%s)"), var, get_locale_var (var));
260 else
261 internal_warning(_("setlocale: %s: cannot change locale (%s): %s"), var, get_locale_var (var), strerror (errno));
262 }
263
264 return (x != 0);
265 }
266
267 /* Called when LANG is assigned a value. Tracks value in `lang'. Calls
268 reset_locale_vars() to reset any default values if LC_ALL is unset or
269 null. */
270 int
271 set_lang (var, value)
272 char *var, *value;
273 {
274 FREE (lang);
275 if (value)
276 lang = savestring (value);
277 else
278 {
279 lang = (char *)xmalloc (1);
280 lang[0] = '\0';
281 }
282
283 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
284 }
285
286 /* Set default values for LANG and LC_ALL. Default values for all other
287 locale-related variables depend on these. */
288 void
289 set_default_lang ()
290 {
291 char *v;
292
293 v = get_string_value ("LC_ALL");
294 set_locale_var ("LC_ALL", v);
295
296 v = get_string_value ("LANG");
297 set_lang ("LANG", v);
298 }
299
300 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
301 The precedence is as POSIX.2 specifies: LC_ALL has precedence over
302 the specific locale variables, and LANG, if set, is used as the default. */
303 char *
304 get_locale_var (var)
305 char *var;
306 {
307 char *locale;
308
309 locale = lc_all;
310
311 if (locale == 0 || *locale == 0)
312 locale = get_string_value (var); /* XXX - no mem leak */
313 if (locale == 0 || *locale == 0)
314 locale = lang;
315 if (locale == 0 || *locale == 0)
316 #if 0
317 locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
318 #else
319 locale = "";
320 #endif
321 return (locale);
322 }
323
324 /* Called to reset all of the locale variables to their appropriate values
325 if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
326 IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
327 static int
328 reset_locale_vars ()
329 {
330 char *t;
331 #if defined (HAVE_SETLOCALE)
332 if (lang == 0 || *lang == '\0')
333 maybe_make_export_env (); /* trust that this will change environment for setlocale */
334 if (setlocale (LC_ALL, lang ? lang : "") == 0)
335 return 0;
336
337 # if defined (LC_CTYPE)
338 t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
339 # endif
340 # if defined (LC_COLLATE)
341 t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
342 # endif
343 # if defined (LC_MESSAGES)
344 t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
345 # endif
346 # if defined (LC_NUMERIC)
347 t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
348 # endif
349 # if defined (LC_TIME)
350 t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
351 # endif
352
353 locale_setblanks ();
354 locale_mb_cur_max = MB_CUR_MAX;
355 u32reset ();
356
357 #endif
358 return 1;
359 }
360
361 /* Translate the contents of STRING, a $"..." quoted string, according
362 to the current locale. In the `C' or `POSIX' locale, or if gettext()
363 is not available, the passed string is returned unchanged. The
364 length of the translated string is returned in LENP, if non-null. */
365 char *
366 localetrans (string, len, lenp)
367 char *string;
368 int len, *lenp;
369 {
370 char *locale, *t;
371 char *translated;
372 int tlen;
373
374 /* Don't try to translate null strings. */
375 if (string == 0 || *string == 0)
376 {
377 if (lenp)
378 *lenp = 0;
379 return ((char *)NULL);
380 }
381
382 locale = get_locale_var ("LC_MESSAGES");
383
384 /* If we don't have setlocale() or the current locale is `C' or `POSIX',
385 just return the string. If we don't have gettext(), there's no use
386 doing anything else. */
387 if (locale == 0 || locale[0] == '\0' ||
388 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
389 {
390 t = (char *)xmalloc (len + 1);
391 strcpy (t, string);
392 if (lenp)
393 *lenp = len;
394 return (t);
395 }
396
397 /* Now try to translate it. */
398 if (default_domain && *default_domain)
399 translated = dgettext (default_domain, string);
400 else
401 translated = string;
402
403 if (translated == string) /* gettext returns its argument if untranslatable */
404 {
405 t = (char *)xmalloc (len + 1);
406 strcpy (t, string);
407 if (lenp)
408 *lenp = len;
409 }
410 else
411 {
412 tlen = strlen (translated);
413 t = (char *)xmalloc (tlen + 1);
414 strcpy (t, translated);
415 if (lenp)
416 *lenp = tlen;
417 }
418 return (t);
419 }
420
421 /* Change a bash string into a string suitable for inclusion in a `po' file.
422 This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
423 char *
424 mk_msgstr (string, foundnlp)
425 char *string;
426 int *foundnlp;
427 {
428 register int c, len;
429 char *result, *r, *s;
430
431 for (len = 0, s = string; s && *s; s++)
432 {
433 len++;
434 if (*s == '"' || *s == '\\')
435 len++;
436 else if (*s == '\n')
437 len += 5;
438 }
439
440 r = result = (char *)xmalloc (len + 3);
441 *r++ = '"';
442
443 for (s = string; s && (c = *s); s++)
444 {
445 if (c == '\n') /* <NL> -> \n"<NL>" */
446 {
447 *r++ = '\\';
448 *r++ = 'n';
449 *r++ = '"';
450 *r++ = '\n';
451 *r++ = '"';
452 if (foundnlp)
453 *foundnlp = 1;
454 continue;
455 }
456 if (c == '"' || c == '\\')
457 *r++ = '\\';
458 *r++ = c;
459 }
460
461 *r++ = '"';
462 *r++ = '\0';
463
464 return result;
465 }
466
467 /* $"..." -- Translate the portion of STRING between START and END
468 according to current locale using gettext (if available) and return
469 the result. The caller will take care of leaving the quotes intact.
470 The string will be left without the leading `$' by the caller.
471 If translation is performed, the translated string will be double-quoted
472 by the caller. The length of the translated string is returned in LENP,
473 if non-null. */
474 char *
475 localeexpand (string, start, end, lineno, lenp)
476 char *string;
477 int start, end, lineno, *lenp;
478 {
479 int len, tlen, foundnl;
480 char *temp, *t, *t2;
481
482 temp = (char *)xmalloc (end - start + 1);
483 for (tlen = 0, len = start; len < end; )
484 temp[tlen++] = string[len++];
485 temp[tlen] = '\0';
486
487 /* If we're just dumping translatable strings, don't do anything with the
488 string itself, but if we're dumping in `po' file format, convert it into
489 a form more palatable to gettext(3) and friends by quoting `"' and `\'
490 with backslashes and converting <NL> into `\n"<NL>"'. If we find a
491 newline in TEMP, we first output a `msgid ""' line and then the
492 translated string; otherwise we output the `msgid' and translated
493 string all on one line. */
494 if (dump_translatable_strings)
495 {
496 if (dump_po_strings)
497 {
498 foundnl = 0;
499 t = mk_msgstr (temp, &foundnl);
500 t2 = foundnl ? "\"\"\n" : "";
501
502 printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
503 yy_input_name (), lineno, t2, t);
504 free (t);
505 }
506 else
507 printf ("\"%s\"\n", temp);
508
509 if (lenp)
510 *lenp = tlen;
511 return (temp);
512 }
513 else if (*temp)
514 {
515 t = localetrans (temp, tlen, &len);
516 free (temp);
517 if (lenp)
518 *lenp = len;
519 return (t);
520 }
521 else
522 {
523 if (lenp)
524 *lenp = 0;
525 return (temp);
526 }
527 }
528
529 /* Set every character in the <blank> character class to be a shell break
530 character for the lexical analyzer when the locale changes. */
531 static void
532 locale_setblanks ()
533 {
534 int x;
535
536 for (x = 0; x < sh_syntabsiz; x++)
537 {
538 if (isblank ((unsigned char)x))
539 sh_syntaxtab[x] |= CSHBRK|CBLANK;
540 else if (member (x, shell_break_chars))
541 {
542 sh_syntaxtab[x] |= CSHBRK;
543 sh_syntaxtab[x] &= ~CBLANK;
544 }
545 else
546 sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
547 }
548 }
549
550 static int
551 locale_isutf8 (lspec)
552 char *lspec;
553 {
554 char *cp;
555
556 #if HAVE_LANGINFO_CODESET
557 cp = nl_langinfo (CODESET);
558 return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
559 #else
560 /* Take a shot */
561 return (strstr (lspec, "UTF-8") || strstr (lspec, "utf8"));
562 #endif
563 }