source: trunk/third/bash/locale.c @ 18290

Revision 18290, 9.6 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18289, which included commits to RCS files with non-trunk default branches.
Line 
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#include "input.h"      /* For bash_input */
36
37extern int dump_translatable_strings, dump_po_strings;
38
39/* The current locale when the program begins */
40static char *default_locale;
41
42/* The current domain for textdomain(3). */
43static char *default_domain;
44static char *default_dir;
45
46/* tracks the value of LC_ALL; used to override values for other locale
47   categories */
48static char *lc_all;
49
50/* Set the value of default_locale and make the current locale the
51   system default locale.  This should be called very early in main(). */
52void
53set_default_locale ()
54{
55#if defined (HAVE_SETLOCALE)
56  default_locale = setlocale (LC_ALL, "");
57  if (default_locale)
58    default_locale = savestring (default_locale);
59#endif /* HAVE_SETLOCALE */
60}
61
62/* Set default values for LC_CTYPE, LC_COLLATE, and LC_MESSAGES if they
63   are not specified in the environment, but LANG or LC_ALL is.  This
64   should be called from main() after parsing the environment. */
65void
66set_default_locale_vars ()
67{
68  char *val;
69
70#if defined (HAVE_SETLOCALE)
71  val = get_string_value ("LC_CTYPE");
72  if (val == 0 && lc_all && *lc_all)
73    setlocale (LC_CTYPE, lc_all);
74
75#  if defined (LC_COLLATE)
76  val = get_string_value ("LC_COLLATE");
77  if (val == 0 && lc_all && *lc_all)
78    setlocale (LC_COLLATE, lc_all);
79#  endif /* LC_COLLATE */
80
81#  if defined (LC_MESSAGES)
82  val = get_string_value ("LC_MESSAGES");
83  if (val == 0 && lc_all && *lc_all)
84    setlocale (LC_MESSAGES, lc_all);
85#  endif /* LC_MESSAGES */
86
87#  if defined (LC_NUMERIC)
88  val = get_string_value ("LC_NUMERIC");
89  if (val == 0 && lc_all && *lc_all)
90    setlocale (LC_NUMERIC, lc_all);
91#  endif /* LC_NUMERIC */
92
93#endif /* HAVE_SETLOCALE */
94
95  val = get_string_value ("TEXTDOMAIN");
96  if (val && *val)
97    {
98      FREE (default_domain);
99      default_domain = savestring (val);
100      textdomain (default_domain);
101    }
102
103  val = get_string_value ("TEXTDOMAINDIR");
104  if (val && *val)
105    {
106      FREE (default_dir);
107      default_dir = savestring (val);
108      bindtextdomain (default_domain, default_dir);
109    }
110}
111
112/* Set one of the locale categories (specified by VAR) to VALUE.  Returns 1
113  if successful, 0 otherwise. */
114int
115set_locale_var (var, value)
116     char *var, *value;
117{
118  if (var[0] == 'T' && var[10] == 0)            /* TEXTDOMAIN */
119    {
120      FREE (default_domain);
121      default_domain = value ? savestring (value) : (char *)NULL;
122      textdomain (default_domain);
123      return (1);
124    }
125  else if (var[0] == 'T')                       /* TEXTDOMAINDIR */
126    {
127      FREE (default_dir);
128      default_dir = value ? savestring (value) : (char *)NULL;
129      bindtextdomain (default_domain, default_dir);
130      return (1);
131    }
132
133  /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
134
135  else if (var[3] == 'A')                       /* LC_ALL */
136    {
137      FREE (lc_all);
138      if (value)
139        lc_all = savestring (value);
140      else if (default_locale)
141        lc_all = savestring (default_locale);
142      else
143        {
144          lc_all = (char *)xmalloc (1);
145          lc_all[0] = '\0';
146        }
147#if defined (HAVE_SETLOCALE)
148      return (setlocale (LC_ALL, lc_all) != 0);
149#else
150      return (1);
151#endif
152    }
153
154#if defined (HAVE_SETLOCALE)
155  else if (var[3] == 'C' && var[4] == 'T')      /* LC_CTYPE */
156    {
157      if (lc_all == 0 || *lc_all == '\0')
158        return (setlocale (LC_CTYPE, value ? value : "") != 0);
159    }
160  else if (var[3] == 'C' && var[4] == 'O')      /* LC_COLLATE */
161    {
162#  if defined (LC_COLLATE)
163      if (lc_all == 0 || *lc_all == '\0')
164        return (setlocale (LC_COLLATE, value ? value : "") != 0);
165#  endif /* LC_COLLATE */
166    }
167  else if (var[3] == 'M' && var[4] == 'E')      /* LC_MESSAGES */
168    {
169#  if defined (LC_MESSAGES)
170      if (lc_all == 0 || *lc_all == '\0')
171        return (setlocale (LC_MESSAGES, value ? value : "") != 0);
172#  endif /* LC_MESSAGES */
173    }
174  else if (var[3] == 'N' && var[4] == 'U')      /* LC_NUMERIC */
175    {
176#  if defined (LC_NUMERIC)
177      if (lc_all == 0 || *lc_all == '\0')
178        return (setlocale (LC_NUMERIC, value ? value : "") != 0);
179#  endif /* LC_NUMERIC */
180    }
181#endif /* HAVE_SETLOCALE */
182
183  return (0);
184}
185
186/* Called when LANG is assigned a value.  Sets LC_ALL category with
187   setlocale(3) if that has not already been set.  Doesn't change any
188   shell variables. */
189int
190set_lang (var, value)
191     char *var, *value;
192{
193  return ((lc_all == 0 || *lc_all == 0) ? setlocale (LC_ALL, value?value:"") != NULL : 0);
194}
195
196/* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE) */
197char *
198get_locale_var (var)
199     char *var;
200{
201  char *locale;
202
203  locale = lc_all;
204
205  if (locale == 0)
206    locale = get_string_value (var);
207  if (locale == 0)
208    locale = default_locale;
209
210  return (locale);
211}
212
213/* Translate the contents of STRING, a $"..." quoted string, according
214   to the current locale.  In the `C' or `POSIX' locale, or if gettext()
215   is not available, the passed string is returned unchanged.  The
216   length of the translated string is returned in LENP, if non-null. */
217char *
218localetrans (string, len, lenp)
219     char *string;
220     int len, *lenp;
221{
222  char *locale, *t;
223#if defined (HAVE_GETTEXT)
224  char *translated;
225  int tlen;
226#endif
227
228  /* Don't try to translate null strings. */
229  if (string == 0 || *string == 0)
230    {
231      if (lenp)
232        *lenp = 0;
233      return ((char *)NULL);
234    }
235
236  locale = get_locale_var ("LC_MESSAGES");
237
238  /* If we don't have setlocale() or the current locale is `C' or `POSIX',
239     just return the string.  If we don't have gettext(), there's no use
240     doing anything else. */
241#if defined (HAVE_GETTEXT)
242  if (locale == 0 || locale[0] == '\0' ||
243      (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
244#endif
245    {
246      t = (char *)xmalloc (len + 1);
247      strcpy (t, string);
248      if (lenp)
249        *lenp = len;
250      return (t);
251    }
252
253#if defined (HAVE_GETTEXT)
254  /* Now try to translate it. */
255  translated = gettext (string);
256  if (translated == string)     /* gettext returns its argument if untranslatable */
257    {
258      t = (char *)xmalloc (len + 1);
259      strcpy (t, string);
260      if (lenp)
261        *lenp = len;
262    }
263  else
264    {
265      tlen = strlen (translated);
266      t = (char *)xmalloc (tlen + 1);
267      strcpy (t, translated);
268      if (lenp)
269        *lenp = tlen;
270    }
271  return (t);
272#endif /* HAVE_GETTEXT */
273}
274
275/* Change a bash string into a string suitable for inclusion in a `po' file.
276   This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
277char *
278mk_msgstr (string, foundnlp)
279     char *string;
280     int *foundnlp;
281{
282  register int c, len;
283  char *result, *r, *s;
284
285  for (len = 0, s = string; s && *s; s++)
286    {
287      len++;
288      if (*s == '"' || *s == '\\')
289        len++;
290      else if (*s == '\n')
291        len += 5;
292    }
293 
294  r = result = (char *)xmalloc (len + 3);
295  *r++ = '"';
296
297  for (s = string; s && (c = *s); s++)
298    {
299      if (c == '\n')    /* <NL> -> \n"<NL>" */
300        {
301          *r++ = '\\';
302          *r++ = 'n';
303          *r++ = '"';
304          *r++ = '\n';
305          *r++ = '"';
306          if (foundnlp)
307            *foundnlp = 1;
308          continue;
309        }
310      if (c == '"' || c == '\\')
311        *r++ = '\\';
312      *r++ = c;
313    }
314
315  *r++ = '"';
316  *r++ = '\0';
317
318  return result;
319}
320
321/* $"..." -- Translate the portion of STRING between START and END
322   according to current locale using gettext (if available) and return
323   the result.  The caller will take care of leaving the quotes intact.
324   The string will be left without the leading `$' by the caller.
325   If translation is performed, the translated string will be double-quoted
326   by the caller.  The length of the translated string is returned in LENP,
327   if non-null. */
328char *
329localeexpand (string, start, end, lineno, lenp)
330     char *string;
331     int start, end, lineno, *lenp;
332{
333  int len, tlen, foundnl;
334  char *temp, *t, *t2;
335
336  temp = (char *)xmalloc (end - start + 1);
337  for (tlen = 0, len = start; len < end; )
338    temp[tlen++] = string[len++];
339  temp[tlen] = '\0';
340
341  /* If we're just dumping translatable strings, don't do anything with the
342     string itself, but if we're dumping in `po' file format, convert it into a form more palatable to gettext(3)
343     and friends by quoting `"' and `\' with backslashes and converting <NL>
344     into `\n"<NL>"'.  If we find a newline in TEMP, we first output a
345     `msgid ""' line and then the translated string; otherwise we output the
346     `msgid' and translated string all on one line. */
347  if (dump_translatable_strings)
348    {
349      if (dump_po_strings)
350        {
351          foundnl = 0;
352          t = mk_msgstr (temp, &foundnl);
353          t2 = foundnl ? "\"\"\n" : "";
354
355          printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
356                        yy_input_name (), lineno, t2, t);
357          free (t);
358        }
359      else
360        printf ("\"%s\"\n", temp);
361
362      if (lenp)
363        *lenp = tlen;
364      return (temp);
365    }
366  else if (*temp)
367    {
368      t = localetrans (temp, tlen, &len);
369      free (temp);
370      if (lenp)
371        *lenp = len;
372      return (t);
373    }
374  else
375    {
376      if (lenp)
377        *lenp = 0;
378      return (temp);
379    }
380}
Note: See TracBrowser for help on using the repository browser.