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. */
22 #include <localeinfo.h>
26 #include <netinet/in.h>
29 #include "localedef.h"
32 /* Arrays representing ctype tables. They must be initialized for the
33 right size to hold the full charmap. */
35 static i32
*names_b
, *toupper_b
, *tolower_b
;
37 /* For accessing the element of the (possibly sparse) array we use this
39 #define ELEM(arr, idx) \
40 (arr)[({ int h = idx % charmap_data.hash_size; \
42 while (n < charmap_data.hash_layers \
43 && names_b[n * charmap_data.hash_size + h] != idx) \
45 if (n >= charmap_data.hash_layers) \
46 error (6, 0, gettext ("internal error in %s, line %u"), \
47 __FUNCTION__, __LINE__); \
48 n * charmap_data.hash_size + h; })]
50 /* The bit used for representing a special class. */
51 #define BITPOS(class) ((class) - TOK_UPPER)
52 #define BIT(class) (1 << BITPOS (class))
54 /* Remember which class or conversion is already done. */
55 static unsigned short class_done
= 0;
56 static unsigned short toupper_done
= 0;
57 static unsigned short tolower_done
= 0;
59 #define SYNTAX_ERROR \
60 error (0, 0, gettext ("%s:%Zd: syntax error in locale definition file"), \
61 locfile_data.filename, locfile_data.line_no);
64 /* Prototypes for local functions. */
65 static void allocate_arrays (void);
66 static void set_class_defaults (void);
67 static int valid_char (int ch
);
70 /* Read CTYPE category. The initial token is given as a parameter. */
72 ctype_input (int token
)
77 /* If necessary allocate arrays. */
80 while (token
!= TOK_END
)
84 case TOK_UPPER
: case TOK_LOWER
: case TOK_ALPHA
: case TOK_DIGIT
:
85 case TOK_XDIGIT
: case TOK_SPACE
: case TOK_PRINT
: case TOK_GRAPH
:
86 case TOK_BLANK
: case TOK_CNTRL
: case TOK_PUNCT
:
88 /* TAKE CARE: the order of the tokens in "token.h" determines
89 the bit used to indicate the membership in the class. This
90 also has to correspond to the values used in <ctype.h>. */
91 int bit
= BIT (token
);
95 if ((class_done
& bit
) != 0)
98 memcpy (tmp
, ptr
, len
);
101 error (0, 0, gettext ("%s:%Zd: duplicate definiton of item "
102 "`%s' in category `LC_CTYPE'"),
103 locfile_data
.filename
, locfile_data
.line_no
, tmp
);
109 token
= xlocfile_lex (&ptr
, &len
);
111 if (token
== TOK_ENDOFLINE
)
117 if (token
== TOK_ELLIPSIS
)
119 if (was_ell
!= 0 || last
< 0)
121 error (0, 0, gettext ("%s:%Zd: illegal use of `...'"),
122 locfile_data
.filename
, locfile_data
.line_no
);
129 if (token
!= TOK_CHAR
)
131 if (token
!= TOK_ILL_CHAR
)
138 if (len
< 0 || !valid_char (len
))
145 /* We have found a valid character. Include it to
146 the class' bit set. */
149 ELEM (ctype_b
, len
) |= bit
;
158 error (0, 0, gettext ("%s:%Zd: lower bound of "
159 "ellipsis not smaller"),
160 locfile_data
.filename
, locfile_data
.line_no
);
166 for (i
= last
+ 1; i
<= len
; ++i
)
167 ELEM (ctype_b
, i
) |= bit
;
173 while ((token
= locfile_lex (&ptr
, &len
)) == TOK_CHAR
176 /* Rest of the line should be empty. */
177 ignore_to_eol (token
, 0);
180 case TOK_TOUPPER
: case TOK_TOLOWER
:
184 int is_upper
= token
== TOK_TOUPPER
;
186 if (((is_upper
? toupper_done
: tolower_done
) & BIT (token
)) != 0)
187 error (0, 0, gettext ("%s:%Zd: duplicate definition of item "
188 "`%s' in category `LC_CTYPE'"),
189 locfile_data
.filename
, locfile_data
.line_no
,
190 is_upper
? "toupper" : "tolower");
191 (is_upper
? toupper_done
: tolower_done
) |= BIT (token
);
197 token
= xlocfile_lex (&ptr
, &len
);
198 if (token
!= TOK_CHAR
|| len
!= '(')
204 token
= xlocfile_lex (&ptr
, &len
);
205 if (token
!= TOK_CHAR
&& token
!= TOK_ILL_CHAR
)
211 ignore
= token
== TOK_ILL_CHAR
;
213 token
= xlocfile_lex (&ptr
, &len
);
214 if (token
!= TOK_CHAR
|| len
!= ',')
220 token
= xlocfile_lex (&ptr
, &len
);
221 if (token
!= TOK_CHAR
&& token
!= TOK_ILL_CHAR
)
227 ignore
|= token
== TOK_ILL_CHAR
;
229 token
= xlocfile_lex (&ptr
, &len
);
230 if (token
!= TOK_CHAR
|| len
!= ')')
236 if (!ignore
&& valid_char (from
) && valid_char (to
))
237 /* Have a valid pair. */
238 ELEM (is_upper
? toupper_b
: tolower_b
, from
) = to
;
240 while ((token
= locfile_lex (&ptr
, &len
)) == TOK_CHAR
243 /* Rest of the line should be empty. */
244 ignore_to_eol (token
, 1);
249 ignore_to_eol (0, 0);
253 /* Read next token. */
254 token
= xlocfile_lex (&ptr
, &len
);
257 token
= xlocfile_lex (&ptr
, &len
);
259 if (token
!= _NL_NUM_LC_CTYPE
)
261 error (0, 0, gettext ("%s:%Zd: category `%s' does not end with "
262 "`END %s'"), locfile_data
.filename
,
263 locfile_data
.line_no
, "LC_CTYPE", "LC_CTYPE");
264 ignore_to_eol (0, 0);
267 ignore_to_eol (0, posix_conformance
);
274 /* Here are a lot of things to check. See POSIX.2, table 2-6. */
279 const char allow
[NCLASS
];
281 valid_table
[NCLASS
] =
283 /* The order is important. See token.h for more information.
284 M = Always, D = Default, - = Permitted, X = Mutually exclusive */
285 [BITPOS (TOK_UPPER
)] = { "upper", "--MX-XDDXXX" },
286 [BITPOS (TOK_LOWER
)] = { "lower", "--MX-XDDXXX" },
287 [BITPOS (TOK_ALPHA
)] = { "alpha", "---X-XDDXXX" },
288 [BITPOS (TOK_DIGIT
)] = { "digit", "XXX--XDDXXX" },
289 [BITPOS (TOK_XDIGIT
)] = { "xdigit", "-----XDDXXX" },
290 [BITPOS (TOK_SPACE
)] = { "space", "XXXXX------" },
291 [BITPOS (TOK_PRINT
)] = { "print", "---------X-" },
292 [BITPOS (TOK_GRAPH
)] = { "graph", "---------X-" },
293 [BITPOS (TOK_BLANK
)] = { "blank", "XXXXXM-----" },
294 [BITPOS (TOK_CNTRL
)] = { "cntrl", "XXXXX-XX--X" },
295 [BITPOS (TOK_PUNCT
)] = { "punct", "XXXXX-DD-X-" }
297 int ch
, cls1
, cls2
, eq
, space_char
;
300 /* Set default value for classes not specified. */
301 set_class_defaults ();
303 /* Check according to table. */
304 for (ch
= 0; ch
< charmap_data
.hash_size
* charmap_data
.hash_layers
; ++ch
)
306 if (ch
!= 0 && names_b
[ch
] == 0)
308 tmp
= ELEM (ctype_b
, names_b
[ch
]);
309 for (cls1
= 0; cls1
< NCLASS
; ++cls1
)
310 if ((tmp
& (1 << cls1
)) != 0)
311 for (cls2
= 0; cls2
< NCLASS
; ++cls2
)
312 if (cls2
!= cls1
&& valid_table
[cls1
].allow
[cls2
] != '-')
314 eq
= (tmp
& (1 << cls2
)) != 0;
315 switch (valid_table
[cls1
].allow
[cls2
])
319 error (0, 0, gettext ("character '\\%o' in class `%s' "
320 "must be in class `%s'"), ch
,
321 valid_table
[cls1
].name
, valid_table
[cls2
].name
);
325 error (0, 0, gettext ("character '\\%o' inc class `%s' "
326 "must not be in class `%s'"), ch
,
327 valid_table
[cls1
].name
, valid_table
[cls2
].name
);
330 ELEM (ctype_b
, names_b
[ch
]) |= 1 << cls2
;
333 error (5, 0, gettext ("internal error in %s, line %u"),
334 __FUNCTION__
, __LINE__
);
339 /* ... and now test <SP> as a special case. */
340 if (find_entry (&charmap_data
.table
, "SP", 2, (void **) &space_char
) == 0)
341 error (0, 0, gettext ("character <SP> not defined in character map"));
342 else if ((tmp
= BITPOS (TOK_SPACE
),
343 (ELEM (ctype_b
, space_char
) & BIT (TOK_SPACE
)) == 0)
344 || (tmp
= BITPOS (TOK_BLANK
),
345 (ELEM (ctype_b
, space_char
) & BIT (TOK_BLANK
)) == 0))
346 error (0, 0, gettext ("<SP> character not in class `%s'"),
347 valid_table
[tmp
].name
);
348 else if ((tmp
= BITPOS (TOK_PUNCT
),
349 (ELEM (ctype_b
, space_char
) & BIT (TOK_PUNCT
)) != 0)
350 || (tmp
= BITPOS (TOK_GRAPH
),
351 (ELEM (ctype_b
, space_char
) & BIT (TOK_GRAPH
)) != 0))
352 error (0, 0, gettext ("<SP> character must not be in class `%s'"),
353 valid_table
[tmp
].name
);
355 ELEM (ctype_b
, space_char
) |= BIT (TOK_PRINT
);
359 /* These macros can change little to big endian and vice versa. */
361 ((u16) (((((unsigned short) (v)) & 0x00ff) << 8) \
362 | ((((unsigned short) (v)) & 0xff00) >> 8)))
364 ((u32) (((((u32) (v)) & 0x000000ff) << 24) \
365 | ((((u32) (v)) & 0x0000ff00) << 8) \
366 | ((((u32) (v)) & 0x00ff0000) >> 8) \
367 | ((((u32) (v)) & 0xff000000) >> 24)))
375 /* File descriptor for output file. */
378 i32 magic
= LIMAGIC (LC_CTYPE
);
379 /* Number of table. */
381 /* Number ints in leading information table. */
383 i32 n
= 2 + 2 * tables
;
387 /* Values describing the character set. */
388 char mb_cur_min
= (char) charmap_data
.mb_cur_min
;
389 char mb_cur_max
= (char) charmap_data
.mb_cur_max
;
390 /* Optimal size of hashing table. */
391 i32 hash_size
= charmap_data
.hash_size
;
392 i32 hash_layers
= charmap_data
.hash_layers
;
393 /* Number of elements in the tables. */
394 int size
= hash_size
* charmap_data
.hash_layers
;
395 /* Positions of the tables. */
398 /* No, no. We don't play towers of Hanoi. This is a more or less
399 readable table of the offsets of the different strings in the
400 produced file. It is seperated in three columns which represent
401 the number of values with 1, 2, and 4 bytes. */
409 2 + 2 * (128 + size
) + 4 * (4 + n
),
410 2 + 2 * (128 + size
) + 4 * ((4 + n
) + (size
+ 128)),
411 2 + 2 * (128 + size
) + 4 * ((4 + n
) + 2 * (size
+ 128)),
412 2 + 2 * (128 + size
) + 4 * ((4 + n
) + 2 * (size
+ 128) + 1 * size
),
413 2 + 2 * (128 + size
) + 4 * ((5 + n
) + 2 * (size
+ 128) + 1 * size
),
414 2 + 2 * (128 + size
) + 4 * ((6 + n
) + 2 * (size
+ 128) + 1 * size
),
415 2 + 2 * (2 * (128 + size
)) + 4 * ((6 + n
) + 2 * (size
+ 128) + 1 * size
),
416 2 + 2 * (2 * (128 + size
)) + 4 * ((6 + n
) + 3 * (size
+ 128) + 1 * size
),
417 2 + 2 * (2 * (128 + size
)) + 4 * ((6 + n
) + 4 * (size
+ 128) + 1 * size
),
420 2 * (128 + size
) + 4 * (2 + n
),
421 2 * (128 + size
) + 4 * ((2 + n
) + (size
+ 128)),
422 2 * (128 + size
) + 4 * ((2 + n
) + 2 * (size
+ 128)),
423 2 * (128 + size
) + 4 * ((2 + n
) + 3 * (size
+ 128)),
426 /* Parameter to writev. */
427 struct iovec iov
[11] =
429 { &magic
, sizeof (i32
) },
430 { &n
, sizeof (i32
) },
432 { pos
, sizeof (pos
) },
435 { &hash_size
, sizeof (i32
) },
436 { &hash_layers
, sizeof (i32
) },
440 { ctype_b
- 128, (size
+ 128) * sizeof (u16
) },
441 { toupper_b
- 128, (size
+ 128) * sizeof (i32
) },
442 { tolower_b
- 128, (size
+ 128) * sizeof (i32
) },
443 { names_b
, size
* sizeof (i32
) }
447 /* Now we can bring the representations into the right form. */
448 for (ch
= -128; ch
< -1; ++ch
)
450 ctype_b
[ch
] = ctype_b
[256 + ch
];
451 toupper_b
[ch
] = toupper_b
[256 + ch
];
452 tolower_b
[ch
] = tolower_b
[256 + ch
];
454 /* Set value for EOF. */
459 for (ch
= -128; ch
< size
; ++ch
)
460 ctype_b
[ch
] = htons (ctype_b
[ch
]);
462 /* Construct the output filename from the argument given to
463 localedef on the command line. */
464 path
= (char *) alloca (strlen (output_path
) +
465 strlen (category
[LC_CTYPE
].name
) + 1);
466 t
= stpcpy (path
, output_path
);
467 strcpy (t
, category
[LC_CTYPE
].name
);
469 fd
= creat (path
, 0666);
472 error (0, 0, gettext ("cannot open output file `%s': %m"), path
);
480 if (writev (fd
, iov
, 10) == -1)
482 if (writev (fd
, iov
, 6) == -1)
485 error (0, 0, gettext ("cannot write output file `%s': %m"), path
);
487 goto close_and_return
;
490 /* Now we have to write the three tables with different endianess. */
491 hash_size
= SWAP32 (hash_size
);
492 for (idx
= -128; idx
< size
; ++idx
)
494 ctype_b
[idx
] = SWAP16 (ctype_b
[idx
]);
495 toupper_b
[idx
] = SWAP32 (toupper_b
[idx
]);
496 tolower_b
[idx
] = SWAP32 (tolower_b
[idx
]);
498 names_b
[idx
] = SWAP32 (names_b
[idx
]);
502 if (writev (fd
, iov
+ 5, 6) == -1)
504 if (writev (fd
, iov
+ 3, 2) == -1)
507 error (0, 0, gettext ("cannot write output file `%s': %m"), path
);
519 /* If necessary allocate the memory for the arrays according to the
520 current character map. */
522 allocate_arrays (void)
524 /* Init ctype data structures. */
526 /* All data structures are not initialized yet. */
528 /* You wonder about this amount of memory? This is only because
529 some users do not manage to address the array with unsigned
530 values or data types with range >= 256. '\200' would result
531 in the array index -128. To help these poor people we
532 duplicate the entries for 128 upto 255 below the entry for \0. */
535 int size
= charmap_data
.hash_size
* charmap_data
.hash_layers
;
537 ctype_b
= xmalloc ((size
- (-128)) * sizeof (u16
));
538 bzero (ctype_b
, (size
- (-128)) * sizeof (u16
));
542 names_b
= xmalloc (size
* sizeof (i32
));
543 bzero (names_b
, size
* sizeof (i32
));
545 toupper_b
= xmalloc ((size
- (-128)) * sizeof (i32
));
546 bzero (toupper_b
, (size
- (-128)) * sizeof (i32
));
549 tolower_b
= xmalloc ((size
- (-128)) * sizeof (i32
));
550 bzero (tolower_b
, (size
- (-128)) * sizeof (i32
));
554 /* Mark the place of the NUL character as occupied. */
557 while (iterate_table (&charmap_data
.table
, (void **) &ptr
,
560 /* We already handled the NUL character. */
564 h
= ch
% charmap_data
.hash_size
;
566 while (names_b
[h
+ n
* charmap_data
.hash_size
] != 0)
569 names_b
[h
+ n
* charmap_data
.hash_size
] = ch
;
570 toupper_b
[h
+ n
* charmap_data
.hash_size
] = ch
;
571 tolower_b
[h
+ n
* charmap_data
.hash_size
] = ch
;
573 /* Correct the value for NUL character. */
579 set_class_defaults (void)
581 /* These function defines the default values for the classes and conversions
582 according to POSIX.2 2.5.2.1.
583 It may seem that the order of these if-blocks is arbitrary but it is NOT.
584 Don't move them unless you know what you do! */
586 void set_default (int bit
, int from
, int to
)
593 for (ch
= from
; ch
<= to
; ++ch
)
598 code
= find_char (tmp
+ 1, 1);
600 error (5, 0, gettext ("character `%s' not defined while needed "
601 "as default value"), tmp
);
602 ELEM (ctype_b
, code
) |= bit
;
606 /* If necessary allocate arrays. */
609 /* Set default values if keyword was not present. */
610 if ((class_done
& BIT (TOK_UPPER
)) == 0)
611 /* "If this keyword [lower] is not specified, the lowercase letters
612 `A' through `Z', ..., shall automatically belong to this class,
613 with implementation defined character values." */
614 set_default (BIT (TOK_UPPER
), 'A', 'Z');
616 if ((class_done
& BIT (TOK_LOWER
)) == 0)
617 /* "If this keyword [lower] is not specified, the lowercase letters
618 `a' through `z', ..., shall automatically belong to this class,
619 with implementation defined character values." */
620 set_default (BIT (TOK_LOWER
), 'a', 'z');
622 if ((class_done
& BIT (TOK_DIGIT
)) == 0)
623 /* "If this keyword [digit] is not specified, the digits `0' through
624 `9', ..., shall automatically belong to this class, with
625 implementation-defined character values." */
626 set_default (BIT (TOK_DIGIT
), '0', '9');
628 if ((class_done
& BIT (TOK_SPACE
)) == 0)
629 /* "If this keyword [space] is not specified, the characters <space>,
630 <form-feed>, <newline>, <carriage-return>, <tab>, and
631 <vertical-tab>, ..., shall automatically belong to this class,
632 with implementtation-defined character values." */
636 code
= find_char ("space", 5);
638 error (5, 0, gettext ("character `%s' not defined while needed as "
639 "default value"), "<space>");
640 ELEM (ctype_b
, code
) |= BIT (TOK_SPACE
);
642 code
= find_char ("form-feed", 9);
644 error (5, 0, gettext ("character `%s' not defined while needed as "
645 "default value"), "<form-feed>");
646 ELEM (ctype_b
, code
) |= BIT (TOK_SPACE
);
648 code
= find_char ("newline", 7);
650 error (5, 0, gettext ("character `%s' not defined while needed as "
651 "default value"), "<newline>");
652 ELEM (ctype_b
, code
) |= BIT (TOK_SPACE
);
654 code
= find_char ("carriage-return", 15);
656 error (5, 0, gettext ("character `%s' not defined while needed as "
657 "default value"), "<carriage-return>");
658 ELEM (ctype_b
, code
) |= BIT (TOK_SPACE
);
660 code
= find_char ("tab", 3);
662 error (5, 0, gettext ("character `%s' not defined while needed as "
663 "default value"), "<tab>");
664 ELEM (ctype_b
, code
) |= BIT (TOK_SPACE
);
666 code
= find_char ("vertical-tab", 11);
668 error (5, 0, gettext ("character `%s' not defined while needed as "
669 "default value"), "<vertical-tab>");
670 ELEM (ctype_b
, code
) |= BIT (TOK_SPACE
);
673 if ((class_done
& BIT (TOK_XDIGIT
)) == 0)
674 /* "If this keyword is not specified, the digits `0' to `9', the
675 uppercase letters `A' through `F', and the lowercase letters `a'
676 through `f', ..., shell automatically belong to this class, with
677 implementation defined character values." */
679 if ((class_done
& BIT (TOK_XDIGIT
)) == 0)
680 set_default (BIT (TOK_XDIGIT
), '0', '9');
682 if ((class_done
& BIT (TOK_XDIGIT
)) == 0)
683 set_default (BIT (TOK_XDIGIT
), 'A', 'F');
685 if ((class_done
& BIT (TOK_XDIGIT
)) == 0)
686 set_default (BIT (TOK_XDIGIT
), 'a', 'f');
689 if ((class_done
& BIT (TOK_BLANK
)) == 0)
690 /* "If this keyword [blank] is unspecified, the characters <space> and
691 <tab> shall belong to this character class." */
695 code
= find_char ("space", 5);
697 error (5, 0, gettext ("character `%s' not defined while needed as "
698 "default value"), "<space>");
699 ELEM (ctype_b
, code
) |= BIT (TOK_BLANK
);
701 code
= find_char ("tab", 3);
703 error (5, 0, gettext ("character `%s' not defined while needed as "
704 "default value"), "<tab>");
705 ELEM (ctype_b
, code
) |= BIT (TOK_BLANK
);
708 if ((class_done
& BIT (TOK_GRAPH
)) == 0)
709 /* "If this keyword [graph] is not specified, characters specified for
710 the keywords `upper', `lower', `alpha', `digit', `xdigit' and `punct',
711 shall belong to this character class." */
714 unsigned short int mask
= BIT (TOK_UPPER
) | BIT (TOK_LOWER
) |
715 BIT (TOK_ALPHA
) | BIT (TOK_DIGIT
) | BIT (TOK_XDIGIT
) | BIT (TOK_PUNCT
);
717 for (ch
= 0; ch
< charmap_data
.hash_size
* charmap_data
.hash_layers
;
720 if (ch
!= 0 && names_b
[ch
] == 0)
722 if ((ELEM (ctype_b
, names_b
[ch
]) & mask
) != 0)
723 ELEM (ctype_b
, names_b
[ch
]) |= BIT (TOK_GRAPH
);
727 if ((class_done
& BIT (TOK_PRINT
)) == 0)
728 /* "If this keyword [print] is not provided, characters specified for
729 the keywords `upper', `lower', `alpha', `digit', `xdigit', `punct',
730 and the <space> character shall belong to this character class." */
733 int space
= find_char ("space", 5);
734 unsigned short int mask
= BIT (TOK_UPPER
) | BIT (TOK_LOWER
) |
735 BIT (TOK_ALPHA
) | BIT (TOK_DIGIT
) | BIT (TOK_XDIGIT
) | BIT (TOK_PUNCT
);
738 error (5, 0, gettext ("character `%s' not defined while needed as "
739 "default value"), "<space>");
741 for (ch
= 0; ch
< charmap_data
.hash_size
* charmap_data
.hash_layers
;
744 if (ch
!= 0 && names_b
[ch
] == 0)
746 if ((ELEM (ctype_b
, names_b
[ch
]) & mask
) != 0)
747 ELEM (ctype_b
, names_b
[ch
]) |= BIT (TOK_PRINT
);
749 ELEM (ctype_b
, space
) |= BIT (TOK_PRINT
);
752 if (toupper_done
== 0)
753 /* "If this keyword [toupper] is not spcified, the lowercase letters
754 `a' through `z', and their corresponding uppercase letters `A' to
755 `Z', ..., shall automatically be included, with implementation-
756 defined character values." */
763 for (ch
= 'a'; ch
<= 'z'; ++ch
)
765 int code_to
, code_from
;
768 code_from
= find_char (tmp
+ 1, 1);
770 error (5, 0, gettext ("character `%s' not defined while needed "
771 "as default value"), tmp
);
773 /* This conversion is implementation defined. */
774 tmp
[1] = ch
+ ('A' - 'a');
775 code_to
= find_char (tmp
+ 1, 1);
777 error (5, 0, gettext ("character `%s' not defined while needed "
778 "as default value"), tmp
);
780 ELEM (toupper_b
, code_from
) = code_to
;
784 if (tolower_done
== 0)
785 /* "If this keyword [tolower] is not specified, the mapping shall be
786 the reverse mapping of the one specified to `toupper'." */
790 for (ch
= 0; ch
< charmap_data
.hash_size
* charmap_data
.hash_layers
;
793 if (ch
!= 0 && names_b
[ch
] == 0)
796 if (toupper_b
[ch
] != names_b
[ch
])
797 ELEM (tolower_b
, toupper_b
[ch
]) = names_b
[ch
];
803 /* Test whether the given character is valid for the current charmap. */
807 /* FIXME: this assumes 32-bit integers. */
809 && (charmap_data
.mb_cur_max
< 4
810 ? ch
< 1 << (8 * charmap_data
.mb_cur_max
) : 1);