blob: 8dabc7d2c863241e47fc7042f1ba1c6ec833221e [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* locale.c - Miscellaneous internationalization functions. */
2
Chet Rameyac50fba2014-02-26 09:36:43 -05003/* Copyright (C) 1996-2009,2012 Free Software Foundation, Inc.
Jari Aaltoccc6cda1996-12-23 17:02:34 +00004
5 This file is part of GNU Bash, the Bourne Again SHell.
6
Jari Aalto31859422009-01-12 13:36:28 +00007 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.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000011
Jari Aalto31859422009-01-12 13:36:28 +000012 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.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000016
Jari Aalto31859422009-01-12 13:36:28 +000017 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*/
Jari Aaltoccc6cda1996-12-23 17:02:34 +000020
21#include "config.h"
22
23#include "bashtypes.h"
24
25#if defined (HAVE_UNISTD_H)
26# include <unistd.h>
27#endif
28
Chet Rameyac50fba2014-02-26 09:36:43 -050029#if HAVE_LANGINFO_CODESET
30# include <langinfo.h>
31#endif
32
Jari Aaltoccc6cda1996-12-23 17:02:34 +000033#include "bashintl.h"
34#include "bashansi.h"
35#include <stdio.h>
Jari Aaltof73dda02001-11-13 17:56:06 +000036#include "chartypes.h"
Jari Aalto31859422009-01-12 13:36:28 +000037#include <errno.h>
Jari Aaltoccc6cda1996-12-23 17:02:34 +000038
39#include "shell.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000040#include "input.h" /* For bash_input */
41
Jari Aalto31859422009-01-12 13:36:28 +000042#ifndef errno
43extern int errno;
44#endif
45
Chet Rameyac50fba2014-02-26 09:36:43 -050046int locale_utf8locale; /* unused for now */
47int locale_mb_cur_max; /* value of MB_CUR_MAX for current locale (LC_CTYPE) */
48
Jari Aalto7117c2d2002-07-17 14:10:11 +000049extern int dump_translatable_strings, dump_po_strings;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000050
51/* The current locale when the program begins */
52static char *default_locale;
53
54/* The current domain for textdomain(3). */
55static char *default_domain;
56static char *default_dir;
57
58/* tracks the value of LC_ALL; used to override values for other locale
59 categories */
60static char *lc_all;
61
Jari Aaltob80f6442004-07-27 13:29:18 +000062/* tracks the value of LC_ALL; used to provide defaults for locale
63 categories */
64static 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. */
68static int reset_locale_vars __P((void));
69
70static void locale_setblanks __P((void));
Chet Rameyac50fba2014-02-26 09:36:43 -050071static int locale_isutf8 __P((char *));
Jari Aaltob80f6442004-07-27 13:29:18 +000072
Jari Aaltoccc6cda1996-12-23 17:02:34 +000073/* Set the value of default_locale and make the current locale the
74 system default locale. This should be called very early in main(). */
75void
76set_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 */
Jari Aaltob80f6442004-07-27 13:29:18 +000083 bindtextdomain (PACKAGE, LOCALEDIR);
84 textdomain (PACKAGE);
Chet Rameyac50fba2014-02-26 09:36:43 -050085
86 locale_mb_cur_max = MB_CUR_MAX;
Jari Aaltoccc6cda1996-12-23 17:02:34 +000087}
88
Jari Aalto95732b42005-12-07 14:08:12 +000089/* 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
Jari Aaltoccc6cda1996-12-23 17:02:34 +000091 should be called from main() after parsing the environment. */
92void
93set_default_locale_vars ()
94{
95 char *val;
96
97#if defined (HAVE_SETLOCALE)
Jari Aaltob80f6442004-07-27 13:29:18 +000098
99# if defined (LC_CTYPE)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000100 val = get_string_value ("LC_CTYPE");
101 if (val == 0 && lc_all && *lc_all)
Jari Aaltob80f6442004-07-27 13:29:18 +0000102 {
103 setlocale (LC_CTYPE, lc_all);
104 locale_setblanks ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500105 locale_mb_cur_max = MB_CUR_MAX;
106 u32reset ();
Jari Aaltob80f6442004-07-27 13:29:18 +0000107 }
108# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000109
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
Jari Aaltobb706242000-03-17 21:46:59 +0000122# 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
Jari Aalto95732b42005-12-07 14:08:12 +0000128# 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
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000134#endif /* HAVE_SETLOCALE */
135
136 val = get_string_value ("TEXTDOMAIN");
137 if (val && *val)
138 {
139 FREE (default_domain);
140 default_domain = savestring (val);
Chet Rameyac50fba2014-02-26 09:36:43 -0500141 if (default_dir && *default_dir)
142 bindtextdomain (default_domain, default_dir);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000143 }
144
145 val = get_string_value ("TEXTDOMAINDIR");
146 if (val && *val)
147 {
148 FREE (default_dir);
149 default_dir = savestring (val);
Jari Aaltob80f6442004-07-27 13:29:18 +0000150 if (default_domain && *default_domain)
151 bindtextdomain (default_domain, default_dir);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000152 }
153}
154
155/* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
156 if successful, 0 otherwise. */
157int
158set_locale_var (var, value)
159 char *var, *value;
160{
Jari Aaltob80f6442004-07-27 13:29:18 +0000161 int r;
Jari Aalto31859422009-01-12 13:36:28 +0000162 char *x;
Jari Aaltob80f6442004-07-27 13:29:18 +0000163
Jari Aalto31859422009-01-12 13:36:28 +0000164 x = "";
165 errno = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000166 if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
167 {
168 FREE (default_domain);
169 default_domain = value ? savestring (value) : (char *)NULL;
Chet Rameyac50fba2014-02-26 09:36:43 -0500170 if (default_dir && *default_dir)
171 bindtextdomain (default_domain, default_dir);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000172 return (1);
173 }
174 else if (var[0] == 'T') /* TEXTDOMAINDIR */
175 {
176 FREE (default_dir);
177 default_dir = value ? savestring (value) : (char *)NULL;
Jari Aaltob80f6442004-07-27 13:29:18 +0000178 if (default_domain && *default_domain)
179 bindtextdomain (default_domain, default_dir);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000180 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);
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000188 if (value)
189 lc_all = savestring (value);
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000190 else
191 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000192 lc_all = (char *)xmalloc (1);
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000193 lc_all[0] = '\0';
194 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000195#if defined (HAVE_SETLOCALE)
Jari Aalto31859422009-01-12 13:36:28 +0000196 r = *lc_all ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
197 if (x == 0)
Jari Aalto17345e52009-02-19 22:21:29 +0000198 {
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 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000204 locale_setblanks ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500205 locale_mb_cur_max = MB_CUR_MAX;
206 u32reset ();
Jari Aaltob80f6442004-07-27 13:29:18 +0000207 return r;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000208#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 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000216# if defined (LC_CTYPE)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000217 if (lc_all == 0 || *lc_all == '\0')
Jari Aaltob80f6442004-07-27 13:29:18 +0000218 {
Jari Aalto31859422009-01-12 13:36:28 +0000219 x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
Jari Aaltob80f6442004-07-27 13:29:18 +0000220 locale_setblanks ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500221 locale_mb_cur_max = MB_CUR_MAX;
222 u32reset ();
Jari Aaltob80f6442004-07-27 13:29:18 +0000223 }
224# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000225 }
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')
Jari Aalto31859422009-01-12 13:36:28 +0000230 x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000231# 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')
Jari Aalto31859422009-01-12 13:36:28 +0000237 x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000238# endif /* LC_MESSAGES */
239 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000240 else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
Jari Aaltobb706242000-03-17 21:46:59 +0000241 {
242# if defined (LC_NUMERIC)
243 if (lc_all == 0 || *lc_all == '\0')
Jari Aalto31859422009-01-12 13:36:28 +0000244 x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
Jari Aaltobb706242000-03-17 21:46:59 +0000245# endif /* LC_NUMERIC */
246 }
Jari Aalto95732b42005-12-07 14:08:12 +0000247 else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
248 {
249# if defined (LC_TIME)
250 if (lc_all == 0 || *lc_all == '\0')
Jari Aalto31859422009-01-12 13:36:28 +0000251 x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
Jari Aalto95732b42005-12-07 14:08:12 +0000252# endif /* LC_TIME */
253 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000254#endif /* HAVE_SETLOCALE */
Jari Aalto95732b42005-12-07 14:08:12 +0000255
Jari Aalto31859422009-01-12 13:36:28 +0000256 if (x == 0)
Jari Aalto17345e52009-02-19 22:21:29 +0000257 {
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 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000263
Jari Aalto31859422009-01-12 13:36:28 +0000264 return (x != 0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000265}
266
Jari Aaltob80f6442004-07-27 13:29:18 +0000267/* 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. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000270int
271set_lang (var, value)
272 char *var, *value;
273{
Jari Aaltob80f6442004-07-27 13:29:18 +0000274 FREE (lang);
275 if (value)
276 lang = savestring (value);
277 else
278 {
279 lang = (char *)xmalloc (1);
280 lang[0] = '\0';
281 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500282
Jari Aaltob80f6442004-07-27 13:29:18 +0000283 return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000284}
285
Jari Aalto06285672006-10-10 14:15:34 +0000286/* Set default values for LANG and LC_ALL. Default values for all other
287 locale-related variables depend on these. */
288void
289set_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
Jari Aaltob80f6442004-07-27 13:29:18 +0000300/* 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. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000303char *
304get_locale_var (var)
305 char *var;
306{
307 char *locale;
308
309 locale = lc_all;
310
Jari Aaltob80f6442004-07-27 13:29:18 +0000311 if (locale == 0 || *locale == 0)
Chet Ramey495aee42011-11-22 19:11:26 -0500312 locale = get_string_value (var); /* XXX - mem leak? */
Jari Aaltob80f6442004-07-27 13:29:18 +0000313 if (locale == 0 || *locale == 0)
314 locale = lang;
315 if (locale == 0 || *locale == 0)
Jari Aalto31859422009-01-12 13:36:28 +0000316#if 0
Jari Aalto06285672006-10-10 14:15:34 +0000317 locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
Jari Aalto31859422009-01-12 13:36:28 +0000318#else
319 locale = "";
320#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000321 return (locale);
322}
323
Jari Aaltob80f6442004-07-27 13:29:18 +0000324/* 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. */
327static int
328reset_locale_vars ()
329{
Jari Aalto31859422009-01-12 13:36:28 +0000330 char *t;
Jari Aaltob80f6442004-07-27 13:29:18 +0000331#if defined (HAVE_SETLOCALE)
Jari Aalto06285672006-10-10 14:15:34 +0000332 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)
Jari Aaltob80f6442004-07-27 13:29:18 +0000335 return 0;
336
337# if defined (LC_CTYPE)
Jari Aalto31859422009-01-12 13:36:28 +0000338 t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
Jari Aaltob80f6442004-07-27 13:29:18 +0000339# endif
340# if defined (LC_COLLATE)
Jari Aalto31859422009-01-12 13:36:28 +0000341 t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
Jari Aaltob80f6442004-07-27 13:29:18 +0000342# endif
343# if defined (LC_MESSAGES)
Jari Aalto31859422009-01-12 13:36:28 +0000344 t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
Jari Aaltob80f6442004-07-27 13:29:18 +0000345# endif
346# if defined (LC_NUMERIC)
Jari Aalto31859422009-01-12 13:36:28 +0000347 t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
Jari Aaltob80f6442004-07-27 13:29:18 +0000348# endif
Jari Aalto95732b42005-12-07 14:08:12 +0000349# if defined (LC_TIME)
Jari Aalto31859422009-01-12 13:36:28 +0000350 t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
Jari Aalto95732b42005-12-07 14:08:12 +0000351# endif
Jari Aaltob80f6442004-07-27 13:29:18 +0000352
353 locale_setblanks ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500354 locale_mb_cur_max = MB_CUR_MAX;
355 u32reset ();
Jari Aaltob80f6442004-07-27 13:29:18 +0000356
357#endif
358 return 1;
359}
360
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000361/* 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. */
365char *
366localetrans (string, len, lenp)
367 char *string;
368 int len, *lenp;
369{
370 char *locale, *t;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000371 char *translated;
372 int tlen;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000373
374 /* Don't try to translate null strings. */
375 if (string == 0 || *string == 0)
376 {
377 if (lenp)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000378 *lenp = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000379 return ((char *)NULL);
380 }
381
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000382 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. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000387 if (locale == 0 || locale[0] == '\0' ||
388 (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000389 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000390 t = (char *)xmalloc (len + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000391 strcpy (t, string);
392 if (lenp)
393 *lenp = len;
394 return (t);
395 }
396
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000397 /* Now try to translate it. */
Jari Aaltob80f6442004-07-27 13:29:18 +0000398 if (default_domain && *default_domain)
399 translated = dgettext (default_domain, string);
400 else
401 translated = string;
402
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000403 if (translated == string) /* gettext returns its argument if untranslatable */
404 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000405 t = (char *)xmalloc (len + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000406 strcpy (t, string);
407 if (lenp)
408 *lenp = len;
409 }
410 else
411 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000412 tlen = strlen (translated);
Jari Aaltof73dda02001-11-13 17:56:06 +0000413 t = (char *)xmalloc (tlen + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000414 strcpy (t, translated);
415 if (lenp)
416 *lenp = tlen;
417 }
418 return (t);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000419}
Jari Aalto7117c2d2002-07-17 14:10:11 +0000420
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". */
423char *
424mk_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. */
474char *
475localeexpand (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
Jari Aaltob80f6442004-07-27 13:29:18 +0000488 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. */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000494 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}
Jari Aaltob80f6442004-07-27 13:29:18 +0000528
529/* Set every character in the <blank> character class to be a shell break
530 character for the lexical analyzer when the locale changes. */
531static void
532locale_setblanks ()
533{
534 int x;
535
536 for (x = 0; x < sh_syntabsiz; x++)
537 {
538 if (isblank (x))
Jari Aalto06285672006-10-10 14:15:34 +0000539 sh_syntaxtab[x] |= CSHBRK|CBLANK;
Jari Aaltob80f6442004-07-27 13:29:18 +0000540 else if (member (x, shell_break_chars))
Jari Aalto06285672006-10-10 14:15:34 +0000541 {
542 sh_syntaxtab[x] |= CSHBRK;
543 sh_syntaxtab[x] &= ~CBLANK;
544 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000545 else
Jari Aalto06285672006-10-10 14:15:34 +0000546 sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
Jari Aaltob80f6442004-07-27 13:29:18 +0000547 }
548}
Chet Rameyac50fba2014-02-26 09:36:43 -0500549
550static int
551locale_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}