summaryrefslogtreecommitdiffstats
path: root/gl/nl_langinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/nl_langinfo.c')
-rw-r--r--gl/nl_langinfo.c579
1 files changed, 440 insertions, 139 deletions
diff --git a/gl/nl_langinfo.c b/gl/nl_langinfo.c
index 771c9533..131166fd 100644
--- a/gl/nl_langinfo.c
+++ b/gl/nl_langinfo.c
@@ -1,34 +1,278 @@
1/* nl_langinfo() replacement: query locale dependent information. 1/* nl_langinfo() replacement: query locale dependent information.
2 2
3 Copyright (C) 2007-2013 Free Software Foundation, Inc. 3 Copyright (C) 2007-2023 Free Software Foundation, Inc.
4 4
5 This program is free software: you can redistribute it and/or modify 5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU Lesser General Public License as
7 the Free Software Foundation; either version 3 of the License, or 7 published by the Free Software Foundation; either version 2.1 of the
8 (at your option) any later version. 8 License, or (at your option) any later version.
9 9
10 This program is distributed in the hope that it will be useful, 10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details. 13 GNU Lesser General Public License for more details.
14 14
15 You should have received a copy of the GNU General Public License 15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 17
18#include <config.h> 18#include <config.h>
19 19
20/* Specification. */ 20/* Specification. */
21#include <langinfo.h> 21#include <langinfo.h>
22 22
23#include <locale.h>
24#include <stdlib.h>
25#include <string.h>
26#if defined _WIN32 && ! defined __CYGWIN__
27# define WIN32_LEAN_AND_MEAN /* avoid including junk */
28# include <windows.h>
29# include <stdio.h>
30#endif
31
32#if REPLACE_NL_LANGINFO && !NL_LANGINFO_MTSAFE
33# if defined _WIN32 && !defined __CYGWIN__
34
35# define WIN32_LEAN_AND_MEAN /* avoid including junk */
36# include <windows.h>
37
38# elif HAVE_PTHREAD_API
39
40# include <pthread.h>
41# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
42# include <threads.h>
43# pragma weak thrd_exit
44# define c11_threads_in_use() (thrd_exit != NULL)
45# else
46# define c11_threads_in_use() 0
47# endif
48
49# elif HAVE_THREADS_H
50
51# include <threads.h>
52
53# endif
54#endif
55
56/* nl_langinfo() must be multithread-safe. To achieve this without using
57 thread-local storage:
58 1. We use a specific static buffer for each possible argument.
59 So that different threads can call nl_langinfo with different arguments,
60 without interfering.
61 2. We use a simple strcpy or memcpy to fill this static buffer. Filling it
62 through, for example, strcpy + strcat would not be guaranteed to leave
63 the buffer's contents intact if another thread is currently accessing
64 it. If necessary, the contents is first assembled in a stack-allocated
65 buffer. */
66
67#if !REPLACE_NL_LANGINFO || GNULIB_defined_CODESET
68/* Return the codeset of the current locale, if this is easily deducible.
69 Otherwise, return "". */
70static char *
71ctype_codeset (void)
72{
73 static char result[2 + 10 + 1];
74 char buf[2 + 10 + 1];
75 char locale[SETLOCALE_NULL_MAX];
76 char *codeset;
77 size_t codesetlen;
78
79 if (setlocale_null_r (LC_CTYPE, locale, sizeof (locale)))
80 locale[0] = '\0';
81
82 codeset = buf;
83 codeset[0] = '\0';
84
85 if (locale[0])
86 {
87 /* If the locale name contains an encoding after the dot, return it. */
88 char *dot = strchr (locale, '.');
89
90 if (dot)
91 {
92 /* Look for the possible @... trailer and remove it, if any. */
93 char *codeset_start = dot + 1;
94 char const *modifier = strchr (codeset_start, '@');
95
96 if (! modifier)
97 codeset = codeset_start;
98 else
99 {
100 codesetlen = modifier - codeset_start;
101 if (codesetlen < sizeof buf)
102 {
103 codeset = memcpy (buf, codeset_start, codesetlen);
104 codeset[codesetlen] = '\0';
105 }
106 }
107 }
108 }
109
110# if defined _WIN32 && ! defined __CYGWIN__
111 /* If setlocale is successful, it returns the number of the
112 codepage, as a string. Otherwise, fall back on Windows API
113 GetACP, which returns the locale's codepage as a number (although
114 this doesn't change according to what the 'setlocale' call specified).
115 Either way, prepend "CP" to make it a valid codeset name. */
116 codesetlen = strlen (codeset);
117 if (0 < codesetlen && codesetlen < sizeof buf - 2)
118 memmove (buf + 2, codeset, codesetlen + 1);
119 else
120 sprintf (buf + 2, "%u", GetACP ());
121 /* For a locale name such as "French_France.65001", in Windows 10,
122 setlocale now returns "French_France.utf8" instead. */
123 if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0)
124 return (char *) "UTF-8";
125 else
126 {
127 memcpy (buf, "CP", 2);
128 strcpy (result, buf);
129 return result;
130 }
131# else
132 strcpy (result, codeset);
133 return result;
134#endif
135}
136#endif
137
138
23#if REPLACE_NL_LANGINFO 139#if REPLACE_NL_LANGINFO
24 140
25/* Override nl_langinfo with support for added nl_item values. */ 141/* Override nl_langinfo with support for added nl_item values. */
26 142
27# include <locale.h>
28# include <string.h>
29
30# undef nl_langinfo 143# undef nl_langinfo
31 144
145/* Without locking, on Solaris 11.3, test-nl_langinfo-mt fails, with message
146 "thread5 disturbed by threadN!", even when threadN invokes only
147 nl_langinfo (CODESET);
148 nl_langinfo (CRNCYSTR);
149 Similarly on Solaris 10. */
150
151# if !NL_LANGINFO_MTSAFE /* Solaris */
152
153# define ITEMS (MAXSTRMSG + 1)
154# define MAX_RESULT_LEN 80
155
156static char *
157nl_langinfo_unlocked (nl_item item)
158{
159 static char result[ITEMS][MAX_RESULT_LEN];
160
161 /* The result of nl_langinfo is in storage that can be overwritten by
162 other calls to nl_langinfo. */
163 char *tmp = nl_langinfo (item);
164 if (item >= 0 && item < ITEMS && tmp != NULL)
165 {
166 size_t tmp_len = strlen (tmp);
167 if (tmp_len < MAX_RESULT_LEN)
168 strcpy (result[item], tmp);
169 else
170 {
171 /* Produce a truncated result. Oh well... */
172 result[item][MAX_RESULT_LEN - 1] = '\0';
173 memcpy (result[item], tmp, MAX_RESULT_LEN - 1);
174 }
175 return result[item];
176 }
177 else
178 return tmp;
179}
180
181/* Use a lock, so that no two threads can invoke nl_langinfo_unlocked
182 at the same time. */
183
184/* Prohibit renaming this symbol. */
185# undef gl_get_nl_langinfo_lock
186
187# if defined _WIN32 && !defined __CYGWIN__
188
189extern __declspec(dllimport) CRITICAL_SECTION *gl_get_nl_langinfo_lock (void);
190
191static char *
192nl_langinfo_with_lock (nl_item item)
193{
194 CRITICAL_SECTION *lock = gl_get_nl_langinfo_lock ();
195 char *ret;
196
197 EnterCriticalSection (lock);
198 ret = nl_langinfo_unlocked (item);
199 LeaveCriticalSection (lock);
200
201 return ret;
202}
203
204# elif HAVE_PTHREAD_API
205
206extern
207# if defined _WIN32 || defined __CYGWIN__
208 __declspec(dllimport)
209# endif
210 pthread_mutex_t *gl_get_nl_langinfo_lock (void);
211
212# if HAVE_WEAK_SYMBOLS /* musl libc, FreeBSD, NetBSD, OpenBSD, Haiku */
213
214 /* Avoid the need to link with '-lpthread'. */
215# pragma weak pthread_mutex_lock
216# pragma weak pthread_mutex_unlock
217
218 /* Determine whether libpthread is in use. */
219# pragma weak pthread_mutexattr_gettype
220 /* See the comments in lock.h. */
221# define pthread_in_use() \
222 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
223
224# else
225# define pthread_in_use() 1
226# endif
227
228static char *
229nl_langinfo_with_lock (nl_item item)
230{
231 if (pthread_in_use())
232 {
233 pthread_mutex_t *lock = gl_get_nl_langinfo_lock ();
234 char *ret;
235
236 if (pthread_mutex_lock (lock))
237 abort ();
238 ret = nl_langinfo_unlocked (item);
239 if (pthread_mutex_unlock (lock))
240 abort ();
241
242 return ret;
243 }
244 else
245 return nl_langinfo_unlocked (item);
246}
247
248# elif HAVE_THREADS_H
249
250extern mtx_t *gl_get_nl_langinfo_lock (void);
251
252static char *
253nl_langinfo_with_lock (nl_item item)
254{
255 mtx_t *lock = gl_get_nl_langinfo_lock ();
256 char *ret;
257
258 if (mtx_lock (lock) != thrd_success)
259 abort ();
260 ret = nl_langinfo_unlocked (item);
261 if (mtx_unlock (lock) != thrd_success)
262 abort ();
263
264 return ret;
265}
266
267# endif
268
269# else
270
271/* On other platforms, no lock is needed. */
272# define nl_langinfo_with_lock nl_langinfo
273
274# endif
275
32char * 276char *
33rpl_nl_langinfo (nl_item item) 277rpl_nl_langinfo (nl_item item)
34{ 278{
@@ -36,47 +280,36 @@ rpl_nl_langinfo (nl_item item)
36 { 280 {
37# if GNULIB_defined_CODESET 281# if GNULIB_defined_CODESET
38 case CODESET: 282 case CODESET:
39 { 283 return ctype_codeset ();
40 const char *locale;
41 static char buf[2 + 10 + 1];
42
43 locale = setlocale (LC_CTYPE, NULL);
44 if (locale != NULL && locale[0] != '\0')
45 {
46 /* If the locale name contains an encoding after the dot, return
47 it. */
48 const char *dot = strchr (locale, '.');
49
50 if (dot != NULL)
51 {
52 const char *modifier;
53
54 dot++;
55 /* Look for the possible @... trailer and remove it, if any. */
56 modifier = strchr (dot, '@');
57 if (modifier == NULL)
58 return dot;
59 if (modifier - dot < sizeof (buf))
60 {
61 memcpy (buf, dot, modifier - dot);
62 buf [modifier - dot] = '\0';
63 return buf;
64 }
65 }
66 }
67 return "";
68 }
69# endif 284# endif
70# if GNULIB_defined_T_FMT_AMPM 285# if GNULIB_defined_T_FMT_AMPM
71 case T_FMT_AMPM: 286 case T_FMT_AMPM:
72 return "%I:%M:%S %p"; 287 return (char *) "%I:%M:%S %p";
288# endif
289# if GNULIB_defined_ALTMON
290 case ALTMON_1:
291 case ALTMON_2:
292 case ALTMON_3:
293 case ALTMON_4:
294 case ALTMON_5:
295 case ALTMON_6:
296 case ALTMON_7:
297 case ALTMON_8:
298 case ALTMON_9:
299 case ALTMON_10:
300 case ALTMON_11:
301 case ALTMON_12:
302 /* We don't ship the appropriate localizations with gnulib. Therefore,
303 treat ALTMON_i like MON_i. */
304 item = item - ALTMON_1 + MON_1;
305 break;
73# endif 306# endif
74# if GNULIB_defined_ERA 307# if GNULIB_defined_ERA
75 case ERA: 308 case ERA:
76 /* The format is not standardized. In glibc it is a sequence of strings 309 /* The format is not standardized. In glibc it is a sequence of strings
77 of the form "direction:offset:start_date:end_date:era_name:era_format" 310 of the form "direction:offset:start_date:end_date:era_name:era_format"
78 with an empty string at the end. */ 311 with an empty string at the end. */
79 return ""; 312 return (char *) "";
80 case ERA_D_FMT: 313 case ERA_D_FMT:
81 /* The %Ex conversion in strftime behaves like %x if the locale does not 314 /* The %Ex conversion in strftime behaves like %x if the locale does not
82 have an alternative time format. */ 315 have an alternative time format. */
@@ -95,176 +328,244 @@ rpl_nl_langinfo (nl_item item)
95 case ALT_DIGITS: 328 case ALT_DIGITS:
96 /* The format is not standardized. In glibc it is a sequence of 10 329 /* The format is not standardized. In glibc it is a sequence of 10
97 strings, appended in memory. */ 330 strings, appended in memory. */
98 return "\0\0\0\0\0\0\0\0\0\0"; 331 return (char *) "\0\0\0\0\0\0\0\0\0\0";
99# endif 332# endif
100# if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS 333# if GNULIB_defined_YESEXPR || !FUNC_NL_LANGINFO_YESEXPR_WORKS
101 case YESEXPR: 334 case YESEXPR:
102 return "^[yY]"; 335 return (char *) "^[yY]";
103 case NOEXPR: 336 case NOEXPR:
104 return "^[nN]"; 337 return (char *) "^[nN]";
105# endif 338# endif
106 default: 339 default:
107 break; 340 break;
108 } 341 }
109 return nl_langinfo (item); 342 return nl_langinfo_with_lock (item);
110} 343}
111 344
112#else 345#else
113 346
114/* Provide nl_langinfo from scratch. */ 347/* Provide nl_langinfo from scratch, either for native MS-Windows, or
115 348 for old Unix platforms without locales, such as Linux libc5 or
116# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 349 BeOS. */
117 350
118/* Native Windows platforms. */ 351# include <time.h>
119
120# define WIN32_LEAN_AND_MEAN /* avoid including junk */
121# include <windows.h>
122
123# include <stdio.h>
124
125# else
126
127/* An old Unix platform without locales, such as Linux libc5 or BeOS. */
128
129# endif
130
131# include <locale.h>
132 352
133char * 353char *
134nl_langinfo (nl_item item) 354nl_langinfo (nl_item item)
135{ 355{
356 char buf[100];
357 struct tm tmm = { 0 };
358
136 switch (item) 359 switch (item)
137 { 360 {
138 /* nl_langinfo items of the LC_CTYPE category */ 361 /* nl_langinfo items of the LC_CTYPE category */
139 case CODESET: 362 case CODESET:
140# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
141 { 363 {
142 static char buf[2 + 10 + 1]; 364 char *codeset = ctype_codeset ();
143 365 if (*codeset)
144 /* The Windows API has a function returning the locale's codepage as 366 return codeset;
145 a number. */
146 sprintf (buf, "CP%u", GetACP ());
147 return buf;
148 } 367 }
149# elif defined __BEOS__ 368# ifdef __BEOS__
150 return "UTF-8"; 369 return (char *) "UTF-8";
151# else 370# else
152 return "ISO-8859-1"; 371 return (char *) "ISO-8859-1";
153# endif 372# endif
154 /* nl_langinfo items of the LC_NUMERIC category */ 373 /* nl_langinfo items of the LC_NUMERIC category */
155 case RADIXCHAR: 374 case RADIXCHAR:
156 return localeconv () ->decimal_point; 375 return localeconv () ->decimal_point;
157 case THOUSEP: 376 case THOUSEP:
158 return localeconv () ->thousands_sep; 377 return localeconv () ->thousands_sep;
378# ifdef GROUPING
379 case GROUPING:
380 return localeconv () ->grouping;
381# endif
159 /* nl_langinfo items of the LC_TIME category. 382 /* nl_langinfo items of the LC_TIME category.
160 TODO: Really use the locale. */ 383 TODO: Really use the locale. */
161 case D_T_FMT: 384 case D_T_FMT:
162 case ERA_D_T_FMT: 385 case ERA_D_T_FMT:
163 return "%a %b %e %H:%M:%S %Y"; 386 return (char *) "%a %b %e %H:%M:%S %Y";
164 case D_FMT: 387 case D_FMT:
165 case ERA_D_FMT: 388 case ERA_D_FMT:
166 return "%m/%d/%y"; 389 return (char *) "%m/%d/%y";
167 case T_FMT: 390 case T_FMT:
168 case ERA_T_FMT: 391 case ERA_T_FMT:
169 return "%H:%M:%S"; 392 return (char *) "%H:%M:%S";
170 case T_FMT_AMPM: 393 case T_FMT_AMPM:
171 return "%I:%M:%S %p"; 394 return (char *) "%I:%M:%S %p";
172 case AM_STR: 395 case AM_STR:
173 return "AM"; 396 {
397 static char result[80];
398 if (!strftime (buf, sizeof result, "%p", &tmm))
399 return (char *) "AM";
400 strcpy (result, buf);
401 return result;
402 }
174 case PM_STR: 403 case PM_STR:
175 return "PM"; 404 {
405 static char result[80];
406 tmm.tm_hour = 12;
407 if (!strftime (buf, sizeof result, "%p", &tmm))
408 return (char *) "PM";
409 strcpy (result, buf);
410 return result;
411 }
176 case DAY_1: 412 case DAY_1:
177 return "Sunday";
178 case DAY_2: 413 case DAY_2:
179 return "Monday";
180 case DAY_3: 414 case DAY_3:
181 return "Tuesday";
182 case DAY_4: 415 case DAY_4:
183 return "Wednesday";
184 case DAY_5: 416 case DAY_5:
185 return "Thursday";
186 case DAY_6: 417 case DAY_6:
187 return "Friday";
188 case DAY_7: 418 case DAY_7:
189 return "Saturday"; 419 {
420 static char result[7][50];
421 static char const days[][sizeof "Wednesday"] = {
422 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
423 "Friday", "Saturday"
424 };
425 tmm.tm_wday = item - DAY_1;
426 if (!strftime (buf, sizeof result[0], "%A", &tmm))
427 return (char *) days[item - DAY_1];
428 strcpy (result[item - DAY_1], buf);
429 return result[item - DAY_1];
430 }
190 case ABDAY_1: 431 case ABDAY_1:
191 return "Sun";
192 case ABDAY_2: 432 case ABDAY_2:
193 return "Mon";
194 case ABDAY_3: 433 case ABDAY_3:
195 return "Tue";
196 case ABDAY_4: 434 case ABDAY_4:
197 return "Wed";
198 case ABDAY_5: 435 case ABDAY_5:
199 return "Thu";
200 case ABDAY_6: 436 case ABDAY_6:
201 return "Fri";
202 case ABDAY_7: 437 case ABDAY_7:
203 return "Sat"; 438 {
204 case MON_1: 439 static char result[7][30];
205 return "January"; 440 static char const abdays[][sizeof "Sun"] = {
206 case MON_2: 441 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
207 return "February"; 442 };
208 case MON_3: 443 tmm.tm_wday = item - ABDAY_1;
209 return "March"; 444 if (!strftime (buf, sizeof result[0], "%a", &tmm))
210 case MON_4: 445 return (char *) abdays[item - ABDAY_1];
211 return "April"; 446 strcpy (result[item - ABDAY_1], buf);
212 case MON_5: 447 return result[item - ABDAY_1];
213 return "May"; 448 }
214 case MON_6: 449 {
215 return "June"; 450 static char const months[][sizeof "September"] = {
216 case MON_7: 451 "January", "February", "March", "April", "May", "June", "July",
217 return "July"; 452 "September", "October", "November", "December"
218 case MON_8: 453 };
219 return "August"; 454 case MON_1:
220 case MON_9: 455 case MON_2:
221 return "September"; 456 case MON_3:
222 case MON_10: 457 case MON_4:
223 return "October"; 458 case MON_5:
224 case MON_11: 459 case MON_6:
225 return "November"; 460 case MON_7:
226 case MON_12: 461 case MON_8:
227 return "December"; 462 case MON_9:
463 case MON_10:
464 case MON_11:
465 case MON_12:
466 {
467 static char result[12][50];
468 tmm.tm_mon = item - MON_1;
469 if (!strftime (buf, sizeof result[0], "%B", &tmm))
470 return (char *) months[item - MON_1];
471 strcpy (result[item - MON_1], buf);
472 return result[item - MON_1];
473 }
474 case ALTMON_1:
475 case ALTMON_2:
476 case ALTMON_3:
477 case ALTMON_4:
478 case ALTMON_5:
479 case ALTMON_6:
480 case ALTMON_7:
481 case ALTMON_8:
482 case ALTMON_9:
483 case ALTMON_10:
484 case ALTMON_11:
485 case ALTMON_12:
486 {
487 static char result[12][50];
488 tmm.tm_mon = item - ALTMON_1;
489 /* The platforms without nl_langinfo() don't support strftime with
490 %OB. We don't even need to try. */
491 #if 0
492 if (!strftime (buf, sizeof result[0], "%OB", &tmm))
493 #endif
494 if (!strftime (buf, sizeof result[0], "%B", &tmm))
495 return (char *) months[item - ALTMON_1];
496 strcpy (result[item - ALTMON_1], buf);
497 return result[item - ALTMON_1];
498 }
499 }
228 case ABMON_1: 500 case ABMON_1:
229 return "Jan";
230 case ABMON_2: 501 case ABMON_2:
231 return "Feb";
232 case ABMON_3: 502 case ABMON_3:
233 return "Mar";
234 case ABMON_4: 503 case ABMON_4:
235 return "Apr";
236 case ABMON_5: 504 case ABMON_5:
237 return "May";
238 case ABMON_6: 505 case ABMON_6:
239 return "Jun";
240 case ABMON_7: 506 case ABMON_7:
241 return "Jul";
242 case ABMON_8: 507 case ABMON_8:
243 return "Aug";
244 case ABMON_9: 508 case ABMON_9:
245 return "Sep";
246 case ABMON_10: 509 case ABMON_10:
247 return "Oct";
248 case ABMON_11: 510 case ABMON_11:
249 return "Nov";
250 case ABMON_12: 511 case ABMON_12:
251 return "Dec"; 512 {
513 static char result[12][30];
514 static char const abmonths[][sizeof "Jan"] = {
515 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
516 "Sep", "Oct", "Nov", "Dec"
517 };
518 tmm.tm_mon = item - ABMON_1;
519 if (!strftime (buf, sizeof result[0], "%b", &tmm))
520 return (char *) abmonths[item - ABMON_1];
521 strcpy (result[item - ABMON_1], buf);
522 return result[item - ABMON_1];
523 }
252 case ERA: 524 case ERA:
253 return ""; 525 return (char *) "";
254 case ALT_DIGITS: 526 case ALT_DIGITS:
255 return "\0\0\0\0\0\0\0\0\0\0"; 527 return (char *) "\0\0\0\0\0\0\0\0\0\0";
256 /* nl_langinfo items of the LC_MONETARY category 528 /* nl_langinfo items of the LC_MONETARY category. */
257 TODO: Really use the locale. */
258 case CRNCYSTR: 529 case CRNCYSTR:
259 return "-"; 530 return localeconv () ->currency_symbol;
531# ifdef INT_CURR_SYMBOL
532 case INT_CURR_SYMBOL:
533 return localeconv () ->int_curr_symbol;
534 case MON_DECIMAL_POINT:
535 return localeconv () ->mon_decimal_point;
536 case MON_THOUSANDS_SEP:
537 return localeconv () ->mon_thousands_sep;
538 case MON_GROUPING:
539 return localeconv () ->mon_grouping;
540 case POSITIVE_SIGN:
541 return localeconv () ->positive_sign;
542 case NEGATIVE_SIGN:
543 return localeconv () ->negative_sign;
544 case FRAC_DIGITS:
545 return & localeconv () ->frac_digits;
546 case INT_FRAC_DIGITS:
547 return & localeconv () ->int_frac_digits;
548 case P_CS_PRECEDES:
549 return & localeconv () ->p_cs_precedes;
550 case N_CS_PRECEDES:
551 return & localeconv () ->n_cs_precedes;
552 case P_SEP_BY_SPACE:
553 return & localeconv () ->p_sep_by_space;
554 case N_SEP_BY_SPACE:
555 return & localeconv () ->n_sep_by_space;
556 case P_SIGN_POSN:
557 return & localeconv () ->p_sign_posn;
558 case N_SIGN_POSN:
559 return & localeconv () ->n_sign_posn;
560# endif
260 /* nl_langinfo items of the LC_MESSAGES category 561 /* nl_langinfo items of the LC_MESSAGES category
261 TODO: Really use the locale. */ 562 TODO: Really use the locale. */
262 case YESEXPR: 563 case YESEXPR:
263 return "^[yY]"; 564 return (char *) "^[yY]";
264 case NOEXPR: 565 case NOEXPR:
265 return "^[nN]"; 566 return (char *) "^[nN]";
266 default: 567 default:
267 return ""; 568 return (char *) "";
268 } 569 }
269} 570}
270 571