(STRTOF): Fix handling of numbers with lots of leading zeroes.
[glibc.git] / locale / locfile-parse.c
blobdaf56bcd455317ff9b81728d90897bade083a024
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 <errno.h>
19 #include <assert.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <langinfo.h>
23 #include <libintl.h>
24 #include <limits.h>
25 #include <obstack.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/stat.h>
31 #include <sys/uio.h>
33 #include "localedef.h"
34 #include "localeinfo.h"
35 #include "token.h"
37 /* We don't have these constants defined because we don't use them. Give
38 default values. */
39 #define CTYPE_MB_CUR_MIN 0
40 #define CTYPE_MB_CUR_MAX 0
41 #define CTYPE_HASH_SIZE 0
42 #define CTYPE_HASH_LAYERS 0
43 #define CTYPE_CLASS 0
44 #define CTYPE_TOUPPER_EB 0
45 #define CTYPE_TOLOWER_EB 0
46 #define CTYPE_TOUPPER_EL 0
47 #define CTYPE_TOLOWER_EL 0
50 /* We have all categories defined in `categories.def'. Now construct
51 the description and data structure used for all categories. */
52 #define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
53 struct cat_item category##_desc[] = \
54 { \
55 NO_PAREN items \
56 }; \
58 char *category##_values[NELEMS (category##_desc) - 1] = { NULL, };
59 #include "categories.def"
60 #undef DEFINE_CATEGORY
62 struct category category[] =
64 #define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
65 [category] = { _NL_NUM_##category, name, NELEMS (category##_desc) - 1, \
66 category##_desc, category##_values, in, check, out },
67 #include "categories.def"
68 #undef DEFINE_CATEGORY
70 #define NCATEGORIES NELEMS (category)
73 #define SYNTAX_ERROR \
74 error (0, 0, gettext ("%s:%Zd: syntax error in locale definition file"), \
75 locfile_data.filename, locfile_data.line_no)
78 /* Prototypes for local functions. */
79 static int get_byte (char *byte_ptr);
80 static char *is_locale_name (int cat_no, const char *str, int len);
83 /* Read a locale definition file FILE. The format is defined in
84 POSIX.2 2.5.3. */
85 void
86 locfile_read (const char *fname)
88 /* Pointer to text of last token. */
89 char *ptr;
90 /* Length of last token (or if NUMBER the value itself). */
91 int len;
92 /* The last returned token. */
93 int token;
94 /* For error correction we remember whether the last token was correct. */
95 int correct_token = 1;
97 /* Open the desired input file on stdin. */
98 locfile_open (fname);
100 while ((token = locfile_lex (&ptr, &len)) != 0)
102 int cat_no;
104 for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
105 if (token == category[cat_no].cat_id)
106 break;
108 if (cat_no >= NCATEGORIES)
109 /* A syntax error occured. No valid category defintion starts. */
111 if (correct_token != 0)
112 error (0, 0, gettext ("%s:%Zd: locale category start expected"),
113 locfile_data.filename, locfile_data.line_no);
115 /* To prevent following errors mark as error case. */
116 correct_token = 0;
118 /* Synchronization point is the beginning of a new category.
119 Overread all line upto this silently. */
120 ignore_to_eol (0, 0);
121 continue;
124 /* Rest of the line should be empty. */
125 ignore_to_eol (0, 1);
127 /* Perhaps these category is already specified. We simply give a
128 warning and overwrite the values. */
129 if (category[cat_no].filled != 0)
130 error (0, 0, gettext ("%s:%Zd: multiple definition of locale "
131 "category %s"), locfile_data.filename,
132 locfile_data.line_no, category[cat_no].name);
134 /* We read the first token because this could be the copy statement. */
135 token = xlocfile_lex (&ptr, &len);
137 if (token == TOK_COPY)
138 /* Copying the definitions from an existing locale is requested. */
140 char *str;
142 /* Get the name of the locale to copy from. */
143 token = xlocfile_lex (&ptr, &len);
144 if (token != TOK_IDENT && token != TOK_STRING)
145 /* No name, then mark error and ignore everything upto next
146 start of an category section. */
148 /* To prevent following errors mark as error case. */
149 correct_token = 0;
151 /* Synchronization point is the beginning of a new category.
152 Overread all line upto this silently. */
153 ignore_to_eol (0, 0);
155 else if ((str = is_locale_name (cat_no, ptr, len)) != NULL)
156 /* Yes the name really names an existing locale file. We are
157 returned the complete file name. Store it so that we can
158 copy it in the output phase. */
160 category[cat_no].copy_locale = str;
161 category[cat_no].filled = 1;
163 ignore_to_eol (0, 1);
165 else
166 /* No, the name does not address a valid locale file. Mark
167 error case and ignore rest of category. */
169 char tmp[len + 1];
170 memcpy (tmp, ptr, len);
171 tmp[len] = '\0';
172 error (0, 0, gettext ("%s:%Zd: invalid locale `%s' in copy "
173 "statement"), locfile_data.filename,
174 locfile_data.line_no, tmp);
175 correct_token = 0;
176 ignore_to_eol (0, 0);
179 /* This should END as the next token. */
180 token = xlocfile_lex (&ptr, &len);
182 if (token == TOK_END)
183 /* This is the end of the category. */
185 token = xlocfile_lex (&ptr, &len);
187 if (token != category[cat_no].cat_id)
188 /* Wrong category name after END. */
190 error (0, 0, gettext ("%s:%Zd: category `%s' does not "
191 "end with `END %s'"),
192 locfile_data.filename, locfile_data.line_no,
193 category[cat_no].name, category[cat_no].name);
194 ignore_to_eol (0, 0);
196 else
197 ignore_to_eol (0, 1);
199 correct_token = 1;
201 else
202 /* No END following copy. Give error while not in error case. */
204 if (correct_token != 0)
205 error (0, 0, gettext ("%s:%Zd: `copy' must be sole rule"),
206 locfile_data.filename, locfile_data.line_no);
207 correct_token = 0;
208 ignore_to_eol (0, 0);
211 continue;
214 /* Now it's time to mark as mentioned in the locale file. */
215 category[cat_no].filled = 1;
217 if (category[cat_no].infct != NULL)
218 /* The category needs a special input handling. */
220 category[cat_no].infct(token);
221 continue;
224 /* Now process the given items. */
225 while (1)
227 int item_no;
229 if (token == TOK_END)
230 /* This is the end of the category. */
232 token = xlocfile_lex (&ptr, &len);
234 if (token != category[cat_no].cat_id)
236 error (0, 0, gettext ("%s:%Zd: category `%s' does not end "
237 "with `END %s'"),
238 locfile_data.filename, locfile_data.line_no,
239 category[cat_no].name, category[cat_no].name);
240 ignore_to_eol (0, 0);
242 else
243 ignore_to_eol (0, 1);
245 /* Start next category. */
246 break;
249 /* All other lines should describe valid items of the category. */
250 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
251 if (category[cat_no].item_desc[item_no].item_id == token)
252 break;
254 if (item_no >= category[cat_no].number)
255 /* This is not a valid item of the category. */
257 SYNTAX_ERROR;
258 ignore_to_eol (0, 0);
260 token = xlocfile_lex (&ptr, &len);
262 /* And process next item. */
263 continue;
266 /* Test whether already a value is defined. */
267 if (category[cat_no].item_value[item_no] != NULL)
268 error (0, 0, gettext ("%s:%Zd: category item `%s' already "
269 "defined"),
270 locfile_data.filename, locfile_data.line_no,
271 category[cat_no].item_desc[item_no].name);
273 switch (category[cat_no].item_desc[item_no].value_type)
275 case string:
276 /* Get next token. This is the argument to the item. */
277 token = xlocfile_lex (&ptr, &len);
279 if (token != TOK_STRING)
280 SYNTAX_ERROR;
281 else
282 category[cat_no].item_value[item_no] = strdup (ptr);
283 ignore_to_eol (0, ptr != NULL);
284 break;
285 case stringarray:
286 /* This is a difficult case. The number of strings in
287 the array may vary. But for now its only necessary
288 with ALT_DIGITS from LC_TIME. This item is the last
289 so be can solve it by storing the number of string in
290 the first place and the string indeces following
291 that. */
293 int cnt;
294 char **buffer;
295 if (category[cat_no].item_value[item_no] != NULL)
296 buffer = (char **) category[cat_no].item_value[item_no];
297 else
298 buffer = (char **) xmalloc (
299 sizeof (char *) * category[cat_no].item_desc[item_no].max);
301 category[cat_no].item_value[item_no] = (char *) buffer;
303 /* As explained we may need a place to store the real number
304 of strings. */
305 if (category[cat_no].item_desc[item_no].min
306 != category[cat_no].item_desc[item_no].max)
307 ++buffer;
309 cnt = 0;
312 token = xlocfile_lex (&ptr, &len);
313 if (token != TOK_STRING)
315 SYNTAX_ERROR;
316 break;
319 if (cnt >= category[cat_no].item_desc[item_no].max)
321 error (0, 0, gettext ("%s:%Zd: too many elements "
322 "for item `%s`"),
323 locfile_data.filename, locfile_data.line_no,
324 category[cat_no].item_desc[item_no].name);
325 break;
328 buffer[cnt++] = strdup (ptr);
330 token = locfile_lex (&ptr, &len);
332 while (token == TOK_CHAR && len == ';');
334 ignore_to_eol (token, ptr != NULL);
336 if (cnt < category[cat_no].item_desc[item_no].min)
337 error (0, 0, gettext ("%s:%Zd: too few elements for item "
338 "`%s'"),
339 locfile_data.filename, locfile_data.line_no,
340 category[cat_no].item_desc[item_no].name);
342 if (category[cat_no].item_desc[item_no].min
343 != category[cat_no].item_desc[item_no].max)
344 *(int *) category[cat_no].item_value[item_no] = cnt;
346 break;
347 case byte:
349 int ok;
350 category[cat_no].item_value[item_no] = (char *) xmalloc (
351 __alignof__ (char));
352 ok = get_byte (category[cat_no].item_value[item_no]);
353 ignore_to_eol (0, ok);
355 break;
356 case bytearray:
358 char *buffer;
359 int maxsize;
360 int cnt;
361 char byte;
362 int ok;
364 buffer = (char *) xmalloc ((maxsize = 30));
365 cnt = 0;
367 while ((ok = get_byte (&byte)))
369 if (cnt >= maxsize)
370 buffer = (char *) xmalloc ((maxsize *= 2));
372 buffer[cnt++] = byte;
374 token = locfile_lex (&ptr, &len);
375 if (token != TOK_CHAR || len != ';')
376 break;
379 buffer[cnt] = '\0';
380 category[cat_no].item_value[item_no] = buffer;
381 ignore_to_eol (token, ok);
383 break;
384 default:
385 error (5, 0, gettext ("internal error in %s, line %u"),
386 __FUNCTION__, __LINE__);
387 /* NOTREACHED */
390 /* Get next token. */
391 token = xlocfile_lex (&ptr, &len);
392 } /* while (1) */
397 /* Check given values for categories for consistency. */
398 void
399 categories_check (void)
401 int cat_no;
403 for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
404 if (category[cat_no].copy_locale == NULL)
405 if (category[cat_no].filled != 0)
406 if (category[cat_no].checkfct)
407 category[cat_no].checkfct();
408 else
410 int item_no;
412 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
413 if (category[cat_no].item_value[item_no] == NULL)
415 int errcode;
417 /* If the item is defined in the standard is it an error to
418 have it not defined. */
419 errcode = category[cat_no].item_desc[item_no].status == std
420 ? 5 : 0;
422 error (errcode, 0, gettext ("item `%s' of category `%s' "
423 "undefined"),
424 category[cat_no].item_desc[item_no].name,
425 category[cat_no].name);
428 else
429 error (0, 0, gettext ("category `%s' not defined"),
430 category[cat_no].name);
434 /* Write out the binary representation of the category data which can be
435 loaded by setlocale(1). */
436 void
437 categories_write (void)
439 struct locale_file
441 int magic;
442 int n;
443 int idx[0];
444 } *data;
445 struct obstack obstk;
446 int cat_no;
448 #define obstack_chunk_alloc xmalloc
449 #define obstack_chunk_free free
450 obstack_init (&obstk);
452 for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
454 int result = 0;
456 if (category[cat_no].copy_locale != NULL)
457 /* Simply copy the addressed locale file of the specified
458 category. Please note that this is tried before the distinction
459 between categories which need special handling is made. */
461 int source;
463 /* Open source file. */
464 source = open (category[cat_no].copy_locale, O_RDONLY);
465 if (source < 0)
466 error (0, 0, gettext ("cannot copy locale definition file `%s'"),
467 category[cat_no].copy_locale);
468 else
470 /* Construct file name of output file and open for writing. */
471 char path[strlen (output_path)
472 + strlen(category[cat_no].name) + 1];
473 int dest;
474 char *t;
476 t = stpcpy (path, output_path);
477 strcpy (t, category[cat_no].name);
479 dest = creat (path, 0666);
480 if (dest == -1)
481 error (0, 0, gettext ("cannot open output file `%s': %m"),
482 path);
483 else
485 char buffer[BUFSIZ];
486 int size;
488 /* Copy the files. */
491 size = read (source, buffer, BUFSIZ);
492 write (dest, buffer, size);
494 while (size > 0);
496 close (dest);
498 /* Show success. */
499 puts (category[cat_no].name);
501 close (source);
504 /* Next category. */
505 continue;
508 if (category[cat_no].outfct)
509 result = category[cat_no].outfct();
510 else
512 char *path, *t;
513 int fd;
514 struct iovec *iov;
515 int item_no, len, slen, cnt;
516 int elems = 0;
518 /* Count number of elements. */
519 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
521 switch (category[cat_no].item_desc[item_no].value_type)
523 case string:
524 case byte:
525 case bytearray:
526 ++elems;
527 break;
528 case stringarray:
529 elems += category[cat_no].item_desc[item_no].max;
530 break;
531 default:
532 error (5, 0, gettext ("internal error in %s, line %u"),
533 __FUNCTION__, __LINE__);
534 /* NOTREACHED */
538 /* We now have the number of elements. We build the structure
539 and a helper structure for writing all out. */
540 len = sizeof (struct locale_file) + elems * sizeof (int);
541 data = obstack_alloc (&obstk, len);
542 iov = obstack_alloc (&obstk, (elems + 1) * sizeof (struct iovec));
544 data->magic = LIMAGIC (cat_no);
545 data->n = elems;
546 iov[0].iov_base = data;
547 iov[0].iov_len = len;
549 cnt = 0;
550 for (item_no = 0; item_no < category[cat_no].number; ++item_no)
551 if (category[cat_no].item_value[item_no] == NULL)
553 switch (category[cat_no].item_desc[item_no].value_type)
555 case string:
556 case byte:
557 case bytearray:
558 data->idx[cnt] = len;
559 ++len; /* We reserve one single byte for this entry. */
560 iov[1 + cnt].iov_base = (char *) "";
561 iov[1 + cnt].iov_len = 1;
562 ++cnt;
563 break;
564 case stringarray:
566 int max;
567 int nstr;
569 max = category[cat_no].item_desc[item_no].max;
571 for (nstr = 0; nstr < max; ++nstr)
573 data->idx[cnt] = len;
574 ++len;
575 iov[1 + cnt].iov_base = (char *) "";
576 iov[1 + cnt].iov_len = 1;
577 ++cnt;
582 else
583 switch (category[cat_no].item_desc[item_no].value_type)
585 case string:
586 case bytearray:
587 data->idx[cnt] = len;
588 slen = strlen (category[cat_no].item_value[item_no]) + 1;
589 len += slen;
590 iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];
591 iov[1 + cnt].iov_len = slen;
592 ++cnt;
593 break;
594 case byte:
595 data->idx[cnt] = len;
596 slen = 1;
597 len += slen;
598 iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];
599 iov[1 + cnt].iov_len = slen;
600 ++cnt;
601 break;
602 case stringarray:
604 int nstr, nact;
605 char **first;
607 if (category[cat_no].item_desc[item_no].min
608 == category[cat_no].item_desc[item_no].max)
610 nstr = category[cat_no].item_desc[item_no].min;
611 first = (char **) category[cat_no].item_value[item_no];
613 else
615 nstr = *(int *) category[cat_no].item_value[item_no];
616 first =
617 ((char **) category[cat_no].item_value[item_no]) + 1;
619 nact = nstr;
620 while (nstr > 0)
622 data->idx[cnt] = len;
623 if (*first != NULL)
625 slen = strlen (*first) + 1;
626 iov[1 + cnt].iov_base = *first;
628 else
630 slen = 1;
631 iov[1 + cnt].iov_base = (char *) "";
633 len += slen;
634 iov[1 + cnt].iov_len = slen;
635 ++cnt;
636 ++first;
637 --nstr;
639 while (nact < category[cat_no].item_desc[item_no].max)
641 data->idx[cnt] = len;
642 len += 1;
643 iov[1 + cnt].iov_base = (char *) "";
644 iov[1 + cnt].iov_len = 1;
645 ++cnt;
646 ++nact;
649 break;
650 default:
651 /* Cannot happen. */
652 break;
654 assert (cnt <= elems);
656 /* Construct the output filename from the argument given to
657 localedef on the command line. */
658 path = (char *) obstack_alloc (&obstk, strlen (output_path) +
659 2 * strlen (category[cat_no].name) + 5);
660 t = stpcpy (path, output_path);
661 strcpy (t, category[cat_no].name);
663 fd = creat (path, 0666);
665 if (fd == -1)
667 /* Check whether it failed because the named file is a directory.
668 In that case we use the file .../LC_xxx/SYS_LC_xxx, as the
669 loading functions of the C Library do. */
670 struct stat st;
672 if (stat (path, &st) == 0 && S_ISDIR (st.st_mode))
674 stpcpy (stpcpy (strchr (path, '\0'), "/SYS_"),
675 category[cat_no].name);
676 fd = creat (path, 0666);
680 if (fd == -1)
682 error (0, 0, gettext ("cannot open output file `%s': %m"),
683 path);
684 result = 1;
686 else
688 if (writev (fd, iov, cnt + 1) == -1)
690 error (0, 0, gettext ("cannot write output file `%s': %m"),
691 path);
692 result = 1;
695 if (elems==0) write(fd, &elems, 10);
697 close (fd);
699 /* The old data is not needed anymore, but keep the obstack
700 intact. */
701 obstack_free (&obstk, data);
704 if (result == 0)
705 puts (category[cat_no].name);
707 /* Now the whole obstack can be removed. */
708 obstack_free (&obstk, NULL);
712 /* Get the representation of a number. This is a positive integer or
713 the number -1 which is handled as a special symbol by the scanner. */
714 static int
715 get_byte (char *byte_ptr)
717 int token;
718 char *ptr;
719 int len;
721 token = locfile_lex (&ptr, &len);
722 if (token != TOK_NUMBER && token != TOK_MINUS1)
723 /* None of the valid number format. */
725 error (0, 0, gettext ("%s:%Zd: number expected"),
726 locfile_data.filename, locfile_data.line_no);
727 *byte_ptr = 0;
728 return 0;
731 if (token == TOK_MINUS1)
733 *byte_ptr = CHAR_MAX;
734 return 1;
737 if (len > CHAR_MAX)
738 /* The value of the numbers has to be less than CHAR_MAX. This is
739 ok for the information they have to express. */
741 error (0, 0, gettext ("%s:%Zd: invalid number"),
742 locfile_data.filename, locfile_data.line_no);
743 *byte_ptr = 0;
744 return 0;
747 *byte_ptr = len;
748 return 1;
752 /* Test whether the string STR with length LEN is the name of an existing
753 locale and whether a file for category CAT_NO is found in this directory.
754 This categories are looked for in the system locale definition file
755 directory.
756 Return the complete file name for the category file. */
757 static char *
758 is_locale_name (int cat_no, const char *str, int len)
760 static char **locale_names = NULL;
761 static int max_count = 0;
762 static int locale_count = 0;
763 int cnt, exist, fd;
764 char *fname;
765 struct stat st;
767 if (locale_names == NULL)
768 /* Read in the list of all available locales. */
770 DIR *dir;
771 struct dirent *dirent;
773 /* LOCALE_NAMES is not NULL anymore, but LOCALE_COUNT == 0. */
774 ++locale_names;
776 dir = opendir (LOCALE_PATH);
777 if (dir == NULL)
779 error (1, errno, gettext ("cannot read locale directory `%s'"),
780 LOCALE_PATH);
782 return NULL;
785 /* Now we can look for all files in the directory. */
786 while ((dirent = readdir (dir)) != NULL)
787 if (strcmp (dirent->d_name, ".") != 0
788 && strcmp (dirent->d_name, "..") != 0)
790 if (max_count == 0)
791 locale_names = (char **) xmalloc ((max_count = 10)
792 * sizeof (char *));
793 else if (locale_count >= max_count)
794 locale_names = (char **) xrealloc (locale_names,
795 (max_count *= 2)
796 * sizeof (char *));
797 locale_names[locale_count++] = strdup (dirent->d_name);
799 closedir (dir);
802 for (cnt = 0; cnt < locale_count; ++cnt)
803 if (strncmp (str, locale_names[cnt], len) == 0
804 && locale_names[cnt][len] == '\0')
805 break;
807 if (cnt >= locale_count)
808 return NULL;
810 /* Now search for this specific locale file. */
811 asprintf (&fname, "%s/%s/%s", LOCALE_PATH, locale_names[cnt],
812 category[cat_no].name);
814 fd = open (fname, O_RDONLY);
815 if (fd < 0)
817 free (fname);
818 return NULL;
821 exist = fstat (fd, &st);
822 close (fd);
824 if (exist < 0)
826 free (fname);
827 return NULL;
830 return fname;
834 * Local Variables:
835 * mode:c
836 * c-basic-offset:2
837 * End: