source: trunk/libs/newlib/src/newlib/libc/locale/nl_langinfo.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 12.3 KB
Line 
1/*-
2 * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#define _GNU_SOURCE
28
29#include <sys/cdefs.h>
30
31#include <locale.h>
32#include <langinfo.h>
33#include <limits.h>
34#include <stdlib.h>
35#include <string.h>
36
37#include "setlocale.h"
38
39#undef offsetoff
40#define _O(TYPE, MEMBER)  __builtin_offsetof (TYPE, MEMBER)
41
42#define _NLITEM(cat,memb) { { cat:__get_##cat##_locale }, \
43                              _O (struct lc_##cat##_T, memb) }
44
45#ifdef __HAVE_LOCALE_INFO_EXTENDED__
46static struct _nl_item_t
47{
48  union {
49    const struct lc_ctype_T *    (*ctype)(struct __locale_t *);
50    const struct lc_time_T *     (*time)(struct __locale_t *);
51    const struct lc_numeric_T *  (*numeric)(struct __locale_t *);
52    const struct lc_monetary_T * (*monetary)(struct __locale_t *);
53    const struct lc_messages_T * (*messages)(struct __locale_t *);
54    void *                       (*base)(struct __locale_t *);
55  };
56  _off_t offset;
57} nl_ext[] =
58{
59  /* First element has an nl_item value of _NL_LOCALE_EXTENDED_FIRST_ENTRY */
60  _NLITEM (ctype, outdigits[0]),
61  _NLITEM (ctype, outdigits[1]),
62  _NLITEM (ctype, outdigits[2]),
63  _NLITEM (ctype, outdigits[3]),
64  _NLITEM (ctype, outdigits[4]),
65  _NLITEM (ctype, outdigits[5]),
66  _NLITEM (ctype, outdigits[6]),
67  _NLITEM (ctype, outdigits[7]),
68  _NLITEM (ctype, outdigits[8]),
69  _NLITEM (ctype, outdigits[9]),
70  _NLITEM (ctype, woutdigits[0]),
71  _NLITEM (ctype, woutdigits[1]),
72  _NLITEM (ctype, woutdigits[2]),
73  _NLITEM (ctype, woutdigits[3]),
74  _NLITEM (ctype, woutdigits[4]),
75  _NLITEM (ctype, woutdigits[5]),
76  _NLITEM (ctype, woutdigits[6]),
77  _NLITEM (ctype, woutdigits[7]),
78  _NLITEM (ctype, woutdigits[8]),
79  _NLITEM (ctype, woutdigits[9]),
80  _NLITEM (time, codeset),
81  _NLITEM (time, wmon[1]),
82  _NLITEM (time, wmon[2]),
83  _NLITEM (time, wmon[3]),
84  _NLITEM (time, wmon[4]),
85  _NLITEM (time, wmon[5]),
86  _NLITEM (time, wmon[6]),
87  _NLITEM (time, wmon[7]),
88  _NLITEM (time, wmon[8]),
89  _NLITEM (time, wmon[9]),
90  _NLITEM (time, wmon[10]),
91  _NLITEM (time, wmon[11]),
92  _NLITEM (time, wmon[12]),
93  _NLITEM (time, wmonth[1]),
94  _NLITEM (time, wmonth[2]),
95  _NLITEM (time, wmonth[3]),
96  _NLITEM (time, wmonth[4]),
97  _NLITEM (time, wmonth[5]),
98  _NLITEM (time, wmonth[6]),
99  _NLITEM (time, wmonth[7]),
100  _NLITEM (time, wmonth[8]),
101  _NLITEM (time, wmonth[9]),
102  _NLITEM (time, wmonth[10]),
103  _NLITEM (time, wmonth[11]),
104  _NLITEM (time, wmonth[12]),
105  _NLITEM (time, wwday[1]),
106  _NLITEM (time, wwday[2]),
107  _NLITEM (time, wwday[3]),
108  _NLITEM (time, wwday[4]),
109  _NLITEM (time, wwday[5]),
110  _NLITEM (time, wwday[6]),
111  _NLITEM (time, wwday[7]),
112  _NLITEM (time, wweekday[1]),
113  _NLITEM (time, wweekday[2]),
114  _NLITEM (time, wweekday[3]),
115  _NLITEM (time, wweekday[4]),
116  _NLITEM (time, wweekday[5]),
117  _NLITEM (time, wweekday[6]),
118  _NLITEM (time, wweekday[7]),
119  _NLITEM (time, wX_fmt),
120  _NLITEM (time, wx_fmt),
121  _NLITEM (time, wc_fmt),
122  _NLITEM (time, wam_pm[0]),
123  _NLITEM (time, wam_pm[1]),
124  _NLITEM (time, wdate_fmt),
125  _NLITEM (time, wampm_fmt),
126  _NLITEM (time, wera),
127  _NLITEM (time, wera_d_fmt),
128  _NLITEM (time, wera_d_t_fmt),
129  _NLITEM (time, wera_t_fmt),
130  _NLITEM (time, walt_digits),
131  _NLITEM (numeric, codeset),
132  _NLITEM (numeric, grouping),
133  _NLITEM (numeric, wdecimal_point),
134  _NLITEM (numeric, wthousands_sep),
135  _NLITEM (monetary, int_curr_symbol),
136  _NLITEM (monetary, currency_symbol),
137  _NLITEM (monetary, mon_decimal_point),
138  _NLITEM (monetary, mon_thousands_sep),
139  _NLITEM (monetary, mon_grouping),
140  _NLITEM (monetary, positive_sign),
141  _NLITEM (monetary, negative_sign),
142  _NLITEM (monetary, int_frac_digits),
143  _NLITEM (monetary, frac_digits),
144  _NLITEM (monetary, p_cs_precedes),
145  _NLITEM (monetary, p_sep_by_space),
146  _NLITEM (monetary, n_cs_precedes),
147  _NLITEM (monetary, n_sep_by_space),
148  _NLITEM (monetary, p_sign_posn),
149  _NLITEM (monetary, n_sign_posn),
150  _NLITEM (monetary, int_p_cs_precedes),
151  _NLITEM (monetary, int_p_sep_by_space),
152  _NLITEM (monetary, int_n_cs_precedes),
153  _NLITEM (monetary, int_n_sep_by_space),
154  _NLITEM (monetary, int_p_sign_posn),
155  _NLITEM (monetary, int_n_sign_posn),
156  _NLITEM (monetary, codeset),
157  _NLITEM (monetary, wint_curr_symbol),
158  _NLITEM (monetary, wcurrency_symbol),
159  _NLITEM (monetary, wmon_decimal_point),
160  _NLITEM (monetary, wmon_thousands_sep),
161  _NLITEM (monetary, wpositive_sign),
162  _NLITEM (monetary, wnegative_sign),
163  _NLITEM (messages, codeset),
164  _NLITEM (messages, wyesexpr),
165  _NLITEM (messages, wnoexpr),
166  _NLITEM (messages, wyesstr),
167  _NLITEM (messages, wnostr),
168};
169#endif /* __HAVE_LOCALE_INFO_EXTENDED__ */
170
171#define _REL(BASE) ((int)item-BASE)
172
173char *nl_langinfo_l (nl_item item, struct __locale_t *locale)
174{
175   char *ret, *cs;
176#ifndef __CYGWIN__
177   char *s;
178#endif
179   static char *csym = NULL;
180   char *nptr;
181
182   switch (item) {
183#ifdef __HAVE_LOCALE_INFO__
184        case _NL_MESSAGES_CODESET:
185                ret = (char *) __get_messages_locale (locale)->codeset;
186                goto do_codeset;
187#ifdef __HAVE_LOCALE_INFO_EXTENDED__
188        case _NL_TIME_CODESET:
189                ret = (char *) __get_time_locale (locale)->codeset;
190                goto do_codeset;
191        case _NL_NUMERIC_CODESET:
192                ret = (char *) __get_numeric_locale (locale)->codeset;
193                goto do_codeset;
194        case _NL_MONETARY_CODESET:
195                ret = (char *) __get_monetary_locale (locale)->codeset;
196                goto do_codeset;
197#ifdef __CYGWIN__
198        case _NL_COLLATE_CODESET:
199                {
200                  ret = (char *) __get_collate_locale (locale)->codeset;
201                  goto do_codeset;
202                }
203#endif /* __CYGWIN__ */
204#endif /* __HAVE_LOCALE_INFO_EXTENDED__ */
205#endif /* __HAVE_LOCALE_INFO__ */
206        case CODESET:
207#ifdef _MB_CAPABLE
208                ret = (char *) __locale_charset (locale);
209#endif
210do_codeset:
211#ifdef __CYGWIN__
212                /* Convert charset to Linux compatible codeset string. */
213                if (ret[0] == 'A'/*SCII*/)
214                  ret = "ANSI_X3.4-1968";
215                else if (ret[0] == 'E')
216                  {
217                    if (strcmp (ret, "EUCJP") == 0)
218                      ret = "EUC-JP";
219                    else if (strcmp (ret, "EUCKR") == 0)
220                      ret = "EUC-KR";
221                    else if (strcmp (ret, "EUCCN") == 0)
222                      ret = "GB2312";
223                  }
224                else if (ret[0] == 'C'/*Pxxxx*/)
225                  {
226                    if (strcmp (ret + 2, "874") == 0)
227                      ret = "TIS-620";
228                    else if (strcmp (ret + 2, "20866") == 0)
229                      ret = "KOI8-R";
230                    else if (strcmp (ret + 2, "21866") == 0)
231                      ret = "KOI8-U";
232                    else if (strcmp (ret + 2, "101") == 0)
233                      ret = "GEORGIAN-PS";
234                    else if (strcmp (ret + 2, "102") == 0)
235                      ret = "PT154";
236                  }
237                else if (ret[0] == 'S'/*JIS*/)
238                  {
239                    /* Cygwin uses MSFT's implementation of SJIS, which differs
240                       in some codepoints from the real thing, especially
241                       0x5c: yen sign instead of backslash,
242                       0x7e: overline instead of tilde.
243                       We can't use the real SJIS since otherwise Win32
244                       pathnames would become invalid.  OTOH, if we return
245                       "SJIS" here, then libiconv will do mb<->wc conversion
246                       differently to our internal functions.  Therefore we
247                       return what we really implement, CP932.  This is handled
248                       fine by libiconv. */
249                    ret = "CP932";
250                  }
251#elif !defined (_MB_CAPABLE)
252                ret = "US-ASCII";
253#endif /* __CYGWIN__ */
254                break;
255        case D_T_FMT:
256                ret = (char *) __get_time_locale (locale)->c_fmt;
257                break;
258        case D_FMT:
259                ret = (char *) __get_time_locale (locale)->x_fmt;
260                break;
261        case T_FMT:
262                ret = (char *) __get_time_locale (locale)->X_fmt;
263                break;
264        case T_FMT_AMPM:
265                ret = (char *) __get_time_locale (locale)->ampm_fmt;
266                break;
267        case AM_STR:
268                ret = (char *) __get_time_locale (locale)->am_pm[0];
269                break;
270        case PM_STR:
271                ret = (char *) __get_time_locale (locale)->am_pm[1];
272                break;
273        case DAY_1: case DAY_2: case DAY_3:
274        case DAY_4: case DAY_5: case DAY_6: case DAY_7:
275                ret = (char*) __get_time_locale (locale)->weekday[_REL(DAY_1)];
276                break;
277        case ABDAY_1: case ABDAY_2: case ABDAY_3:
278        case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7:
279                ret = (char*) __get_time_locale (locale)->wday[_REL(ABDAY_1)];
280                break;
281        case MON_1: case MON_2: case MON_3: case MON_4:
282        case MON_5: case MON_6: case MON_7: case MON_8:
283        case MON_9: case MON_10: case MON_11: case MON_12:
284                ret = (char*) __get_time_locale (locale)->month[_REL(MON_1)];
285                break;
286        case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4:
287        case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8:
288        case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
289                ret = (char*) __get_time_locale (locale)->mon[_REL(ABMON_1)];
290                break;
291        case ERA:
292                ret = (char*) __get_time_locale (locale)->era;
293                break;
294        case ERA_D_FMT:
295                ret = (char*) __get_time_locale (locale)->era_d_fmt;
296                break;
297        case ERA_D_T_FMT:
298                ret = (char*) __get_time_locale (locale)->era_d_t_fmt;
299                break;
300        case ERA_T_FMT:
301                ret = (char*) __get_time_locale (locale)->era_t_fmt;
302                break;
303        case ALT_DIGITS:
304                ret = (char*) __get_time_locale (locale)->alt_digits;
305                break;
306        case _DATE_FMT: /* GNU extension */
307                ret = (char*) __get_time_locale (locale)->date_fmt;
308                break;
309        case RADIXCHAR:
310                ret = (char*) __get_numeric_locale (locale)->decimal_point;
311                break;
312        case THOUSEP:
313                ret = (char*) __get_numeric_locale (locale)->thousands_sep;
314                break;
315        case YESEXPR:
316                ret = (char*) __get_messages_locale (locale)->yesexpr;
317                break;
318        case NOEXPR:
319                ret = (char*) __get_messages_locale (locale)->noexpr;
320                break;
321        /*
322         * All items marked with LEGACY are available, but not recomended
323         * by SUSv2 to be used in portable applications since they're subject
324         * to remove in future specification editions
325         */
326        case YESSTR:            /* LEGACY  */
327                ret = (char*) __get_messages_locale (locale)->yesstr;
328                break;
329        case NOSTR:             /* LEGACY  */
330                ret = (char*) __get_messages_locale (locale)->nostr;
331                break;
332        case CRNCYSTR:
333                ret = "";
334                cs = (char*) __get_monetary_locale (locale)->currency_symbol;
335                if (*cs != '\0') {
336                        char pos = __localeconv_l (locale)->p_cs_precedes;
337
338                        if (pos == __localeconv_l (locale)->n_cs_precedes) {
339                                char psn = '\0';
340
341                                if (pos == CHAR_MAX) {
342                                        if (strcmp(cs, __get_monetary_locale (locale)->mon_decimal_point) == 0)
343                                                psn = '.';
344                                } else
345                                        psn = pos ? '-' : '+';
346                                if (psn != '\0') {
347                                        int clen = strlen(cs);
348
349                                        nptr = realloc(csym, clen + 2);
350                                        if (!nptr && csym)
351                                          free (csym);
352
353                                        csym = nptr;
354
355                                        if (csym != NULL) {
356                                                *csym = psn;
357                                                strcpy(csym + 1, cs);
358                                                ret = csym;
359                                        }
360                                }
361                        }
362                }
363                break;
364        case D_MD_ORDER:        /* local extension */
365                ret = (char *) __get_time_locale (locale)->md_order;
366                break;
367#ifdef __HAVE_LOCALE_INFO__
368        case _NL_CTYPE_MB_CUR_MAX:
369                ret = (char *) __get_ctype_locale (locale)->mb_cur_max;
370                break;
371#endif
372        default:
373                /* Relies on the fact that LC_ALL is 0, and all other
374                   LC_ constants are in ascending order. */
375                if (item > NL_LOCALE_NAME(LC_ALL)
376                    && item < NL_LOCALE_NAME(_LC_LAST)) {
377                        return locale->categories[item
378                                                  - NL_LOCALE_NAME(LC_ALL)];
379                }
380#ifdef __HAVE_LOCALE_INFO_EXTENDED__
381                if (item > _NL_LOCALE_EXTENDED_FIRST_ENTRY
382                    && item < _NL_LOCALE_EXTENDED_LAST_ENTRY) {
383                        int idx = item - _NL_LOCALE_EXTENDED_FIRST_ENTRY - 1;
384                        return *(char **) ((char *) (*nl_ext[idx].base)(locale)
385                                           + nl_ext[idx].offset);
386                }
387#endif
388                ret = "";
389   }
390   return (ret);
391}
392
393char *nl_langinfo (nl_item item)
394{
395  return nl_langinfo_l (item, __get_current_locale ());
396}
Note: See TracBrowser for help on using the repository browser.