*** empty log message ***
[glibc.git] / locale / locale.c
blob20385f07d81d88c34b85936935692463ff8211e1
1 /* Copyright (C) 1995 Free Software Foundation, Inc.
3 The GNU C Library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public License as
5 published by the Free Software Foundation; either version 2 of the
6 License, or (at your option) any later version.
8 The GNU C Library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public
14 License along with the GNU C Library; see the file COPYING.LIB. If
15 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
16 Cambridge, MA 02139, USA. */
18 #include <dirent.h>
19 #include <getopt.h>
20 #include <langinfo.h>
21 #include <libintl.h>
22 #include <limits.h>
23 #include <locale.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
28 #include "localedef.h"
31 /* If set dump C code describing the current locale. */
32 static int do_dump;
34 /* If set print the name of the category. */
35 static int show_category_name;
37 /* If set print the name of the item. */
38 static int show_keyword_name;
40 /* Long options. */
41 static const struct option long_options[] =
43 { "all-locales", no_argument, NULL, 'a' },
44 { "category-name", no_argument, &show_category_name, 1 },
45 { "charmaps", no_argument, NULL, 'm' },
46 { "dump", no_argument, &do_dump, 1 },
47 { "help", no_argument, NULL, 'h' },
48 { "keyword-name", no_argument, &show_keyword_name, 1 },
49 { "version", no_argument, NULL, 'v' },
50 { NULL, 0, NULL, 0 }
54 /* We don't have these constants defined because we don't use them. Give
55 default values. */
56 #define CTYPE_MB_CUR_MIN 0
57 #define CTYPE_MB_CUR_MAX 0
58 #define CTYPE_HASH_SIZE 0
59 #define CTYPE_HASH_LAYERS 0
60 #define CTYPE_CLASS 0
61 #define CTYPE_TOUPPER_EB 0
62 #define CTYPE_TOLOWER_EB 0
63 #define CTYPE_TOUPPER_EL 0
64 #define CTYPE_TOLOWER_EL 0
67 /* We have all categories defined in `categories.def'. Now construct
68 the description and data structure used for all categories. */
69 #define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
70 static struct cat_item category##_desc[] = \
71 { \
72 NO_PAREN items \
75 #include "categories.def"
76 #undef DEFINE_CATEGORY
78 static struct category category[] =
80 #define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
81 { _NL_NUM_##category, name, NELEMS (category##_desc) - 1, \
82 category##_desc, NULL, NULL, NULL, out },
83 #include "categories.def"
84 #undef DEFINE_CATEGORY
86 #define NCATEGORIES NELEMS (category)
89 /* Prototypes for local functions. */
90 static void usage (int status) __attribute__ ((noreturn));
91 static void write_locales (void);
92 static void write_charmaps (void);
93 static void show_locale_vars (void);
94 static void show_info (const char *name);
95 static void dump_category (const char *name);
98 int
99 main (int argc, char *argv[])
101 int optchar;
102 int do_all = 0;
103 int do_help = 0;
104 int do_version = 0;
105 int do_charmaps = 0;
107 /* Set initial values for global varaibles. */
108 do_dump = 0;
109 show_category_name = 0;
110 show_keyword_name = 0;
112 /* Set locale. Do not set LC_ALL because the other categories must
113 not be affected (acccording to POSIX.2). */
114 setlocale (LC_CTYPE, "");
115 setlocale (LC_MESSAGES, "");
117 /* Initialize the message catalog. */
118 textdomain (PACKAGE);
120 while ((optchar = getopt_long (argc, argv, "achkmv", long_options, NULL))
121 != EOF)
122 switch (optchar)
124 case '\0':
125 break;
126 case 'a':
127 do_all = 1;
128 break;
129 case 'c':
130 show_category_name = 1;
131 break;
132 case 'h':
133 do_help = 1;
134 break;
135 case 'k':
136 show_keyword_name = 1;
137 break;
138 case 'm':
139 do_charmaps = 1;
140 break;
141 case 'v':
142 do_version = 1;
143 break;
144 default:
145 error (1, 0, gettext ("illegal option \"%s\""), optarg);
146 break;
149 /* Version information is requested. */
150 if (do_version)
152 fprintf (stderr, "GNU %s %s\n", PACKAGE, VERSION);
153 exit (EXIT_SUCCESS);
156 /* Help is requested. */
157 if (do_help)
158 usage (EXIT_SUCCESS);
160 /* Dump C code. */
161 if (do_dump)
163 printf ("\
164 /* Generated by GNU %s %s. */\n\
166 #include \"localeinfo.h\"\n", program_invocation_name, VERSION);
168 while (optind < argc)
169 dump_category (argv[optind++]);
171 exit (EXIT_SUCCESS);
174 /* `-a' requests the names of all available locales. */
175 if (do_all != 0)
177 write_locales ();
178 exit (EXIT_SUCCESS);
181 /* `m' requests the names of all available charmaps. The names can be
182 used for the -f argument to localedef(3). */
183 if (do_charmaps != 0)
185 write_charmaps ();
186 exit (EXIT_SUCCESS);
189 /* If no real argument is given we have to print the contents of the
190 current locale definition variables. These are LANG and the LC_*. */
191 if (optind == argc && show_keyword_name == 0 && show_category_name == 0)
193 show_locale_vars ();
194 exit (EXIT_SUCCESS);
197 /* Process all given names. */
198 while (optind < argc)
199 show_info (argv[optind++]);
201 exit (EXIT_SUCCESS);
205 /* Display usage information and exit. */
206 static void
207 usage(int status)
209 if (status != EXIT_SUCCESS)
210 fprintf (stderr, gettext ("Try `%s --help' for more information.\n"),
211 program_invocation_name);
212 else
213 printf(gettext ("\
214 Usage: %s [OPTION]... name\n\
215 Mandatory arguments to long options are mandatory for short options too.\n\
216 -h, --help display this help and exit\n\
217 -v, --version output version information and exit\n\
219 -a, --all-locales write names of available locales\n\
220 -m, --charmaps write names of available charmaps\n\
222 -c, --category-name write names of selected categories\n\
223 -k, --keyword-name write names of selected keywords\n\
225 --dump dump C code describing the current locale\n\
226 (this code can be used in the C library)\n\
227 "), program_invocation_name);
229 exit (status);
233 /* Write the names of all available locales to stdout. */
234 static void
235 write_locales (void)
237 DIR *dir;
238 struct dirent *dirent;
240 /* `POSIX' locale is always available (POSIX.2 4.34.3). */
241 puts ("POSIX");
243 dir = opendir (LOCALE_PATH);
244 if (dir == NULL)
246 error (1, errno, gettext ("cannot read locale directory `%s'"),
247 LOCALE_PATH);
248 return;
251 /* Now we can look for all files in the directory. */
252 while ((dirent = readdir (dir)) != NULL)
253 if (strcmp (dirent->d_name, ".") != 0
254 && strcmp (dirent->d_name, "..") != 0)
255 puts (dirent->d_name);
257 closedir (dir);
261 /* Write the names of all available character maps to stdout. */
262 static void
263 write_charmaps (void)
265 DIR *dir;
266 struct dirent *dirent;
268 dir = opendir (CHARMAP_PATH);
269 if (dir == NULL)
271 error (1, errno, gettext ("cannot read character map directory `%s'"),
272 CHARMAP_PATH);
273 return;
276 /* Now we can look for all files in the directory. */
277 while ((dirent = readdir (dir)) != NULL)
278 if (strcmp (dirent->d_name, ".") != 0
279 && strcmp (dirent->d_name, "..") != 0)
280 puts (dirent->d_name);
282 closedir (dir);
286 /* We have to show the contents of the environments determining the
287 locale. */
288 static void
289 show_locale_vars (void)
291 size_t cat_no;
292 const char *lcall = getenv ("LC_ALL");
293 const char *lang = getenv ("LANG") ? : "POSIX";
295 void get_source (const char *name)
297 char *val = getenv (name);
299 if (lcall != NULL || val == NULL)
300 printf ("%s=\"%s\"\n", name, lcall ? : lang);
301 else
302 printf ("%s=%s\n", name, val);
305 /* LANG has to be the first value. */
306 printf ("LANG=%s\n", lang);
308 /* Now all categories in an unspecified order. */
309 for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
310 get_source (category[cat_no].name);
312 /* The last is the LC_ALL value. */
313 printf ("LC_ALL=%s\n", lcall ? : "");
317 /* Show the information request for NAME. */
318 static void
319 show_info (const char *name)
321 size_t cat_no;
323 void print_item (struct cat_item *item)
325 if (show_keyword_name != 0)
326 printf ("%s=", item->name);
328 switch (item->value_type)
330 case string:
331 printf ("%s%s%s", show_keyword_name ? "\"" : "",
332 nl_langinfo (item->item_id) ? : "",
333 show_keyword_name ? "\"" : "");
334 break;
335 case stringarray:
337 int cnt;
338 const char *val;
340 if (show_keyword_name)
341 putchar ('"');
343 for (cnt = 0; cnt < item->max - 1; ++cnt)
345 val = nl_langinfo (item->item_id + cnt);
346 printf ("%s;", val ? : "");
349 val = nl_langinfo (item->item_id + cnt);
350 printf ("%s", val ? : "");
352 if (show_keyword_name)
353 putchar ('"');
355 break;
356 case byte:
358 const char *val = nl_langinfo (item->item_id);
360 if (val != NULL)
361 printf ("%d", *val == CHAR_MAX ? -1 : *val);
363 break;
364 case bytearray:
366 const char *val = nl_langinfo (item->item_id);
367 int cnt = val ? strlen (val) : 0;
369 while (cnt > 1)
371 printf ("%d;", *val == CHAR_MAX ? -1 : *val);
372 --cnt;
373 ++val;
376 printf ("%d", cnt == 0 || *val == CHAR_MAX ? -1 : *val);
378 break;
379 default:
381 putchar ('\n');
384 for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
386 size_t item_no;
388 if (category[cat_no].outfct != NULL)
389 /* Categories which need special handling of the output are
390 not written. This is especially for LC_CTYPE and LC_COLLATE.
391 It does not make sense to have this large number of cryptic
392 characters displayed. */
393 continue;
395 if (strcmp (name, category[cat_no].name) == 0)
396 /* Print the whole category. */
398 if (show_category_name != 0)
399 puts (category[cat_no].name);
401 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
402 print_item (&category[cat_no].item_desc[item_no]);
404 return;
407 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
408 if (strcmp (name, category[cat_no].item_desc[item_no].name) == 0)
410 if (show_category_name != 0)
411 puts (category[cat_no].name);
413 print_item (&category[cat_no].item_desc[item_no]);
414 return;
420 static void
421 dump_category (const char *name)
423 char *locname;
424 size_t cat_no, item_no, nstrings;
426 for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
427 if (strcmp (name, category[cat_no].name) == 0)
428 break;
430 if (cat_no >= NCATEGORIES)
431 return;
433 /* The NAME specifies a correct locale category. */
434 if (category[cat_no].outfct != NULL)
436 category[cat_no].outfct ();
437 return;
440 locname = (getenv ("LC_ALL") ?: getenv (name) ?:
441 getenv ("LANG") ?: (char *) "POSIX");
443 /* Determine the number of strings in advance. */
444 nstrings = 0;
445 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
446 switch (category[cat_no].item_desc[item_no].value_type)
448 case string:
449 case byte:
450 case bytearray:
451 ++nstrings;
452 break;
453 case stringarray:
454 nstrings += category[cat_no].item_desc[item_no].max;
455 default:
458 printf ("\nconst struct locale_data _nl_%s_%s =\n{\n"
459 " NULL, 0, /* no file mapped */\n %Zu,\n {\n",
460 locname, name, nstrings);
462 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
463 switch (category[cat_no].item_desc[item_no].value_type)
465 case string:
467 const char *val = nl_langinfo (
468 category[cat_no].item_desc[item_no].item_id);
470 if (val != NULL)
471 printf (" \"%s\",\n", val);
472 else
473 puts (" NULL,");
475 break;
476 case stringarray:
478 const char *val;
479 int cnt;
481 for (cnt = 0; cnt < category[cat_no].item_desc[item_no].max; ++cnt)
483 val = nl_langinfo (
484 category[cat_no].item_desc[item_no].item_id + cnt);
486 if (val != NULL)
487 printf (" \"%s\",\n", val);
488 else
489 puts (" NULL,");
492 break;
493 case byte:
495 const char *val = nl_langinfo (
496 category[cat_no].item_desc[item_no].item_id);
498 if (val != NULL)
499 printf (" \"\\%o\",\n",
500 *(unsigned char *) val ? : UCHAR_MAX);
501 else
502 puts (" NULL,");
504 break;
505 case bytearray:
507 const char *bytes = nl_langinfo (
508 category[cat_no].item_desc[item_no].item_id);
510 if (bytes != NULL)
512 fputs (" \"", stdout);
513 if (*bytes != '\0')
515 printf ("\\%o", *(unsigned char *) bytes++);
516 while (*bytes != '\0');
517 else
518 printf ("\\%o", UCHAR_MAX);
520 puts ("\",");
522 else
523 puts (" NULL,");
525 break;
526 default:
527 break;
530 puts (" }\n};");
534 * Local Variables:
535 * mode:c
536 * c-basic-offset:2
537 * End: