Update copyright notices with scripts/update-copyrights
[glibc.git] / locale / programs / charmap.c
blob1fcce5c327c965bef91e39c11a733f442507349c
1 /* Copyright (C) 1996-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.org>, 1996.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
22 #include <ctype.h>
23 #include <errno.h>
24 #include <libintl.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <error.h>
30 #include <stdint.h>
32 #include "localedef.h"
33 #include "linereader.h"
34 #include "charmap.h"
35 #include "charmap-dir.h"
37 #include <assert.h>
40 /* Define the lookup function. */
41 #include "charmap-kw.h"
44 /* Prototypes for local functions. */
45 static struct charmap_t *parse_charmap (struct linereader *cmfile,
46 int verbose, int be_quiet);
47 static void new_width (struct linereader *cmfile, struct charmap_t *result,
48 const char *from, const char *to,
49 unsigned long int width);
50 static void charmap_new_char (struct linereader *lr, struct charmap_t *cm,
51 size_t nbytes, unsigned char *bytes,
52 const char *from, const char *to,
53 int decimal_ellipsis, int step);
56 bool enc_not_ascii_compatible;
59 #ifdef NEED_NULL_POINTER
60 static const char *null_pointer;
61 #endif
63 static struct linereader *
64 cmlr_open (const char *directory, const char *name, kw_hash_fct_t hf)
66 FILE *fp;
68 fp = charmap_open (directory, name);
69 if (fp == NULL)
70 return NULL;
71 else
73 size_t dlen = strlen (directory);
74 int add_slash = (dlen == 0 || directory[dlen - 1] != '/');
75 size_t nlen = strlen (name);
76 char *pathname;
77 char *p;
79 pathname = alloca (dlen + add_slash + nlen + 1);
80 p = stpcpy (pathname, directory);
81 if (add_slash)
82 *p++ = '/';
83 stpcpy (p, name);
85 return lr_create (fp, pathname, hf);
89 struct charmap_t *
90 charmap_read (const char *filename, int verbose, int error_not_found,
91 int be_quiet, int use_default)
93 struct charmap_t *result = NULL;
95 if (filename != NULL)
97 struct linereader *cmfile;
99 /* First try the name as found in the parameter. */
100 cmfile = lr_open (filename, charmap_hash);
101 if (cmfile == NULL)
103 /* No successful. So start looking through the directories
104 in the I18NPATH if this is a simple name. */
105 if (strchr (filename, '/') == NULL)
107 char *i18npath = getenv ("I18NPATH");
108 if (i18npath != NULL && *i18npath != '\0')
110 const size_t pathlen = strlen (i18npath);
111 char i18npathbuf[pathlen + 1];
112 char path[pathlen + sizeof ("/charmaps")];
113 char *next;
114 i18npath = memcpy (i18npathbuf, i18npath, pathlen + 1);
116 while (cmfile == NULL
117 && (next = strsep (&i18npath, ":")) != NULL)
119 stpcpy (stpcpy (path, next), "/charmaps");
120 cmfile = cmlr_open (path, filename, charmap_hash);
122 if (cmfile == NULL)
123 /* Try without the "/charmaps" part. */
124 cmfile = cmlr_open (next, filename, charmap_hash);
128 if (cmfile == NULL)
129 /* Try the default directory. */
130 cmfile = cmlr_open (CHARMAP_PATH, filename, charmap_hash);
134 if (cmfile != NULL)
135 result = parse_charmap (cmfile, verbose, be_quiet);
137 if (result == NULL && error_not_found)
138 WITH_CUR_LOCALE (error (0, errno, _("\
139 character map file `%s' not found"), filename));
142 if (result == NULL && filename != NULL && strchr (filename, '/') == NULL)
144 /* OK, one more try. We also accept the names given to the
145 character sets in the files. Sometimes they differ from the
146 file name. */
147 CHARMAP_DIR *dir;
149 dir = charmap_opendir (CHARMAP_PATH);
150 if (dir != NULL)
152 const char *dirent;
154 while ((dirent = charmap_readdir (dir)) != NULL)
156 char **aliases;
157 char **p;
158 int found;
160 aliases = charmap_aliases (CHARMAP_PATH, dirent);
161 found = 0;
162 for (p = aliases; *p; p++)
163 if (strcasecmp (*p, filename) == 0)
165 found = 1;
166 break;
168 charmap_free_aliases (aliases);
170 if (found)
172 struct linereader *cmfile;
174 cmfile = cmlr_open (CHARMAP_PATH, dirent, charmap_hash);
175 if (cmfile != NULL)
176 result = parse_charmap (cmfile, verbose, be_quiet);
178 break;
182 charmap_closedir (dir);
186 if (result == NULL && DEFAULT_CHARMAP != NULL)
188 struct linereader *cmfile;
190 cmfile = cmlr_open (CHARMAP_PATH, DEFAULT_CHARMAP, charmap_hash);
191 if (cmfile != NULL)
192 result = parse_charmap (cmfile, verbose, be_quiet);
194 if (result == NULL)
195 WITH_CUR_LOCALE (error (4, errno, _("\
196 default character map file `%s' not found"), DEFAULT_CHARMAP));
199 if (result != NULL && result->code_set_name == NULL)
200 /* The input file does not specify a code set name. This
201 shouldn't happen but we should cope with it. */
202 result->code_set_name = basename (filename);
204 /* Test of ASCII compatibility of locale encoding.
206 Verify that the encoding to be used in a locale is ASCII compatible,
207 at least for the graphic characters, excluding the control characters,
208 '$' and '@'. This constraint comes from an ISO C 99 restriction.
210 ISO C 99 section 7.17.(2) (about wchar_t):
211 the null character shall have the code value zero and each member of
212 the basic character set shall have a code value equal to its value
213 when used as the lone character in an integer character constant.
214 ISO C 99 section 5.2.1.(3):
215 Both the basic source and basic execution character sets shall have
216 the following members: the 26 uppercase letters of the Latin alphabet
217 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
218 the 26 lowercase letters of the Latin alphabet
219 a b c d e f g h i j k l m n o p q r s t u v w x y z
220 the 10 decimal digits
221 0 1 2 3 4 5 6 7 8 9
222 the following 29 graphic characters
223 ! " # % & ' ( ) * + , - . / : ; < = > ? [ \ ] ^ _ { | } ~
224 the space character, and control characters representing horizontal
225 tab, vertical tab, and form feed.
227 Therefore, for all members of the "basic character set", the 'char' code
228 must have the same value as the 'wchar_t' code, which in glibc is the
229 same as the Unicode code, which for all of the enumerated characters
230 is identical to the ASCII code. */
231 if (result != NULL && use_default)
233 static const char basic_charset[] =
235 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
236 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
237 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
238 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
239 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
240 '!', '"', '#', '%', '&', '\'', '(', ')', '*', '+', ',', '-',
241 '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^',
242 '_', '{', '|', '}', '~', ' ', '\t', '\v', '\f', '\0'
244 int failed = 0;
245 const char *p = basic_charset;
249 struct charseq *seq = charmap_find_symbol (result, p, 1);
251 if (seq == NULL || seq->ucs4 != (uint32_t) *p)
252 failed = 1;
254 while (*p++ != '\0');
256 if (failed)
258 WITH_CUR_LOCALE (fprintf (stderr, _("\
259 character map `%s' is not ASCII compatible, locale not ISO C compliant\n"),
260 result->code_set_name));
261 enc_not_ascii_compatible = true;
265 return result;
269 static struct charmap_t *
270 parse_charmap (struct linereader *cmfile, int verbose, int be_quiet)
272 struct charmap_t *result;
273 int state;
274 enum token_t expected_tok = tok_error;
275 const char *expected_str = NULL;
276 char *from_name = NULL;
277 char *to_name = NULL;
278 enum token_t ellipsis = 0;
279 int step = 1;
281 /* We don't want symbolic names in string to be translated. */
282 cmfile->translate_strings = 0;
284 /* Allocate room for result. */
285 result = (struct charmap_t *) xmalloc (sizeof (struct charmap_t));
286 memset (result, '\0', sizeof (struct charmap_t));
287 /* The default DEFAULT_WIDTH is 1. */
288 result->width_default = 1;
290 #define obstack_chunk_alloc malloc
291 #define obstack_chunk_free free
292 obstack_init (&result->mem_pool);
294 if (init_hash (&result->char_table, 256)
295 || init_hash (&result->byte_table, 256))
297 free (result);
298 return NULL;
301 /* We use a state machine to describe the charmap description file
302 format. */
303 state = 1;
304 while (1)
306 /* What's on? */
307 struct token *now = lr_token (cmfile, NULL, NULL, NULL, verbose);
308 enum token_t nowtok = now->tok;
309 struct token *arg;
311 if (nowtok == tok_eof)
312 break;
314 switch (state)
316 case 1:
317 /* The beginning. We expect the special declarations, EOL or
318 `CHARMAP'. */
319 if (nowtok == tok_eol)
320 /* Ignore empty lines. */
321 continue;
323 if (nowtok == tok_charmap)
325 from_name = NULL;
326 to_name = NULL;
328 /* We have to set up the real work. Fill in some
329 default values. */
330 if (result->mb_cur_max == 0)
331 result->mb_cur_max = 1;
332 if (result->mb_cur_min == 0)
333 result->mb_cur_min = result->mb_cur_max;
334 if (result->mb_cur_min > result->mb_cur_max)
336 if (!be_quiet)
337 WITH_CUR_LOCALE (error (0, 0, _("\
338 %s: <mb_cur_max> must be greater than <mb_cur_min>\n"),
339 cmfile->fname));
341 result->mb_cur_min = result->mb_cur_max;
344 lr_ignore_rest (cmfile, 1);
346 state = 2;
347 continue;
350 if (nowtok != tok_code_set_name && nowtok != tok_mb_cur_max
351 && nowtok != tok_mb_cur_min && nowtok != tok_escape_char
352 && nowtok != tok_comment_char && nowtok != tok_g0esc
353 && nowtok != tok_g1esc && nowtok != tok_g2esc
354 && nowtok != tok_g3esc && nowtok != tok_repertoiremap
355 && nowtok != tok_include)
357 lr_error (cmfile, _("syntax error in prolog: %s"),
358 _("invalid definition"));
360 lr_ignore_rest (cmfile, 0);
361 continue;
364 /* We know that we need an argument. */
365 arg = lr_token (cmfile, NULL, NULL, NULL, verbose);
367 switch (nowtok)
369 case tok_code_set_name:
370 case tok_repertoiremap:
371 if (arg->tok != tok_ident && arg->tok != tok_string)
373 badarg:
374 lr_error (cmfile, _("syntax error in prolog: %s"),
375 _("bad argument"));
377 lr_ignore_rest (cmfile, 0);
378 continue;
381 if (nowtok == tok_code_set_name)
382 result->code_set_name = obstack_copy0 (&result->mem_pool,
383 arg->val.str.startmb,
384 arg->val.str.lenmb);
385 else
386 result->repertoiremap = obstack_copy0 (&result->mem_pool,
387 arg->val.str.startmb,
388 arg->val.str.lenmb);
390 lr_ignore_rest (cmfile, 1);
391 continue;
393 case tok_mb_cur_max:
394 case tok_mb_cur_min:
395 if (arg->tok != tok_number)
396 goto badarg;
398 if (verbose
399 && ((nowtok == tok_mb_cur_max
400 && result->mb_cur_max != 0)
401 || (nowtok == tok_mb_cur_max
402 && result->mb_cur_max != 0)))
403 lr_error (cmfile, _("duplicate definition of <%s>"),
404 nowtok == tok_mb_cur_min
405 ? "mb_cur_min" : "mb_cur_max");
407 if (arg->val.num < 1)
409 lr_error (cmfile,
410 _("value for <%s> must be 1 or greater"),
411 nowtok == tok_mb_cur_min
412 ? "mb_cur_min" : "mb_cur_max");
414 lr_ignore_rest (cmfile, 0);
415 continue;
417 if ((nowtok == tok_mb_cur_max && result->mb_cur_min != 0
418 && (int) arg->val.num < result->mb_cur_min)
419 || (nowtok == tok_mb_cur_min && result->mb_cur_max != 0
420 && (int) arg->val.num > result->mb_cur_max))
422 lr_error (cmfile, _("\
423 value of <%s> must be greater or equal than the value of <%s>"),
424 "mb_cur_max", "mb_cur_min");
426 lr_ignore_rest (cmfile, 0);
427 continue;
430 if (nowtok == tok_mb_cur_max)
431 result->mb_cur_max = arg->val.num;
432 else
433 result->mb_cur_min = arg->val.num;
435 lr_ignore_rest (cmfile, 1);
436 continue;
438 case tok_escape_char:
439 case tok_comment_char:
440 if (arg->tok != tok_ident)
441 goto badarg;
443 if (arg->val.str.lenmb != 1)
445 lr_error (cmfile, _("\
446 argument to <%s> must be a single character"),
447 nowtok == tok_escape_char ? "escape_char"
448 : "comment_char");
450 lr_ignore_rest (cmfile, 0);
451 continue;
454 if (nowtok == tok_escape_char)
455 cmfile->escape_char = *arg->val.str.startmb;
456 else
457 cmfile->comment_char = *arg->val.str.startmb;
459 lr_ignore_rest (cmfile, 1);
460 continue;
462 case tok_g0esc:
463 case tok_g1esc:
464 case tok_g2esc:
465 case tok_g3esc:
466 case tok_escseq:
467 lr_ignore_rest (cmfile, 0); /* XXX */
468 continue;
470 case tok_include:
471 lr_error (cmfile, _("\
472 character sets with locking states are not supported"));
473 exit (4);
475 default:
476 /* Cannot happen. */
477 assert (! "Should not happen");
479 break;
481 case 2:
482 /* We have seen `CHARMAP' and now are in the body. Each line
483 must have the format "%s %s %s\n" or "%s...%s %s %s\n". */
484 if (nowtok == tok_eol)
485 /* Ignore empty lines. */
486 continue;
488 if (nowtok == tok_end)
490 expected_tok = tok_charmap;
491 expected_str = "CHARMAP";
492 state = 90;
493 continue;
496 if (nowtok != tok_bsymbol && nowtok != tok_ucs4)
498 lr_error (cmfile, _("syntax error in %s definition: %s"),
499 "CHARMAP", _("no symbolic name given"));
501 lr_ignore_rest (cmfile, 0);
502 continue;
505 /* If the previous line was not completely correct free the
506 used memory. */
507 if (from_name != NULL)
508 obstack_free (&result->mem_pool, from_name);
510 if (nowtok == tok_bsymbol)
511 from_name = (char *) obstack_copy0 (&result->mem_pool,
512 now->val.str.startmb,
513 now->val.str.lenmb);
514 else
516 obstack_printf (&result->mem_pool, "U%08X",
517 cmfile->token.val.ucs4);
518 obstack_1grow (&result->mem_pool, '\0');
519 from_name = (char *) obstack_finish (&result->mem_pool);
521 to_name = NULL;
523 state = 3;
524 continue;
526 case 3:
527 /* We have two possibilities: We can see an ellipsis or an
528 encoding value. */
529 if (nowtok == tok_ellipsis3 || nowtok == tok_ellipsis4
530 || nowtok == tok_ellipsis2 || nowtok == tok_ellipsis4_2
531 || nowtok == tok_ellipsis2_2)
533 ellipsis = nowtok;
534 if (nowtok == tok_ellipsis4_2)
536 step = 2;
537 nowtok = tok_ellipsis4;
539 else if (nowtok == tok_ellipsis2_2)
541 step = 2;
542 nowtok = tok_ellipsis2;
544 state = 4;
545 continue;
547 /* FALLTHROUGH */
549 case 5:
550 if (nowtok != tok_charcode)
552 lr_error (cmfile, _("syntax error in %s definition: %s"),
553 "CHARMAP", _("invalid encoding given"));
555 lr_ignore_rest (cmfile, 0);
557 state = 2;
558 continue;
561 if (now->val.charcode.nbytes < result->mb_cur_min)
562 lr_error (cmfile, _("too few bytes in character encoding"));
563 else if (now->val.charcode.nbytes > result->mb_cur_max)
564 lr_error (cmfile, _("too many bytes in character encoding"));
565 else
566 charmap_new_char (cmfile, result, now->val.charcode.nbytes,
567 now->val.charcode.bytes, from_name, to_name,
568 ellipsis != tok_ellipsis2, step);
570 /* Ignore trailing comment silently. */
571 lr_ignore_rest (cmfile, 0);
573 from_name = NULL;
574 to_name = NULL;
575 ellipsis = tok_none;
576 step = 1;
578 state = 2;
579 continue;
581 case 4:
582 if (nowtok != tok_bsymbol && nowtok != tok_ucs4)
584 lr_error (cmfile, _("syntax error in %s definition: %s"),
585 "CHARMAP",
586 _("no symbolic name given for end of range"));
588 lr_ignore_rest (cmfile, 0);
589 continue;
592 /* Copy the to-name in a safe place. */
593 if (nowtok == tok_bsymbol)
594 to_name = (char *) obstack_copy0 (&result->mem_pool,
595 cmfile->token.val.str.startmb,
596 cmfile->token.val.str.lenmb);
597 else
599 obstack_printf (&result->mem_pool, "U%08X",
600 cmfile->token.val.ucs4);
601 obstack_1grow (&result->mem_pool, '\0');
602 to_name = (char *) obstack_finish (&result->mem_pool);
605 state = 5;
606 continue;
608 case 90:
609 if (nowtok != expected_tok)
610 lr_error (cmfile, _("\
611 %1$s: definition does not end with `END %1$s'"), expected_str);
613 lr_ignore_rest (cmfile, nowtok == expected_tok);
614 state = 91;
615 continue;
617 case 91:
618 /* Waiting for WIDTH... */
619 if (nowtok == tok_eol)
620 /* Ignore empty lines. */
621 continue;
623 if (nowtok == tok_width_default)
625 state = 92;
626 continue;
629 if (nowtok == tok_width)
631 lr_ignore_rest (cmfile, 1);
632 state = 93;
633 continue;
636 if (nowtok == tok_width_variable)
638 lr_ignore_rest (cmfile, 1);
639 state = 98;
640 continue;
643 lr_error (cmfile, _("\
644 only WIDTH definitions are allowed to follow the CHARMAP definition"));
646 lr_ignore_rest (cmfile, 0);
647 continue;
649 case 92:
650 if (nowtok != tok_number)
651 lr_error (cmfile, _("value for %s must be an integer"),
652 "WIDTH_DEFAULT");
653 else
654 result->width_default = now->val.num;
656 lr_ignore_rest (cmfile, nowtok == tok_number);
658 state = 91;
659 continue;
661 case 93:
662 /* We now expect `END WIDTH' or lines of the format "%s %d\n" or
663 "%s...%s %d\n". */
664 if (nowtok == tok_eol)
665 /* ignore empty lines. */
666 continue;
668 if (nowtok == tok_end)
670 expected_tok = tok_width;
671 expected_str = "WIDTH";
672 state = 90;
673 continue;
676 if (nowtok != tok_bsymbol && nowtok != tok_ucs4)
678 lr_error (cmfile, _("syntax error in %s definition: %s"),
679 "WIDTH", _("no symbolic name given"));
681 lr_ignore_rest (cmfile, 0);
682 continue;
685 if (from_name != NULL)
686 obstack_free (&result->mem_pool, from_name);
688 if (nowtok == tok_bsymbol)
689 from_name = (char *) obstack_copy0 (&result->mem_pool,
690 now->val.str.startmb,
691 now->val.str.lenmb);
692 else
694 obstack_printf (&result->mem_pool, "U%08X",
695 cmfile->token.val.ucs4);
696 obstack_1grow (&result->mem_pool, '\0');
697 from_name = (char *) obstack_finish (&result->mem_pool);
700 to_name = NULL;
702 state = 94;
703 continue;
705 case 94:
706 if (nowtok == tok_ellipsis3)
708 state = 95;
709 continue;
712 case 96:
713 if (nowtok != tok_number)
714 lr_error (cmfile, _("value for %s must be an integer"),
715 "WIDTH");
716 else
718 /* Store width for chars. */
719 new_width (cmfile, result, from_name, to_name, now->val.num);
721 from_name = NULL;
722 to_name = NULL;
725 lr_ignore_rest (cmfile, nowtok == tok_number);
727 state = 93;
728 continue;
730 case 95:
731 if (nowtok != tok_bsymbol && nowtok != tok_ucs4)
733 lr_error (cmfile, _("syntax error in %s definition: %s"),
734 "WIDTH", _("no symbolic name given for end of range"));
736 lr_ignore_rest (cmfile, 0);
738 state = 93;
739 continue;
742 if (nowtok == tok_bsymbol)
743 to_name = (char *) obstack_copy0 (&result->mem_pool,
744 now->val.str.startmb,
745 now->val.str.lenmb);
746 else
748 obstack_printf (&result->mem_pool, "U%08X",
749 cmfile->token.val.ucs4);
750 obstack_1grow (&result->mem_pool, '\0');
751 to_name = (char *) obstack_finish (&result->mem_pool);
754 state = 96;
755 continue;
757 case 98:
758 /* We now expect `END WIDTH_VARIABLE' or lines of the format
759 "%s\n" or "%s...%s\n". */
760 if (nowtok == tok_eol)
761 /* ignore empty lines. */
762 continue;
764 if (nowtok == tok_end)
766 expected_tok = tok_width_variable;
767 expected_str = "WIDTH_VARIABLE";
768 state = 90;
769 continue;
772 if (nowtok != tok_bsymbol && nowtok != tok_ucs4)
774 lr_error (cmfile, _("syntax error in %s definition: %s"),
775 "WIDTH_VARIABLE", _("no symbolic name given"));
777 lr_ignore_rest (cmfile, 0);
779 continue;
782 if (from_name != NULL)
783 obstack_free (&result->mem_pool, from_name);
785 if (nowtok == tok_bsymbol)
786 from_name = (char *) obstack_copy0 (&result->mem_pool,
787 now->val.str.startmb,
788 now->val.str.lenmb);
789 else
791 obstack_printf (&result->mem_pool, "U%08X",
792 cmfile->token.val.ucs4);
793 obstack_1grow (&result->mem_pool, '\0');
794 from_name = (char *) obstack_finish (&result->mem_pool);
796 to_name = NULL;
798 state = 99;
799 continue;
801 case 99:
802 if (nowtok == tok_ellipsis3)
803 state = 100;
805 /* Store info. */
806 from_name = NULL;
808 /* Warn */
809 state = 98;
810 continue;
812 case 100:
813 if (nowtok != tok_bsymbol && nowtok != tok_ucs4)
815 lr_error (cmfile, _("syntax error in %s definition: %s"),
816 "WIDTH_VARIABLE",
817 _("no symbolic name given for end of range"));
818 lr_ignore_rest (cmfile, 0);
819 continue;
822 if (nowtok == tok_bsymbol)
823 to_name = (char *) obstack_copy0 (&result->mem_pool,
824 now->val.str.startmb,
825 now->val.str.lenmb);
826 else
828 obstack_printf (&result->mem_pool, "U%08X",
829 cmfile->token.val.ucs4);
830 obstack_1grow (&result->mem_pool, '\0');
831 to_name = (char *) obstack_finish (&result->mem_pool);
834 /* XXX Enter value into table. */
836 lr_ignore_rest (cmfile, 1);
838 state = 98;
839 continue;
841 default:
842 WITH_CUR_LOCALE (error (5, 0, _("%s: error in state machine"),
843 __FILE__));
844 /* NOTREACHED */
846 break;
849 if (state != 91 && !be_quiet)
850 WITH_CUR_LOCALE (error (0, 0, _("%s: premature end of file"),
851 cmfile->fname));
853 lr_close (cmfile);
855 return result;
859 static void
860 new_width (struct linereader *cmfile, struct charmap_t *result,
861 const char *from, const char *to, unsigned long int width)
863 struct charseq *from_val;
864 struct charseq *to_val;
866 from_val = charmap_find_value (result, from, strlen (from));
867 if (from_val == NULL)
869 lr_error (cmfile, _("unknown character `%s'"), from);
870 return;
873 if (to == NULL)
874 to_val = from_val;
875 else
877 to_val = charmap_find_value (result, to, strlen (to));
878 if (to_val == NULL)
880 lr_error (cmfile, _("unknown character `%s'"), to);
881 return;
884 /* Make sure the number of bytes for the end points of the range
885 is correct. */
886 if (from_val->nbytes != to_val->nbytes)
888 lr_error (cmfile, _("\
889 number of bytes for byte sequence of beginning and end of range not the same: %d vs %d"),
890 from_val->nbytes, to_val->nbytes);
891 return;
895 if (result->nwidth_rules >= result->nwidth_rules_max)
897 size_t new_size = result->nwidth_rules + 32;
898 struct width_rule *new_rules =
899 (struct width_rule *) obstack_alloc (&result->mem_pool,
900 (new_size
901 * sizeof (struct width_rule)));
903 memcpy (new_rules, result->width_rules,
904 result->nwidth_rules_max * sizeof (struct width_rule));
906 result->width_rules = new_rules;
907 result->nwidth_rules_max = new_size;
910 result->width_rules[result->nwidth_rules].from = from_val;
911 result->width_rules[result->nwidth_rules].to = to_val;
912 result->width_rules[result->nwidth_rules].width = (unsigned int) width;
913 ++result->nwidth_rules;
917 struct charseq *
918 charmap_find_value (const struct charmap_t *cm, const char *name, size_t len)
920 void *result;
922 return (find_entry ((hash_table *) &cm->char_table, name, len, &result)
923 < 0 ? NULL : (struct charseq *) result);
927 static void
928 charmap_new_char (struct linereader *lr, struct charmap_t *cm,
929 size_t nbytes, unsigned char *bytes,
930 const char *from, const char *to,
931 int decimal_ellipsis, int step)
933 hash_table *ht = &cm->char_table;
934 hash_table *bt = &cm->byte_table;
935 struct obstack *ob = &cm->mem_pool;
936 char *from_end;
937 char *to_end;
938 const char *cp;
939 int prefix_len, len1, len2;
940 unsigned int from_nr, to_nr, cnt;
941 struct charseq *newp;
943 len1 = strlen (from);
945 if (to == NULL)
947 newp = (struct charseq *) obstack_alloc (ob, sizeof (*newp) + nbytes);
948 newp->nbytes = nbytes;
949 memcpy (newp->bytes, bytes, nbytes);
950 newp->name = from;
952 newp->ucs4 = UNINITIALIZED_CHAR_VALUE;
953 if ((from[0] == 'U' || from[0] == 'P') && (len1 == 5 || len1 == 9))
955 /* Maybe the name is of the form `Uxxxx' or `Uxxxxxxxx' where
956 xxxx and xxxxxxxx are hexadecimal numbers. In this case
957 we use the value of xxxx or xxxxxxxx as the UCS4 value of
958 this character and we don't have to consult the repertoire
959 map.
961 If the name is of the form `Pxxxx' or `Pxxxxxxxx' the xxxx
962 and xxxxxxxx also give the code point in UCS4 but this must
963 be in the private, i.e., unassigned, area. This should be
964 used for characters which do not (yet) have an equivalent
965 in ISO 10646 and Unicode. */
966 char *endp;
968 errno = 0;
969 newp->ucs4 = strtoul (from + 1, &endp, 16);
970 if (endp - from != len1
971 || (newp->ucs4 == ~((uint32_t) 0) && errno == ERANGE)
972 || newp->ucs4 >= 0x80000000)
973 /* This wasn't successful. Signal this name cannot be a
974 correct UCS value. */
975 newp->ucs4 = UNINITIALIZED_CHAR_VALUE;
978 insert_entry (ht, from, len1, newp);
979 insert_entry (bt, newp->bytes, nbytes, newp);
980 /* Please note that it isn't a bug if a symbol is defined more
981 than once. All later definitions are simply discarded. */
982 return;
985 /* We have a range: the names must have names with equal prefixes
986 and an equal number of digits, where the second number is greater
987 or equal than the first. */
988 len2 = strlen (to);
990 if (len1 != len2)
992 illegal_range:
993 lr_error (lr, _("invalid names for character range"));
994 return;
997 cp = &from[len1 - 1];
998 if (decimal_ellipsis)
999 while (isdigit (*cp) && cp >= from)
1000 --cp;
1001 else
1002 while (isxdigit (*cp) && cp >= from)
1004 if (!isdigit (*cp) && !isupper (*cp))
1005 lr_error (lr, _("\
1006 hexadecimal range format should use only capital characters"));
1007 --cp;
1010 prefix_len = (cp - from) + 1;
1012 if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
1013 goto illegal_range;
1015 errno = 0;
1016 from_nr = strtoul (&from[prefix_len], &from_end, decimal_ellipsis ? 10 : 16);
1017 if (*from_end != '\0' || (from_nr == UINT_MAX && errno == ERANGE)
1018 || ((to_nr = strtoul (&to[prefix_len], &to_end,
1019 decimal_ellipsis ? 10 : 16)) == UINT_MAX
1020 && errno == ERANGE)
1021 || *to_end != '\0')
1023 lr_error (lr, _("<%s> and <%s> are invalid names for range"), from, to);
1024 return;
1027 if (from_nr > to_nr)
1029 lr_error (lr, _("upper limit in range is smaller than lower limit"));
1030 return;
1033 for (cnt = from_nr; cnt <= to_nr; cnt += step)
1035 char *name_end;
1036 obstack_printf (ob, decimal_ellipsis ? "%.*s%0*d" : "%.*s%0*X",
1037 prefix_len, from, len1 - prefix_len, cnt);
1038 obstack_1grow (ob, '\0');
1039 name_end = obstack_finish (ob);
1041 newp = (struct charseq *) obstack_alloc (ob, sizeof (*newp) + nbytes);
1042 newp->nbytes = nbytes;
1043 memcpy (newp->bytes, bytes, nbytes);
1044 newp->name = name_end;
1046 newp->ucs4 = UNINITIALIZED_CHAR_VALUE;
1047 if ((name_end[0] == 'U' || name_end[0] == 'P')
1048 && (len1 == 5 || len1 == 9))
1050 /* Maybe the name is of the form `Uxxxx' or `Uxxxxxxxx' where
1051 xxxx and xxxxxxxx are hexadecimal numbers. In this case
1052 we use the value of xxxx or xxxxxxxx as the UCS4 value of
1053 this character and we don't have to consult the repertoire
1054 map.
1056 If the name is of the form `Pxxxx' or `Pxxxxxxxx' the xxxx
1057 and xxxxxxxx also give the code point in UCS4 but this must
1058 be in the private, i.e., unassigned, area. This should be
1059 used for characters which do not (yet) have an equivalent
1060 in ISO 10646 and Unicode. */
1061 char *endp;
1063 errno = 0;
1064 newp->ucs4 = strtoul (name_end + 1, &endp, 16);
1065 if (endp - name_end != len1
1066 || (newp->ucs4 == ~((uint32_t) 0) && errno == ERANGE)
1067 || newp->ucs4 >= 0x80000000)
1068 /* This wasn't successful. Signal this name cannot be a
1069 correct UCS value. */
1070 newp->ucs4 = UNINITIALIZED_CHAR_VALUE;
1073 insert_entry (ht, name_end, len1, newp);
1074 insert_entry (bt, newp->bytes, nbytes, newp);
1075 /* Please note we don't examine the return value since it is no error
1076 if we have two definitions for a symbol. */
1078 /* Increment the value in the byte sequence. */
1079 if (++bytes[nbytes - 1] == '\0')
1081 int b = nbytes - 2;
1084 if (b < 0)
1086 lr_error (lr,
1087 _("resulting bytes for range not representable."));
1088 return;
1090 while (++bytes[b--] == 0);
1096 struct charseq *
1097 charmap_find_symbol (const struct charmap_t *cm, const char *bytes,
1098 size_t nbytes)
1100 void *result;
1102 return (find_entry ((hash_table *) &cm->byte_table, bytes, nbytes, &result)
1103 < 0 ? NULL : (struct charseq *) result);