Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
LOCALE_NAME_FMAT.cpp
Go to the documentation of this file.
1// determining combined locale name format
2
3
25// If strict_ansi_errors is present, the definition of __PURE_CNAME
26// dictates inclusion of locale_cname_impl & locale_ansi_impl which
27// do not define LC_MESSAGES locale category
28#if defined (__PURE_CNAME)
29# undef __PURE_CNAME
30#endif // __PURE_CNAME
31
32#include <locale.h>
33#include <stdio.h>
34#include <string.h>
35
36// prevent IBM xlC 5.0 errors caused by using /usr/include/string.h
37// which #defines these (and other) names to undeclared symbols
38#undef strcpy
39#undef strcmp
40#undef strlen
41#undef strcat
42
43
44#include "locale_names.h" // for test_locale_names
45
46
47// the longest combined locale name handled by the test (GNU glibc
48// can generate some awfully long names since in addition to the
49// name of the locale name for each category it includes the name
50// of the category itself, e.g., "LC_CTYPE=en;LC_NUMERIC=es;...")
51#define MAX_LOCALE_NAME_LEN 1024
52
53
54#if 0 // disabled
55
56// enable for debugging to emulate a system with no locales installed
57
58extern "C" char* setlocale (int, const char *name)
59{
60 static char cname[] = "C";
61
62 if (0 == name)
63 return cname;
64
65 if ('C' != name [0] || '\0' != name [1])
66 return 0;
67
68 return cname;
69}
70
71#endif // 0/1
72
73
74// define own version of the libc functions to prevent problems
75// caused by them being not declared (sometimes due to the fact
76// that they must be overloaded in C++ which may not be done in
77// headers that are #included in the test)
78
79char* rw_strchr (const char *s, char c)
80{
81 for (; *s && *s != c; ++s);
82
83 return *s == c ? (char*)s : 0;
84}
85
86
87char* rw_strpbrk (const char *s, const char *seps)
88{
89 for (; *seps; ++seps) {
90 char *where = rw_strchr (s, *seps);
91 if (where)
92 return where;
93 }
94
95 return 0;
96}
97
98
99char* rw_strstr (const char *str, const char *s)
100{
101 for (; *str; ++str) {
102
103 str = rw_strchr (str, *s);
104
105 if (!str)
106 return 0;
107
108 const char *s1 = str;
109 const char *s2 = s;
110
111 for (; *s1 && *s2 && *s1 == *s2; ++s1, ++s2);
112
113 if (!*s2)
114 return (char*)str;
115 }
116
117 return 0;
118}
119
120
121extern "C" int putenv (char*);
122
123
124extern const char* const test_locale_names[];
125extern const unsigned nlocales;
126
127int print_lc_constants ();
128int print_categories (const char*, int, int&, int&, int, char&, char&);
129int print_locale_name_format (int, int, int, int, int, char, char);
130
131
132#if !defined (_WIN32) || defined (__CYGWIN__)
133char cat_seps[] = " \n\t/\\:;#%";
134#else
135char cat_seps[] = "\n\t/\\:;#%";
136#endif
137
138
139int main ()
140{
141 // compute and print the values of the LC_XXX constants
142 // and their relationship to the std::locale::category
143 // constants
144 if (print_lc_constants ())
145 return 0;
146
147 // try to determine the format of combined locale names
148 int setlocale_environ = 0;
149 int loc_name_use_cat = 0;
150 int loc_name_prepend_sep = 0;
151 int loc_name_condense = 0;
152 char loc_name_cat_sep = '\0';
153 char loc_name_cat_eq = '\0';
154
155 char namebuf [MAX_LOCALE_NAME_LEN];
156 namebuf [0] = '\0';
157
158 // determine whether setlocale(LC_ALL, name) returns
159 // a string containing the equivalent of `name' for
160 // each LC_XXX category or whether it collapses all
161 // equivalent names into just a single locale name
162 const char *locname = setlocale (LC_ALL, "C");
163
164 char *sep = locname ? rw_strpbrk (locname, cat_seps) : 0;
165 if (sep) {
166 if ('C' == sep [-1] && 1 == sep - locname)
167 loc_name_cat_sep = *sep;
168 else {
169 loc_name_condense = 1;
170 *rw_strchr (cat_seps, *sep) = '\n';
171 }
172 }
173 else {
174 loc_name_condense = 1;
175 }
176
177 // find the first valid locale name other than "C" or
178 // the default locale returned by locale (LC_ALL, "")
179 if ((locname = setlocale (LC_ALL, "")))
180 strcpy (namebuf, locname);
181
182 unsigned i;
183
184 for (i = 0; i != nlocales; ++i) {
185
186 locname = test_locale_names [i];
187
188#if defined (_MSC_VER) && _MSC_VER <= 1200
189
190 // work around an MSVC libc bug (PR #27990)
191 if (rw_strpbrk (locname, ".-"))
192 continue;
193
194#endif // MSVC <= 6.0
195
196 locname = setlocale (LC_ALL, locname);
197 if (locname && strcmp (namebuf, locname))
198 break;
199 }
200
201 if (locname) {
202 locname = strcpy (namebuf, locname);
203
204 sep = rw_strpbrk (locname, cat_seps);
205 if (sep)
206 *sep = '\0';
207
208 // determine if the environment has any effect on setlocale()
209 {
210 char def_locale [MAX_LOCALE_NAME_LEN];
211 def_locale [0] = '\0';
212
213 const char *tmpname = setlocale (LC_ALL, "");
214 if (tmpname)
215 strcpy (def_locale, tmpname);
216
218 strcpy (buf, "LC_COLLATE=");
219 strcat (buf, locname);
220 putenv (buf);
221
222 tmpname = setlocale (LC_ALL, "");
223 setlocale_environ = tmpname ? strcmp (def_locale, tmpname) : 1;
224 }
225 }
226
227 print_categories (locname,
228 setlocale_environ,
229 loc_name_use_cat,
230 loc_name_prepend_sep,
231 loc_name_condense,
232 loc_name_cat_sep,
233 loc_name_cat_eq);
234
235 return print_locale_name_format (0 == locname,
236 setlocale_environ,
237 loc_name_use_cat,
238 loc_name_prepend_sep,
239 loc_name_condense,
240 loc_name_cat_sep,
241 loc_name_cat_eq);
242}
243
244
246static struct LC_vars
247{
248 int ord;
249 int cat;
250 char name [64];
251 const char *lower;
252} lc_vars [] = {
253 { -1, LC_COLLATE, "LC_COLLATE=C", "collate" },
254 { -1, LC_CTYPE, "LC_CTYPE=C", "ctype" },
255 { -1, LC_MONETARY, "LC_MONETARY=C", "monetary" },
256 { -1, LC_NUMERIC, "LC_NUMERIC=C", "numeric" },
257 { -1, LC_TIME, "LC_TIME=C", "time" },
258
259#if defined (LC_MESSAGES)
260 { -1, LC_MESSAGES, "LC_MESSAGES=C", "messages" },
261#endif
262
263#if defined (LC_NAME)
264 { -1, LC_NAME, "LC_NAME=C", "name" },
265#endif
266
267#if defined (LC_PAPER)
268 { -1, LC_PAPER, "LC_PAPER=C", "paper" },
269#endif
270
271#if defined (LC_IDENTIFICATION)
272 { -1, LC_IDENTIFICATION, "LC_IDENTIFICATION=C", "ident" },
273#endif
274
275#if defined (LC_ADDRESS)
276 { -1, LC_ADDRESS, "LC_ADDRESS=C", "address" },
277#endif
278
279#if defined (LC_TELEPHONE)
280 { -1, LC_TELEPHONE, "LC_TELEPHONE=C", "telephone" },
281#endif
282
283#if defined (LC_MEASUREMENT)
284 { -1, LC_MEASUREMENT, "LC_MEASUREMENT=C", "measurement" },
285#endif
286
287 { -1, LC_ALL, "LC_ALL", 0 },
288 { -1, 0, "", 0 }
289};
290
291
292// the known order of categories in combined locale names
293const int lc_cat_order[] = {
294
295#if defined (_AIX)
297 -1, -1, -1, -1, -1, -1
298#elif defined (__FreeBSD__) || defined (__NetBSD__)
300 -1, -1, -1, -1, -1, -1
301#elif defined (__hpux)
303 -1, -1, -1, -1, -1, -1
304#elif defined (__GLIBC__)
306
307# if defined (LC_PAPER)
308 LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
309 LC_IDENTIFICATION
310# else
311 -1, -1, -1, -1, -1, -1
312# endif
313#elif defined (__osf__)
315 -1, -1, -1, -1, -1, -1
316#elif defined (__sgi)
318 -1, -1, -1, -1, -1, -1
319#elif (defined (__sun__) || defined (__sun) || defined (sun)) \
320 && defined (__svr4__)
322 -1, -1, -1, -1, -1, -1
323#elif defined (_WIN32)
325 -1, -1, -1, -1, -1, -1,
326#elif defined (__CYGWIN__)
327 // this is just a wild guess since localization support
328 // on CygWin seems to be very limited
330 -1, -1, -1, -1, -1, -1,
331#else
332 -1, -1, -1, -1, -1, -1,
333 -1, -1, -1, -1, -1, -1
334#endif
335
336};
337
338
341{
342 // determine the values of LC_XXX constants
343
344 unsigned lc_max_inx = 0;
345 unsigned lc_min_inx = 0;
346
347 char *eq;
348
349 for (unsigned i = 0; *lc_vars [i].name; ++i) {
350 eq = rw_strchr (lc_vars [i].name, '=');
351 if (eq)
352 *eq = '\0';
353
354 printf ("#define _RWSTD_%-20s %2d\n",
355 lc_vars [i].name, lc_vars [i].cat);
356
357 if (lc_vars [i].cat > lc_vars [lc_max_inx].cat)
358 lc_max_inx = i;
359
360 if (lc_vars [i].cat < lc_vars [lc_min_inx].cat)
361 lc_min_inx = i;
362
363 if (eq)
364 *eq = '=';
365 }
366
367 eq = rw_strchr (lc_vars [lc_max_inx].name, '=');
368 if (eq)
369 *eq = '\0';
370
371 printf ("#define %-27s _RWSTD_%s\n",
372 "_RWSTD_LC_MAX", lc_vars [lc_max_inx].name);
373
374 if (eq)
375 *eq = '=';
376
377 eq = rw_strchr (lc_vars [lc_min_inx].name, '=');
378 if (eq)
379 *eq = '\0';
380
381 printf ("#define %-27s _RWSTD_%s\n",
382 "_RWSTD_LC_MIN", lc_vars [lc_min_inx].name);
383
384 if (eq)
385 *eq = '=';
386
387 return 0;
388}
389
390
392int print_categories (const char *locname,
393 int setlocale_environ,
394 int &loc_name_use_cat,
395 int &loc_name_prepend_sep,
396 int loc_name_condense,
397 char &loc_name_cat_sep,
398 char &loc_name_cat_eq)
399{
400 // set or overwrite LC_ALL to prevent it from
401 // overriding the settings below, and also reset
402 // the global C locale to "C"
403 char lc_all[] = "LC_ALL=";
404 putenv (lc_all);
405 setlocale (LC_ALL, "C");
406
407 unsigned i;
408
409 // set up the default environment (i.e., LC_COLLATE=C; LC_CTYPE=C; etc.)
410 for (i = 0; lc_vars [i].cat != LC_ALL; ++i)
411 putenv (lc_vars [i].name);
412
413 for (i = 0; locname && lc_vars [i].cat != LC_ALL; ++i) {
414 if (i) {
415 if (setlocale_environ) {
416 // replace previous LC_XXX environment variable
417 strcpy (rw_strchr (lc_vars [i - 1].name, '=') + 1, "C");
418 putenv (lc_vars [i - 1].name);
419 }
420 else {
421 setlocale (lc_vars [i - 1].cat, "C");
422 }
423 }
424
425 strcpy (rw_strchr (lc_vars [i].name, '=') + 1, locname);
426
427 // add/modify variable to/in the environemnt (may or may not
428 // be necessary depending on whether putenv() adds the actual
429 // string or a copy of it
430 putenv (lc_vars [i].name);
431
432 // set the combined locale
433 char *combined;
434
435 if (setlocale_environ) {
436 // create combined name from the environment
437 combined = setlocale (LC_ALL, "");
438 }
439 else {
440 // create combined name programmatically
441 // by setting just one category
442 setlocale (lc_vars [i].cat, locname);
443 combined = setlocale (LC_ALL, 0);
444 }
445
446 // construct LC_XXX name
447 char *eq = rw_strchr (lc_vars [i].name, '=');
448 *eq = '\0';
449
450 // look for LC_XXX string in locale name
451 const char *where =
452 combined ? rw_strstr (combined, lc_vars [i].name) : (char*)0;
453
454 if (where) {
455 // found the name of the category constant
456 // in the name of the combined locale
457 loc_name_use_cat = 1;
458
459 // look for a separator between LC_XXX
460 // and the locale name (typically '=')
461 if (!loc_name_cat_eq)
462 loc_name_cat_eq = where [strlen (lc_vars [i].name)];
463
464 int j = -1;
465
466 char* sep = rw_strpbrk (combined, cat_seps);
467 char* first = rw_strstr (combined, locname);
468
469 for (const char *s = combined; *s && s != first; ++j)
470 s = rw_strchr (s, loc_name_cat_eq) + 1;
471
472 lc_vars [i].ord = j;
473
474 // look for a separator between LC_XXX=name pairs
475 // (typically ';')
476 if (where != combined && !loc_name_cat_sep) {
477 loc_name_cat_sep = where [-1];
478 }
479 }
480 else {
481 // look for a separator between locale categories
482 char* sep = combined ? rw_strpbrk (combined, cat_seps) : (char*)0;
483 if (sep == combined)
484 loc_name_prepend_sep = 1;
485
486 if (sep)
487 loc_name_cat_sep = *sep;
488
489 int j = -loc_name_prepend_sep;
490
491 if (sep) {
492 char *first = rw_strstr (combined, locname);
493 for (const char *s = combined; *s && s != first; ++j) {
494 s = rw_strchr (s, *sep);
495 if (s)
496 s += 1;
497 else
498 break;
499 }
500
501 lc_vars [i].ord = j;
502 }
503 else {
504 // combined locale name is the same as the name
505 // of one of the combining locales (e.g., Windows)
506 lc_vars [i].ord = i;
507 }
508 }
509
510 // replace the original '=' in the LC_XXX=name environment variable
511 *eq = '=';
512
513 if (combined && *combined == loc_name_cat_sep)
514 loc_name_prepend_sep = 1;
515 }
516
517 for (i = 0; lc_vars [i].cat != LC_ALL; ++i) {
518
519 char* eq = rw_strchr (lc_vars [i].name, '=');
520 if (eq)
521 *eq = '\0';
522
523 const char *comment = 0;
524 int inx = -1;
525
526 for (int j = 0; *lc_vars [j].name; ++j) {
527 if (lc_vars [i].ord == j) {
528 comment = 0;
529 inx = j;
530 break;
531 }
532
533 if (lc_vars [i].cat == lc_cat_order [j]) {
534 comment = " // assumed";
535 inx = j;
536 }
537 }
538
539 if (-1 < inx)
540 printf ("#define _RWSTD_CAT_%d(pfx) "
541 "{ %d, \"%s\", pfx::_C_%s }%s\n",
542 inx, lc_vars [i].cat, lc_vars [i].name,
543 lc_vars [i].lower, comment ? comment : "");
544 }
545
546 return 0;
547}
548
549
552 int setlocale_environ,
553 int loc_name_use_cat,
554 int loc_name_prepend_sep,
555 int loc_name_condense,
556 char loc_name_cat_sep,
557 char loc_name_cat_eq)
558{
559 const char* os_name = 0;
560
561 if (guess) {
562
563#if defined (_AIX)
564
565 setlocale_environ = 1;
566 loc_name_use_cat = 0;
567 loc_name_prepend_sep = 0;
568 loc_name_condense = 0;
569 loc_name_cat_sep = ' ';
570 loc_name_cat_eq = '\0';
571 os_name = "AIX";
572
573#elif defined (__FreeBSD__)
574
575 setlocale_environ = 1;
576 loc_name_use_cat = 0;
577 loc_name_prepend_sep = 0;
578 loc_name_condense = 1;
579 loc_name_cat_sep = '/';
580 loc_name_cat_eq = '\0';
581 os_name = "FreeBSD";
582
583#elif defined (__hpux)
584
585 setlocale_environ = 1;
586 loc_name_use_cat = 0;
587 loc_name_prepend_sep = 0;
588 loc_name_condense = 0;
589 loc_name_cat_sep = ' ';
590 loc_name_cat_eq = '\0';
591 os_name = "HP-UX";
592
593#elif defined (__GLIBC__)
594
595 setlocale_environ = 1;
596 loc_name_use_cat = 1;
597 loc_name_prepend_sep = 0;
598 loc_name_condense = 0;
599 loc_name_cat_sep = ';';
600 loc_name_cat_eq = '=';
601 os_name = "GNU libc";
602
603#elif defined (__NetBSD__)
604
605 setlocale_environ = 0;
606 loc_name_use_cat = 0;
607 loc_name_prepend_sep = 0;
608 loc_name_condense = 1;
609 loc_name_cat_sep = '\0';
610 loc_name_cat_eq = '\0';
611 os_name = "NetBSD";
612
613#elif defined (__osf__)
614
615 setlocale_environ = 1;
616 loc_name_use_cat = 0;
617 loc_name_prepend_sep = 0;
618 loc_name_condense = 0;
619 loc_name_cat_sep = ' ';
620 loc_name_cat_eq = '\0';
621 os_name = "Tru64 UNIX";
622
623#elif defined (__sgi)
624
625 setlocale_environ = 1;
626 loc_name_use_cat = 0;
627 loc_name_prepend_sep = 1;
628 loc_name_condense = 1;
629 loc_name_cat_sep = '/';
630 loc_name_cat_eq = '\0';
631 os_name = "SGI IRIX";
632
633#elif (defined (__sun__) || defined (__sun) || defined (sun)) \
634 && defined (__svr4__)
635
636 setlocale_environ = 1;
637 loc_name_use_cat = 0;
638 loc_name_prepend_sep = 1;
639 loc_name_condense = 1;
640 loc_name_cat_sep = '/';
641 loc_name_cat_eq = '\0';
642 os_name = "SunOS";
643
644#elif defined (_WIN32)
645
646 setlocale_environ = 0;
647 loc_name_use_cat = 1;
648 loc_name_prepend_sep = 0;
649 loc_name_condense = 1;
650 loc_name_cat_sep = ';';
651 loc_name_cat_eq = '=';
652 os_name = "Windows";
653
654#elif defined (__CYGWIN__)
655
656 // guessing this might be the same as Windows
657 setlocale_environ = 0;
658 loc_name_use_cat = 1;
659 loc_name_prepend_sep = 0;
660 loc_name_condense = 1;
661 loc_name_cat_sep = ';';
662 loc_name_cat_eq = '=';
663 // change the OS name to CygWin as soon as CygWin
664 // has implemented locale support
665 os_name = "Windows";
666
667#else
668
669 printf ("// no locales found, unknown system\n");
670 return -1; // unknown OS, fail
671
672#endif
673
674 }
675
676 if (os_name)
677 printf ("// no locales found, using %s format\n", os_name);
678
679 if (setlocale_environ)
680 printf ("// #define _RWSTD_NO_SETLOCALE_ENVIRONMENT\n");
681 else
682 printf ("#define _RWSTD_NO_SETLOCALE_ENVIRONMENT\n");
683
684 if (loc_name_use_cat)
685 printf ("// #define _RWSTD_NO_CAT_NAMES\n");
686 else
687 printf ("#define _RWSTD_NO_CAT_NAMES\n");
688
689 if (loc_name_cat_sep)
690 printf ("#define _RWSTD_CAT_SEP \"%c\"\n", loc_name_cat_sep);
691 else
692 printf ("#define _RWSTD_NO_CAT_SEP\n");
693
694 if (loc_name_cat_eq)
695 printf ("#define _RWSTD_CAT_EQ \"%c\"\n", loc_name_cat_eq);
696 else
697 printf ("#define _RWSTD_NO_CAT_EQ\n");
698
699 if (loc_name_prepend_sep)
700 printf ("// #define _RWSTD_NO_INITIAL_CAT_SEP\n");
701 else
702 printf ("#define _RWSTD_NO_INITIAL_CAT_SEP\n");
703
704 if (loc_name_condense)
705 printf ("// #define _RWSTD_NO_CONDENSED_NAME\n");
706 else
707 printf ("#define _RWSTD_NO_CONDENSED_NAME\n");
708
709 return 0;
710}
const char lower[]
#define i
Definition 17.names.cpp:126
#define s1
Definition 17.names.cpp:242
#define s2
Definition 17.names.cpp:268
#define buf
Definition 17.names.cpp:452
#define j
Definition 17.names.cpp:127
#define c
Definition 17.names.cpp:111
#define s
#define inx
Definition 17.names.cpp:484
IMPORT_C SInt32 printf(const Char *,...)
char * rw_strchr(const char *s, char c)
const char *const test_locale_names[]
char * rw_strpbrk(const char *s, const char *seps)
int print_categories(const char *, int, int &, int &, int, char &, char &)
#define MAX_LOCALE_NAME_LEN
int putenv(char *)
const int lc_cat_order[]
int print_lc_constants()
char * rw_strstr(const char *str, const char *s)
char cat_seps[]
int print_locale_name_format(int, int, int, int, int, char, char)
const unsigned nlocales
int main()
#define LC_CTYPE
#define LC_NUMERIC
#define LC_MONETARY
#define LC_ALL
#define LC_TIME
#define LC_COLLATE
const char * name
Definition codecvt1.cpp:72
const char * str
Definition exec.cpp:170
#define LC_MESSAGES
Definition time_put.cpp:60