d340d93f47119f7a121217fed389eb7d907ebc94
[platform/upstream/bash.git] / locale.c
1 /* locale.c - Miscellaneous internationalization functions. */
2
3 /* Copyright (C) 1996 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 it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 2, or (at your option) any later
10    version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17    You should have received a copy of the GNU General Public License along
18    with Bash; see the file COPYING.  If not, write to the Free Software
19    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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 #include "bashintl.h"
30 #include "bashansi.h"
31 #include <stdio.h>
32 #include "chartypes.h"
33
34 #include "shell.h"
35
36 /* The current locale when the program begins */
37 static char *default_locale;
38
39 /* The current domain for textdomain(3). */
40 static char *default_domain;
41 static char *default_dir;
42
43 /* tracks the value of LC_ALL; used to override values for other locale
44    categories */
45 static char *lc_all;
46
47 /* Set the value of default_locale and make the current locale the
48    system default locale.  This should be called very early in main(). */
49 void
50 set_default_locale ()
51 {
52 #if defined (HAVE_SETLOCALE)
53   default_locale = setlocale (LC_ALL, "");
54   if (default_locale)
55     default_locale = savestring (default_locale);
56 #endif /* HAVE_SETLOCALE */
57 }
58
59 /* Set default values for LC_CTYPE, LC_COLLATE, and LC_MESSAGES if they
60    are not specified in the environment, but LANG or LC_ALL is.  This
61    should be called from main() after parsing the environment. */
62 void
63 set_default_locale_vars ()
64 {
65   char *val;
66
67 #if defined (HAVE_SETLOCALE)
68   val = get_string_value ("LC_CTYPE");
69   if (val == 0 && lc_all && *lc_all)
70     setlocale (LC_CTYPE, lc_all);
71
72 #  if defined (LC_COLLATE)
73   val = get_string_value ("LC_COLLATE");
74   if (val == 0 && lc_all && *lc_all)
75     setlocale (LC_COLLATE, lc_all);
76 #  endif /* LC_COLLATE */
77
78 #  if defined (LC_MESSAGES)
79   val = get_string_value ("LC_MESSAGES");
80   if (val == 0 && lc_all && *lc_all)
81     setlocale (LC_MESSAGES, lc_all);
82 #  endif /* LC_MESSAGES */
83
84 #  if defined (LC_NUMERIC)
85   val = get_string_value ("LC_NUMERIC");
86   if (val == 0 && lc_all && *lc_all)
87     setlocale (LC_NUMERIC, lc_all);
88 #  endif /* LC_NUMERIC */
89
90 #endif /* HAVE_SETLOCALE */
91
92   val = get_string_value ("TEXTDOMAIN");
93   if (val && *val)
94     {
95       FREE (default_domain);
96       default_domain = savestring (val);
97       textdomain (default_domain);
98     }
99
100   val = get_string_value ("TEXTDOMAINDIR");
101   if (val && *val)
102     {
103       FREE (default_dir);
104       default_dir = savestring (val);
105       bindtextdomain (default_domain, default_dir);
106     }
107 }
108
109 /* Set one of the locale categories (specified by VAR) to VALUE.  Returns 1
110   if successful, 0 otherwise. */
111 int
112 set_locale_var (var, value)
113      char *var, *value;
114 {
115   if (var[0] == 'T' && var[10] == 0)            /* TEXTDOMAIN */
116     {
117       FREE (default_domain);
118       default_domain = value ? savestring (value) : (char *)NULL;
119       textdomain (default_domain);
120       return (1);
121     }
122   else if (var[0] == 'T')                       /* TEXTDOMAINDIR */
123     {
124       FREE (default_dir);
125       default_dir = value ? savestring (value) : (char *)NULL;
126       bindtextdomain (default_domain, default_dir);
127       return (1);
128     }
129
130   /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
131
132   else if (var[3] == 'A')                       /* LC_ALL */
133     {
134       FREE (lc_all);
135       if (value)
136         lc_all = savestring (value);
137       else if (default_locale)
138         lc_all = savestring (default_locale);
139       else
140         {
141           lc_all = (char *)xmalloc (1);
142           lc_all[0] = '\0';
143         }
144 #if defined (HAVE_SETLOCALE)
145       return (setlocale (LC_ALL, lc_all) != 0);
146 #else
147       return (1);
148 #endif
149     }
150
151 #if defined (HAVE_SETLOCALE)
152   else if (var[3] == 'C' && var[4] == 'T')      /* LC_CTYPE */
153     {
154       if (lc_all == 0 || *lc_all == '\0')
155         return (setlocale (LC_CTYPE, value ? value : "") != 0);
156     }
157   else if (var[3] == 'C' && var[4] == 'O')      /* LC_COLLATE */
158     {
159 #  if defined (LC_COLLATE)
160       if (lc_all == 0 || *lc_all == '\0')
161         return (setlocale (LC_COLLATE, value ? value : "") != 0);
162 #  endif /* LC_COLLATE */
163     }
164   else if (var[3] == 'M' && var[4] == 'E')      /* LC_MESSAGES */
165     {
166 #  if defined (LC_MESSAGES)
167       if (lc_all == 0 || *lc_all == '\0')
168         return (setlocale (LC_MESSAGES, value ? value : "") != 0);
169 #  endif /* LC_MESSAGES */
170     }
171   else if (var[3] == 'N' && var[4] == 'U')      /* LC_NUMERIC */
172     {
173 #  if defined (LC_NUMERIC)
174       if (lc_all == 0 || *lc_all == '\0')
175         return (setlocale (LC_NUMERIC, value ? value : "") != 0);
176 #  endif /* LC_NUMERIC */
177     }
178 #endif /* HAVE_SETLOCALE */
179
180   return (0);
181 }
182
183 #if 0
184 /* Called when LANG is assigned a value.  Sets LC_ALL if that has not
185    already been set. */
186 #else
187 /* This no longer does anything; we rely on the C library for correct
188    behavior. */
189 #endif
190 int
191 set_lang (var, value)
192      char *var, *value;
193 {
194 #if 0
195   return ((lc_all == 0) ? set_locale_var ("LC_ALL", value) : 0);
196 #else
197   return 0;
198 #endif
199 }
200
201 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE) */
202 char *
203 get_locale_var (var)
204      char *var;
205 {
206   char *locale;
207
208   locale = lc_all;
209
210   if (locale == 0)
211     locale = get_string_value (var);
212   if (locale == 0)
213     locale = default_locale;
214
215   return (locale);
216 }
217
218 /* Translate the contents of STRING, a $"..." quoted string, according
219    to the current locale.  In the `C' or `POSIX' locale, or if gettext()
220    is not available, the passed string is returned unchanged.  The
221    length of the translated string is returned in LENP, if non-null. */
222 char *
223 localetrans (string, len, lenp)
224      char *string;
225      int len, *lenp;
226 {
227   char *locale, *t;
228 #if defined (HAVE_GETTEXT)
229   char *translated;
230   int tlen;
231 #endif
232
233   /* Don't try to translate null strings. */
234   if (string == 0 || *string == 0)
235     {
236       if (lenp)
237         *lenp = 0;
238       return ((char *)NULL);
239     }
240
241   locale = get_locale_var ("LC_MESSAGES");
242
243   /* If we don't have setlocale() or the current locale is `C' or `POSIX',
244      just return the string.  If we don't have gettext(), there's no use
245      doing anything else. */
246 #if defined (HAVE_GETTEXT)
247   if (locale == 0 || locale[0] == '\0' ||
248       (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
249 #endif
250     {
251       t = (char *)xmalloc (len + 1);
252       strcpy (t, string);
253       if (lenp)
254         *lenp = len;
255       return (t);
256     }
257
258 #if defined (HAVE_GETTEXT)
259   /* Now try to translate it. */
260   translated = gettext (string);
261   if (translated == string)     /* gettext returns its argument if untranslatable */
262     {
263       t = (char *)xmalloc (len + 1);
264       strcpy (t, string);
265       if (lenp)
266         *lenp = len;
267     }
268   else
269     {
270       tlen = strlen (translated);
271       t = (char *)xmalloc (tlen + 1);
272       strcpy (t, translated);
273       if (lenp)
274         *lenp = tlen;
275     }
276   return (t);
277 #endif /* HAVE_GETTEXT */
278 }