1 /* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library 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 GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
30 #include "localeinfo.h"
32 #include "locfile-token.h"
33 #include "stringtrans.h"
35 /* Uncomment the following line in the production version. */
40 void *xmalloc (size_t __n
);
41 void *xcalloc (size_t __n
, size_t __s
);
42 void *xrealloc (void *__ptr
, size_t __n
);
45 /* The bit used for representing a special class. */
46 #define BITPOS(class) ((class) - tok_upper)
47 #define BIT(class) (1 << BITPOS (class))
49 #define ELEM(ctype, collection, idx, value) \
50 *find_idx (ctype, &ctype->collection idx, &ctype->collection##_max idx, \
51 &ctype->collection##_act idx, value)
54 (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24))
57 ((((w) >> 8) & 0xff) | (((w) & 0xff) << 8))
60 ((((w) & 0xff00ff00) >> 8) | (((w) & 0xff00ff) << 8))
63 /* To be compatible with former implementations we for now restrict
64 the number of bits for character classes to 16. When compatibility
65 is not necessary anymore increase the number to 32. */
66 #define char_class_t u_int16_t
67 #define CHAR_CLASS_TRANS SWAPU16
68 #define char_class32_t u_int32_t
69 #define CHAR_CLASS32_TRANS XSWAPU32
72 /* The real definition of the struct for the LC_CTYPE locale. */
75 unsigned int *charnames
;
79 /* We will allow up to 8 * sizeof(u_int32_t) - 1 character classes. */
80 #define MAX_NR_CHARCLASS (8 * sizeof (u_int32_t) - 1)
82 const char *classnames
[MAX_NR_CHARCLASS
];
83 unsigned long int current_class_mask
;
84 unsigned int last_class_char
;
85 u_int32_t
*class_collection
;
86 size_t class_collection_max
;
87 size_t class_collection_act
;
88 unsigned long int class_done
;
90 /* If the following number ever turns out to be too small simply
91 increase it. But I doubt it will. --drepper@gnu */
92 #define MAX_NR_CHARMAP 16
93 const char *mapnames
[MAX_NR_CHARMAP
];
94 u_int32_t
*map_collection
[MAX_NR_CHARMAP
];
95 size_t map_collection_max
[MAX_NR_CHARMAP
];
96 size_t map_collection_act
[MAX_NR_CHARMAP
];
97 size_t map_collection_nr
;
99 unsigned int from_map_char
;
103 /* The arrays for the binary representation. */
104 u_int32_t plane_size
;
106 char_class_t
*ctype_b
;
107 char_class32_t
*ctype32_b
;
112 u_int32_t
*class_name_ptr
;
113 u_int32_t
*map_name_ptr
;
114 unsigned char *width
;
115 u_int32_t mb_cur_max
;
116 const char *codeset_name
;
120 /* Prototypes for local functions. */
121 static void ctype_class_newP (struct linereader
*lr
,
122 struct locale_ctype_t
*ctype
, const char *name
);
123 static void ctype_map_newP (struct linereader
*lr
,
124 struct locale_ctype_t
*ctype
,
125 const char *name
, struct charset_t
*charset
);
126 static u_int32_t
*find_idx (struct locale_ctype_t
*ctype
, u_int32_t
**table
,
127 size_t *max
, size_t *act
, unsigned int idx
);
128 static void set_class_defaults (struct locale_ctype_t
*ctype
,
129 struct charset_t
*charset
);
130 static void allocate_arrays (struct locale_ctype_t
*ctype
,
131 struct charset_t
*charset
);
135 ctype_startup (struct linereader
*lr
, struct localedef_t
*locale
,
136 struct charset_t
*charset
)
139 struct locale_ctype_t
*ctype
;
141 /* It is important that we always use UCS1 encoding for strings now. */
142 encoding_method
= ENC_UCS1
;
144 /* Allocate the needed room. */
145 locale
->categories
[LC_CTYPE
].ctype
= ctype
=
146 (struct locale_ctype_t
*) xmalloc (sizeof (struct locale_ctype_t
));
148 /* We have no names seen yet. */
149 ctype
->charnames_max
= charset
->mb_cur_max
== 1 ? 256 : 512;
151 (unsigned int *) xmalloc (ctype
->charnames_max
* sizeof (unsigned int));
152 for (cnt
= 0; cnt
< 256; ++cnt
)
153 ctype
->charnames
[cnt
] = cnt
;
154 ctype
->charnames_act
= 256;
156 /* Fill character class information. */
157 ctype
->nr_charclass
= 0;
158 ctype
->current_class_mask
= 0;
159 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
160 /* The order of the following instructions determines the bit
162 ctype_class_newP (lr
, ctype
, "upper");
163 ctype_class_newP (lr
, ctype
, "lower");
164 ctype_class_newP (lr
, ctype
, "alpha");
165 ctype_class_newP (lr
, ctype
, "digit");
166 ctype_class_newP (lr
, ctype
, "xdigit");
167 ctype_class_newP (lr
, ctype
, "space");
168 ctype_class_newP (lr
, ctype
, "print");
169 ctype_class_newP (lr
, ctype
, "graph");
170 ctype_class_newP (lr
, ctype
, "blank");
171 ctype_class_newP (lr
, ctype
, "cntrl");
172 ctype_class_newP (lr
, ctype
, "punct");
173 ctype_class_newP (lr
, ctype
, "alnum");
175 ctype
->class_collection_max
= charset
->mb_cur_max
== 1 ? 256 : 512;
176 ctype
->class_collection
177 = (u_int32_t
*) xmalloc (sizeof (unsigned long int)
178 * ctype
->class_collection_max
);
179 memset (ctype
->class_collection
, '\0',
180 sizeof (unsigned long int) * ctype
->class_collection_max
);
181 ctype
->class_collection_act
= 256;
183 /* Fill character map information. */
184 ctype
->map_collection_nr
= 0;
185 ctype
->last_map_idx
= MAX_NR_CHARMAP
;
186 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
187 ctype_map_newP (lr
, ctype
, "toupper", charset
);
188 ctype_map_newP (lr
, ctype
, "tolower", charset
);
190 /* Fill first 256 entries in `toupper' and `tolower' arrays. */
191 for (cnt
= 0; cnt
< 256; ++cnt
)
193 ctype
->map_collection
[0][cnt
] = cnt
;
194 ctype
->map_collection
[1][cnt
] = cnt
;
200 ctype_finish (struct localedef_t
*locale
, struct charset_t
*charset
)
202 /* See POSIX.2, table 2-6 for the meaning of the following table. */
207 const char allow
[NCLASS
];
209 valid_table
[NCLASS
] =
211 /* The order is important. See token.h for more information.
212 M = Always, D = Default, - = Permitted, X = Mutually exclusive */
213 { "upper", "--MX-XDDXXX-" },
214 { "lower", "--MX-XDDXXX-" },
215 { "alpha", "---X-XDDXXX-" },
216 { "digit", "XXX--XDDXXX-" },
217 { "xdigit", "-----XDDXXX-" },
218 { "space", "XXXXX------X" },
219 { "print", "---------X--" },
220 { "graph", "---------X--" },
221 { "blank", "XXXXXM-----X" },
222 { "cntrl", "XXXXX-XX--XX" },
223 { "punct", "XXXXX-DD-X-X" },
224 { "alnum", "-----XDDXXX-" }
228 unsigned int space_value
;
229 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
231 /* Set default value for classes not specified. */
232 set_class_defaults (ctype
, charset
);
234 /* Check according to table. */
235 for (cnt
= 0; cnt
< ctype
->class_collection_max
; ++cnt
)
237 unsigned long int tmp
;
239 tmp
= ctype
->class_collection
[cnt
];
243 for (cls1
= 0; cls1
< NCLASS
; ++cls1
)
244 if ((tmp
& (1 << cls1
)) != 0)
245 for (cls2
= 0; cls2
< NCLASS
; ++cls2
)
246 if (valid_table
[cls1
].allow
[cls2
] != '-')
248 int eq
= (tmp
& (1 << cls2
)) != 0;
249 switch (valid_table
[cls1
].allow
[cls2
])
258 value
= ctype
->charnames
[cnt
];
260 if ((value
& 0xff000000) != 0)
261 cp
+= sprintf (cp
, "\\%o", (value
>> 24) & 0xff);
262 if ((value
& 0xffff0000) != 0)
263 cp
+= sprintf (cp
, "\\%o", (value
>> 16) & 0xff);
264 if ((value
& 0xffffff00) != 0)
265 cp
+= sprintf (cp
, "\\%o", (value
>> 8) & 0xff);
266 sprintf (cp
, "\\%o", value
& 0xff);
270 character %s'%s' in class `%s' must be in class `%s'"), value
> 256 ? "L" : "",
271 cp
, valid_table
[cls1
].name
,
272 valid_table
[cls2
].name
);
283 value
= ctype
->charnames
[cnt
];
285 if ((value
& 0xff000000) != 0)
286 cp
+= sprintf (cp
, "\\%o", value
>> 24);
287 if ((value
& 0xffff0000) != 0)
288 cp
+= sprintf (cp
, "\\%o", (value
>> 16) & 0xff);
289 if ((value
& 0xffffff00) != 0)
290 cp
+= sprintf (cp
, "\\%o", (value
>> 8) & 0xff);
291 sprintf (cp
, "\\%o", value
& 0xff);
295 character %s'%s' in class `%s' must not be in class `%s'"),
296 value
> 256 ? "L" : "", cp
,
297 valid_table
[cls1
].name
,
298 valid_table
[cls2
].name
);
303 ctype
->class_collection
[cnt
] |= 1 << cls2
;
307 error (5, 0, _("internal error in %s, line %u"),
308 __FUNCTION__
, __LINE__
);
313 /* ... and now test <SP> as a special case. */
314 space_value
= charset_find_value (charset
, "SP", 2);
315 if ((wchar_t) space_value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
316 error (0, 0, _("character <SP> not defined in character map"));
317 else if (((cnt
= BITPOS (tok_space
),
318 (ELEM (ctype
, class_collection
, , space_value
)
319 & BIT (tok_space
)) == 0)
320 || (cnt
= BITPOS (tok_blank
),
321 (ELEM (ctype
, class_collection
, , space_value
)
322 & BIT (tok_blank
)) == 0))
324 error (0, 0, _("<SP> character not in class `%s'"),
325 valid_table
[cnt
].name
);
326 else if (((cnt
= BITPOS (tok_punct
),
327 (ELEM (ctype
, class_collection
, , space_value
)
328 & BIT (tok_punct
)) != 0)
329 || (cnt
= BITPOS (tok_graph
),
330 (ELEM (ctype
, class_collection
, , space_value
)
334 error (0, 0, _("<SP> character must not be in class `%s'"),
335 valid_table
[cnt
].name
);
337 ELEM (ctype
, class_collection
, , space_value
) |= BIT (tok_print
);
339 /* Now that the tests are done make sure the name array contains all
340 characters which are handled in the WIDTH section of the
341 character set definition file. */
342 if (charset
->width_rules
!= NULL
)
343 for (cnt
= 0; cnt
< charset
->nwidth_rules
; ++cnt
)
346 for (inner
= charset
->width_rules
[cnt
].from
;
347 inner
<= charset
->width_rules
[cnt
].to
; ++inner
)
348 (void) find_idx (ctype
, NULL
, NULL
, NULL
, inner
);
354 ctype_output (struct localedef_t
*locale
, struct charset_t
*charset
,
355 const char *output_path
)
357 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
358 const size_t nelems
= (_NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
)
359 + 2 * (ctype
->map_collection_nr
- 2));
360 struct iovec iov
[2 + nelems
+ ctype
->nr_charclass
361 + ctype
->map_collection_nr
];
362 struct locale_file data
;
363 u_int32_t idx
[nelems
];
364 size_t elem
, cnt
, offset
, total
;
367 if ((locale
->binary
& (1 << LC_CTYPE
)) != 0)
369 iov
[0].iov_base
= ctype
;
370 iov
[0].iov_len
= locale
->len
[LC_CTYPE
];
372 write_locale_data (output_path
, "LC_CTYPE", 1, iov
);
378 /* Now prepare the output: Find the sizes of the table we can use. */
379 allocate_arrays (ctype
, charset
);
381 data
.magic
= LIMAGIC (LC_CTYPE
);
383 iov
[0].iov_base
= (void *) &data
;
384 iov
[0].iov_len
= sizeof (data
);
386 iov
[1].iov_base
= (void *) idx
;
387 iov
[1].iov_len
= sizeof (idx
);
389 idx
[0] = iov
[0].iov_len
+ iov
[1].iov_len
;
392 for (elem
= 0; elem
< nelems
; ++elem
)
394 if (elem
< _NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
))
397 #define CTYPE_DATA(name, base, len) \
398 case _NL_ITEM_INDEX (name): \
399 iov[2 + elem + offset].iov_base = (base); \
400 iov[2 + elem + offset].iov_len = (len); \
401 if (elem + 1 < nelems) \
402 idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len; \
405 CTYPE_DATA (_NL_CTYPE_CLASS
,
407 (256 + 128) * sizeof (char_class_t
));
409 CTYPE_DATA (_NL_CTYPE_TOUPPER_EB
,
411 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
412 * sizeof (u_int32_t
));
413 CTYPE_DATA (_NL_CTYPE_TOLOWER_EB
,
415 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
416 * sizeof (u_int32_t
));
418 CTYPE_DATA (_NL_CTYPE_TOUPPER_EL
,
420 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
421 * sizeof (u_int32_t
));
422 CTYPE_DATA (_NL_CTYPE_TOLOWER_EL
,
424 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
425 * sizeof (u_int32_t
));
427 CTYPE_DATA (_NL_CTYPE_CLASS32
,
429 (ctype
->plane_size
* ctype
->plane_cnt
430 * sizeof (char_class32_t
)));
432 CTYPE_DATA (_NL_CTYPE_NAMES_EB
,
433 ctype
->names_eb
, (ctype
->plane_size
* ctype
->plane_cnt
434 * sizeof (u_int32_t
)));
435 CTYPE_DATA (_NL_CTYPE_NAMES_EL
,
436 ctype
->names_el
, (ctype
->plane_size
* ctype
->plane_cnt
437 * sizeof (u_int32_t
)));
439 CTYPE_DATA (_NL_CTYPE_HASH_SIZE
,
440 &ctype
->plane_size
, sizeof (u_int32_t
));
441 CTYPE_DATA (_NL_CTYPE_HASH_LAYERS
,
442 &ctype
->plane_cnt
, sizeof (u_int32_t
));
444 case _NL_ITEM_INDEX (_NL_CTYPE_CLASS_NAMES
):
445 /* The class name array. */
447 for (cnt
= 0; cnt
< ctype
->nr_charclass
; ++cnt
, ++offset
)
449 iov
[2 + elem
+ offset
].iov_base
450 = (void *) ctype
->classnames
[cnt
];
451 iov
[2 + elem
+ offset
].iov_len
452 = strlen (ctype
->classnames
[cnt
]) + 1;
453 total
+= iov
[2 + elem
+ offset
].iov_len
;
455 iov
[2 + elem
+ offset
].iov_base
= (void *) "\0\0\0";
456 iov
[2 + elem
+ offset
].iov_len
= 1 + (4 - ((total
+ 1) % 4));
457 total
+= 1 + (4 - ((total
+ 1) % 4));
459 if (elem
+ 1 < nelems
)
460 idx
[elem
+ 1] = idx
[elem
] + total
;
463 case _NL_ITEM_INDEX (_NL_CTYPE_MAP_NAMES
):
464 /* The class name array. */
466 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
, ++offset
)
468 iov
[2 + elem
+ offset
].iov_base
469 = (void *) ctype
->mapnames
[cnt
];
470 iov
[2 + elem
+ offset
].iov_len
471 = strlen (ctype
->mapnames
[cnt
]) + 1;
472 total
+= iov
[2 + elem
+ offset
].iov_len
;
474 iov
[2 + elem
+ offset
].iov_base
= (void *) "\0\0\0";
475 iov
[2 + elem
+ offset
].iov_len
= 1 + (4 - ((total
+ 1) % 4));
476 total
+= 1 + (4 - ((total
+ 1) % 4));
478 if (elem
+ 1 < nelems
)
479 idx
[elem
+ 1] = idx
[elem
] + total
;
482 CTYPE_DATA (_NL_CTYPE_WIDTH
,
483 ctype
->width
, ctype
->plane_size
* ctype
->plane_cnt
);
485 CTYPE_DATA (_NL_CTYPE_MB_CUR_MAX
,
486 &ctype
->mb_cur_max
, sizeof (u_int32_t
));
488 case _NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME
):
489 total
= strlen (ctype
->codeset_name
) + 1;
491 iov
[2 + elem
+ offset
].iov_base
= (char *) ctype
->codeset_name
;
494 iov
[2 + elem
+ offset
].iov_base
= alloca ((total
+ 3) & ~3);
495 memset (mempcpy (iov
[2 + elem
+ offset
].iov_base
,
496 ctype
->codeset_name
, total
),
497 '\0', 4 - (total
& 3));
498 total
= (total
+ 3) & ~3;
500 iov
[2 + elem
+ offset
].iov_len
= total
;
501 if (elem
+ 1 < nelems
)
502 idx
[elem
+ 1] = idx
[elem
] + iov
[2 + elem
+ offset
].iov_len
;
506 assert (! "unknown CTYPE element");
510 /* Handle extra maps. */
511 size_t nr
= (elem
- _NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
)) >> 1;
513 if (((elem
- _NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
)) & 1) == 0)
514 iov
[2 + elem
+ offset
].iov_base
= ctype
->map_eb
[nr
];
516 iov
[2 + elem
+ offset
].iov_base
= ctype
->map_el
[nr
];
518 iov
[2 + elem
+ offset
].iov_len
= ((ctype
->plane_size
519 * ctype
->plane_cnt
+ 128)
520 * sizeof (u_int32_t
));
522 if (elem
+ 1 < nelems
)
523 idx
[elem
+ 1] = idx
[elem
] + iov
[2 + elem
+ offset
].iov_len
;
527 assert (2 + elem
+ offset
== (nelems
+ ctype
->nr_charclass
528 + ctype
->map_collection_nr
+ 2));
530 write_locale_data (output_path
, "LC_CTYPE", 2 + elem
+ offset
, iov
);
534 /* Character class handling. */
536 ctype_class_new (struct linereader
*lr
, struct localedef_t
*locale
,
537 enum token_t tok
, struct token
*code
,
538 struct charset_t
*charset
)
540 ctype_class_newP (lr
, locale
->categories
[LC_CTYPE
].ctype
,
541 code
->val
.str
.start
);
546 ctype_is_charclass (struct linereader
*lr
, struct localedef_t
*locale
,
551 for (cnt
= 0; cnt
< locale
->categories
[LC_CTYPE
].ctype
->nr_charclass
; ++cnt
)
552 if (strcmp (name
, locale
->categories
[LC_CTYPE
].ctype
->classnames
[cnt
])
561 ctype_class_start (struct linereader
*lr
, struct localedef_t
*locale
,
562 enum token_t tok
, const char *str
,
563 struct charset_t
*charset
)
565 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
609 assert (! "illegal token as class name: should not happen");
612 for (cnt
= 0; cnt
< ctype
->nr_charclass
; ++cnt
)
613 if (strcmp (str
, ctype
->classnames
[cnt
]) == 0)
616 if (cnt
>= ctype
->nr_charclass
)
617 assert (! "unknown class in class definition: should not happen");
619 ctype
->class_done
|= BIT (tok
);
621 ctype
->current_class_mask
= 1 << cnt
;
622 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
627 ctype_class_from (struct linereader
*lr
, struct localedef_t
*locale
,
628 struct token
*code
, struct charset_t
*charset
)
630 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
633 value
= charset_find_value (charset
, code
->val
.str
.start
, code
->val
.str
.len
);
635 ctype
->last_class_char
= value
;
637 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
638 /* In the LC_CTYPE category it is no error when a character is
639 not found. This has to be ignored silently. */
642 *find_idx (ctype
, &ctype
->class_collection
, &ctype
->class_collection_max
,
643 &ctype
->class_collection_act
, value
)
644 |= ctype
->current_class_mask
;
649 ctype_class_to (struct linereader
*lr
, struct localedef_t
*locale
,
650 struct token
*code
, struct charset_t
*charset
)
652 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
653 unsigned int value
, cnt
;
655 value
= charset_find_value (charset
, code
->val
.str
.start
, code
->val
.str
.len
);
657 assert (value
>= ctype
->last_class_char
);
659 for (cnt
= ctype
->last_class_char
+ 1; cnt
<= value
; ++cnt
)
660 *find_idx (ctype
, &ctype
->class_collection
, &ctype
->class_collection_max
,
661 &ctype
->class_collection_act
, cnt
)
662 |= ctype
->current_class_mask
;
664 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
669 ctype_class_end (struct linereader
*lr
, struct localedef_t
*locale
)
671 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
673 /* We have no special actions to perform here. */
674 ctype
->current_class_mask
= 0;
675 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
679 /* Character map handling. */
681 ctype_map_new (struct linereader
*lr
, struct localedef_t
*locale
,
682 enum token_t tok
, struct token
*code
,
683 struct charset_t
*charset
)
685 ctype_map_newP (lr
, locale
->categories
[LC_CTYPE
].ctype
,
686 code
->val
.str
.start
, charset
);
691 ctype_is_charconv (struct linereader
*lr
, struct localedef_t
*locale
,
694 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
697 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
)
698 if (strcmp (name
, ctype
->mapnames
[cnt
]) == 0)
706 ctype_map_start (struct linereader
*lr
, struct localedef_t
*locale
,
707 enum token_t tok
, const char *name
, struct charset_t
*charset
)
709 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
715 ctype
->toupper_done
= 1;
719 ctype
->tolower_done
= 1;
725 assert (! "unknown token in category `LC_CTYPE' should not happen");
728 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
)
729 if (strcmp (name
, ctype
->mapnames
[cnt
]) == 0)
732 if (cnt
== ctype
->map_collection_nr
)
733 assert (! "unknown token in category `LC_CTYPE' should not happen");
735 ctype
->last_map_idx
= cnt
;
736 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
741 ctype_map_from (struct linereader
*lr
, struct localedef_t
*locale
,
742 struct token
*code
, struct charset_t
*charset
)
744 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
747 value
= charset_find_value (charset
, code
->val
.str
.start
, code
->val
.str
.len
);
749 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
750 /* In the LC_CTYPE category it is no error when a character is
751 not found. This has to be ignored silently. */
754 assert (ctype
->last_map_idx
< ctype
->map_collection_nr
);
756 ctype
->from_map_char
= value
;
761 ctype_map_to (struct linereader
*lr
, struct localedef_t
*locale
,
762 struct token
*code
, struct charset_t
*charset
)
764 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
767 value
= charset_find_value (charset
, code
->val
.str
.start
, code
->val
.str
.len
);
769 if ((wchar_t) ctype
->from_map_char
== ILLEGAL_CHAR_VALUE
770 || (wchar_t) value
== ILLEGAL_CHAR_VALUE
)
772 /* In the LC_CTYPE category it is no error when a character is
773 not found. This has to be ignored silently. */
774 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
778 *find_idx (ctype
, &ctype
->map_collection
[ctype
->last_map_idx
],
779 &ctype
->map_collection_max
[ctype
->last_map_idx
],
780 &ctype
->map_collection_act
[ctype
->last_map_idx
],
781 ctype
->from_map_char
) = value
;
783 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
788 ctype_map_end (struct linereader
*lr
, struct localedef_t
*locale
)
790 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
792 ctype
->last_map_idx
= MAX_NR_CHARMAP
;
793 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
797 /* Local functions. */
799 ctype_class_newP (struct linereader
*lr
, struct locale_ctype_t
*ctype
,
804 for (cnt
= 0; cnt
< ctype
->nr_charclass
; ++cnt
)
805 if (strcmp (ctype
->classnames
[cnt
], name
) == 0)
808 if (cnt
< ctype
->nr_charclass
)
810 lr_error (lr
, _("character class `%s' already defined"), name
);
814 if (ctype
->nr_charclass
== MAX_NR_CHARCLASS
)
815 /* Exit code 2 is prescribed in P1003.2b. */
817 implementation limit: no more than %d character classes allowed"),
820 ctype
->classnames
[ctype
->nr_charclass
++] = name
;
825 ctype_map_newP (struct linereader
*lr
, struct locale_ctype_t
*ctype
,
826 const char *name
, struct charset_t
*charset
)
828 size_t max_chars
= 0;
831 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
)
833 if (strcmp (ctype
->mapnames
[cnt
], name
) == 0)
836 if (max_chars
< ctype
->map_collection_max
[cnt
])
837 max_chars
= ctype
->map_collection_max
[cnt
];
840 if (cnt
< ctype
->map_collection_nr
)
842 lr_error (lr
, _("character map `%s' already defined"), name
);
846 if (ctype
->map_collection_nr
== MAX_NR_CHARMAP
)
847 /* Exit code 2 is prescribed in P1003.2b. */
849 implementation limit: no more than %d character maps allowed"),
852 ctype
->mapnames
[cnt
] = name
;
855 ctype
->map_collection_max
[cnt
] = charset
->mb_cur_max
== 1 ? 256 : 512;
857 ctype
->map_collection_max
[cnt
] = max_chars
;
859 ctype
->map_collection
[cnt
] = (u_int32_t
*)
860 xmalloc (sizeof (u_int32_t
) * ctype
->map_collection_max
[cnt
]);
861 memset (ctype
->map_collection
[cnt
], '\0',
862 sizeof (u_int32_t
) * ctype
->map_collection_max
[cnt
]);
863 ctype
->map_collection_act
[cnt
] = 256;
865 ++ctype
->map_collection_nr
;
869 /* We have to be prepared that TABLE, MAX, and ACT can be NULL. This
870 is possible if we only want ot extend the name array. */
872 find_idx (struct locale_ctype_t
*ctype
, u_int32_t
**table
, size_t *max
,
873 size_t *act
, unsigned int idx
)
878 return table
== NULL
? NULL
: &(*table
)[idx
];
880 for (cnt
= 256; cnt
< ctype
->charnames_act
; ++cnt
)
881 if (ctype
->charnames
[cnt
] == idx
)
884 /* We have to distinguish two cases: the names is found or not. */
885 if (cnt
== ctype
->charnames_act
)
887 /* Extend the name array. */
888 if (ctype
->charnames_act
== ctype
->charnames_max
)
890 ctype
->charnames_max
*= 2;
891 ctype
->charnames
= (unsigned int *)
892 xrealloc (ctype
->charnames
,
893 sizeof (unsigned int) * ctype
->charnames_max
);
895 ctype
->charnames
[ctype
->charnames_act
++] = idx
;
899 /* We have done everything we are asked to do. */
906 size_t old_max
= *max
;
912 (u_int32_t
*) xrealloc (*table
, *max
* sizeof (unsigned long int));
913 memset (&(*table
)[old_max
], '\0',
914 (*max
- old_max
) * sizeof (u_int32_t
));
921 return &(*table
)[cnt
];
926 set_class_defaults (struct locale_ctype_t
*ctype
, struct charset_t
*charset
)
928 /* These function defines the default values for the classes and conversions
929 according to POSIX.2 2.5.2.1.
930 It may seem that the order of these if-blocks is arbitrary but it is NOT.
931 Don't move them unless you know what you do! */
933 void set_default (int bit
, int from
, int to
)
940 for (ch
= from
; ch
<= to
; ++ch
)
945 value
= charset_find_value (charset
, tmp
, 1);
946 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
949 character `%s' not defined while needed as default value"),
954 ELEM (ctype
, class_collection
, , value
) |= bit
;
958 /* Set default values if keyword was not present. */
959 if ((ctype
->class_done
& BIT (tok_upper
)) == 0)
960 /* "If this keyword [lower] is not specified, the lowercase letters
961 `A' through `Z', ..., shall automatically belong to this class,
962 with implementation defined character values." [P1003.2, 2.5.2.1] */
963 set_default (BIT (tok_upper
), 'A', 'Z');
965 if ((ctype
->class_done
& BIT (tok_lower
)) == 0)
966 /* "If this keyword [lower] is not specified, the lowercase letters
967 `a' through `z', ..., shall automatically belong to this class,
968 with implementation defined character values." [P1003.2, 2.5.2.1] */
969 set_default (BIT (tok_lower
), 'a', 'z');
971 if ((ctype
->class_done
& BIT (tok_alpha
)) == 0)
973 /* Table 2-6 in P1003.2 says that characters in class `upper' or
974 class `lower' *must* be in class `alpha'. */
975 unsigned long int mask
= BIT (tok_upper
) | BIT (tok_lower
);
978 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
979 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
980 ctype
->class_collection
[cnt
] |= BIT (tok_alpha
);
983 if ((ctype
->class_done
& BIT (tok_digit
)) == 0)
984 /* "If this keyword [digit] is not specified, the digits `0' through
985 `9', ..., shall automatically belong to this class, with
986 implementation-defined character values." [P1003.2, 2.5.2.1] */
987 set_default (BIT (tok_digit
), '0', '9');
989 /* "Only characters specified for the `alpha' and `digit' keyword
990 shall be specified. Characters specified for the keyword `alpha'
991 and `digit' are automatically included in this class. */
993 unsigned long int mask
= BIT (tok_alpha
) | BIT (tok_digit
);
996 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
997 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
998 ctype
->class_collection
[cnt
] |= BIT (tok_alnum
);
1001 if ((ctype
->class_done
& BIT (tok_space
)) == 0)
1002 /* "If this keyword [space] is not specified, the characters <space>,
1003 <form-feed>, <newline>, <carriage-return>, <tab>, and
1004 <vertical-tab>, ..., shall automatically belong to this class,
1005 with implementation-defined character values." [P1003.2, 2.5.2.1] */
1009 value
= charset_find_value (charset
, "space", 5);
1010 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1012 character `%s' not defined while needed as default value"),
1015 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1017 value
= charset_find_value (charset
, "form-feed", 9);
1018 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1020 character `%s' not defined while needed as default value"),
1023 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1025 value
= charset_find_value (charset
, "newline", 7);
1026 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1028 character `%s' not defined while needed as default value"),
1031 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1033 value
= charset_find_value (charset
, "carriage-return", 15);
1034 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1036 character `%s' not defined while needed as default value"),
1037 "<carriage-return>");
1039 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1041 value
= charset_find_value (charset
, "tab", 3);
1042 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1044 character `%s' not defined while needed as default value"),
1047 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1049 value
= charset_find_value (charset
, "vertical-tab", 12);
1050 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1052 character `%s' not defined while needed as default value"),
1055 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1058 if ((ctype
->class_done
& BIT (tok_xdigit
)) == 0)
1059 /* "If this keyword is not specified, the digits `0' to `9', the
1060 uppercase letters `A' through `F', and the lowercase letters `a'
1061 through `f', ..., shell automatically belong to this class, with
1062 implementation defined character values." [P1003.2, 2.5.2.1] */
1064 set_default (BIT (tok_xdigit
), '0', '9');
1065 set_default (BIT (tok_xdigit
), 'A', 'F');
1066 set_default (BIT (tok_xdigit
), 'a', 'f');
1069 if ((ctype
->class_done
& BIT (tok_blank
)) == 0)
1070 /* "If this keyword [blank] is unspecified, the characters <space> and
1071 <tab> shall belong to this character class." [P1003.2, 2.5.2.1] */
1075 value
= charset_find_value (charset
, "space", 5);
1076 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1078 character `%s' not defined while needed as default value"),
1081 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_blank
);
1083 value
= charset_find_value (charset
, "tab", 3);
1084 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1086 character `%s' not defined while needed as default value"),
1089 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_blank
);
1092 if ((ctype
->class_done
& BIT (tok_graph
)) == 0)
1093 /* "If this keyword [graph] is not specified, characters specified for
1094 the keywords `upper', `lower', `alpha', `digit', `xdigit' and `punct',
1095 shall belong to this character class." [P1003.2, 2.5.2.1] */
1097 unsigned long int mask
= BIT (tok_upper
) | BIT (tok_lower
) |
1098 BIT (tok_alpha
) | BIT (tok_digit
) | BIT (tok_xdigit
) | BIT (tok_punct
);
1101 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
1102 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
1103 ctype
->class_collection
[cnt
] |= BIT (tok_graph
);
1106 if ((ctype
->class_done
& BIT (tok_print
)) == 0)
1107 /* "If this keyword [print] is not provided, characters specified for
1108 the keywords `upper', `lower', `alpha', `digit', `xdigit', `punct',
1109 and the <space> character shall belong to this character class."
1110 [P1003.2, 2.5.2.1] */
1112 unsigned long int mask
= BIT (tok_upper
) | BIT (tok_lower
) |
1113 BIT (tok_alpha
) | BIT (tok_digit
) | BIT (tok_xdigit
) | BIT (tok_punct
);
1117 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
1118 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
1119 ctype
->class_collection
[cnt
] |= BIT (tok_print
);
1121 space
= charset_find_value (charset
, "space", 5);
1122 if (space
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1124 character `%s' not defined while needed as default value"),
1127 ELEM (ctype
, class_collection
, , space
) |= BIT (tok_print
);
1130 if (ctype
->toupper_done
== 0)
1131 /* "If this keyword [toupper] is not specified, the lowercase letters
1132 `a' through `z', and their corresponding uppercase letters `A' to
1133 `Z', ..., shall automatically be included, with implementation-
1134 defined character values." [P1003.2, 2.5.2.1] */
1139 strcpy (tmp
, "<?>");
1141 for (ch
= 'a'; ch
<= 'z'; ++ch
)
1143 unsigned int value_from
, value_to
;
1147 value_from
= charset_find_value (charset
, &tmp
[1], 1);
1148 if ((wchar_t) value_from
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1151 character `%s' not defined while needed as default value"),
1156 /* This conversion is implementation defined. */
1157 tmp
[1] = (char) (ch
+ ('A' - 'a'));
1158 value_to
= charset_find_value (charset
, &tmp
[1], 1);
1159 if ((wchar_t) value_to
== ILLEGAL_CHAR_VALUE
&& !be_quiet
)
1162 character `%s' not defined while needed as default value"),
1167 /* The index [0] is determined by the order of the
1168 `ctype_map_newP' calls in `ctype_startup'. */
1169 ELEM (ctype
, map_collection
, [0], value_from
) = value_to
;
1173 if (ctype
->tolower_done
== 0)
1174 /* "If this keyword [tolower] is not specified, the mapping shall be
1175 the reverse mapping of the one specified to `toupper'." [P1003.2] */
1179 for (cnt
= 0; cnt
< ctype
->map_collection_act
[0]; ++cnt
)
1180 if (ctype
->map_collection
[0][cnt
] != 0)
1181 ELEM (ctype
, map_collection
, [1],
1182 ctype
->map_collection
[0][cnt
])
1183 = ctype
->charnames
[cnt
];
1189 allocate_arrays (struct locale_ctype_t
*ctype
, struct charset_t
*charset
)
1193 /* First we have to decide how we organize the arrays. It is easy
1194 for a one-byte character set. But multi-byte character set
1195 cannot be stored flat because the chars might be sparsely used.
1196 So we determine an optimal hashing function for the used
1199 We use a very trivial hashing function to store the sparse
1200 table. CH % TABSIZE is used as an index. To solve multiple hits
1201 we have N planes. This guarantees a fixed search time for a
1202 character [N / 2]. In the following code we determine the minmum
1203 value for TABSIZE * N, where TABSIZE >= 256. */
1204 size_t min_total
= UINT_MAX
;
1205 size_t act_size
= 256;
1209 Computing table size for character classes might take a while..."),
1212 while (act_size
< min_total
)
1214 size_t cnt
[act_size
];
1215 size_t act_planes
= 1;
1217 memset (cnt
, '\0', sizeof cnt
);
1219 for (idx
= 0; idx
< 256; ++idx
)
1222 for (idx
= 0; idx
< ctype
->charnames_act
; ++idx
)
1223 if (ctype
->charnames
[idx
] >= 256)
1225 size_t nr
= ctype
->charnames
[idx
] % act_size
;
1227 if (++cnt
[nr
] > act_planes
)
1229 act_planes
= cnt
[nr
];
1230 if (act_size
* act_planes
>= min_total
)
1235 if (act_size
* act_planes
< min_total
)
1237 min_total
= act_size
* act_planes
;
1238 ctype
->plane_size
= act_size
;
1239 ctype
->plane_cnt
= act_planes
;
1246 fputs (_(" done\n"), stderr
);
1249 #if __BYTE_ORDER == __LITTLE_ENDIAN
1250 # define NAMES_B1 ctype->names_el
1251 # define NAMES_B2 ctype->names_eb
1253 # define NAMES_B1 ctype->names_eb
1254 # define NAMES_B2 ctype->names_el
1257 ctype
->names_eb
= (u_int32_t
*) xcalloc (ctype
->plane_size
1259 sizeof (u_int32_t
));
1260 ctype
->names_el
= (u_int32_t
*) xcalloc (ctype
->plane_size
1262 sizeof (u_int32_t
));
1264 for (idx
= 1; idx
< 256; ++idx
)
1265 NAMES_B1
[idx
] = idx
;
1267 /* Trick: change the 0th entry's name to 1 to mark the cell occupied. */
1270 for (idx
= 256; idx
< ctype
->charnames_act
; ++idx
)
1272 size_t nr
= (ctype
->charnames
[idx
] % ctype
->plane_size
);
1275 while (NAMES_B1
[nr
+ depth
* ctype
->plane_size
])
1277 assert (depth
< ctype
->plane_cnt
);
1279 NAMES_B1
[nr
+ depth
* ctype
->plane_size
] = ctype
->charnames
[idx
];
1281 /* Now for faster access remember the index in the NAMES_B array. */
1282 ctype
->charnames
[idx
] = nr
+ depth
* ctype
->plane_size
;
1286 for (idx
= 0; idx
< ctype
->plane_size
* ctype
->plane_cnt
; ++idx
)
1287 NAMES_B2
[idx
] = SWAPU32 (NAMES_B1
[idx
]);
1290 /* You wonder about this amount of memory? This is only because some
1291 users do not manage to address the array with unsigned values or
1292 data types with range >= 256. '\200' would result in the array
1293 index -128. To help these poor people we duplicate the entries for
1294 128 up to 255 below the entry for \0. */
1295 ctype
->ctype_b
= (char_class_t
*) xcalloc (256 + 128,
1296 sizeof (char_class_t
));
1297 ctype
->ctype32_b
= (char_class32_t
*) xcalloc (ctype
->plane_size
1299 sizeof (char_class32_t
));
1301 /* Fill in the character class information. */
1302 #if __BYTE_ORDER == __LITTLE_ENDIAN
1303 # define TRANS(w) CHAR_CLASS_TRANS (w)
1304 # define TRANS32(w) CHAR_CLASS32_TRANS (w)
1306 # define TRANS(w) (w)
1307 # define TRANS32(w) (w)
1310 for (idx
= 0; idx
< ctype
->class_collection_act
; ++idx
)
1311 if (ctype
->charnames
[idx
] < 256)
1312 ctype
->ctype_b
[128 + ctype
->charnames
[idx
]]
1313 = TRANS (ctype
->class_collection
[idx
]);
1315 /* Mirror first 127 entries. We must take care that entry -1 is not
1316 mirrored because EOF == -1. */
1317 for (idx
= 0; idx
< 127; ++idx
)
1318 ctype
->ctype_b
[idx
] = ctype
->ctype_b
[256 + idx
];
1320 /* The 32 bit array contains all characters. */
1321 for (idx
= 0; idx
< ctype
->class_collection_act
; ++idx
)
1322 ctype
->ctype32_b
[ctype
->charnames
[idx
]]
1323 = TRANS32 (ctype
->class_collection
[idx
]);
1325 /* Room for table of mappings. */
1326 ctype
->map_eb
= (u_int32_t
**) xmalloc (ctype
->map_collection_nr
1327 * sizeof (u_int32_t
*));
1328 ctype
->map_el
= (u_int32_t
**) xmalloc (ctype
->map_collection_nr
1329 * sizeof (u_int32_t
*));
1331 /* Fill in all mappings. */
1332 for (idx
= 0; idx
< ctype
->map_collection_nr
; ++idx
)
1336 /* Allocate table. */
1337 ctype
->map_eb
[idx
] = (u_int32_t
*) xmalloc ((ctype
->plane_size
1338 * ctype
->plane_cnt
+ 128)
1339 * sizeof (u_int32_t
));
1340 ctype
->map_el
[idx
] = (u_int32_t
*) xmalloc ((ctype
->plane_size
1341 * ctype
->plane_cnt
+ 128)
1342 * sizeof (u_int32_t
));
1344 #if __BYTE_ORDER == __LITTLE_ENDIAN
1345 # define MAP_B1 ctype->map_el
1346 # define MAP_B2 ctype->map_eb
1348 # define MAP_B1 ctype->map_eb
1349 # define MAP_B2 ctype->map_el
1352 /* Copy default value (identity mapping). */
1353 memcpy (&MAP_B1
[idx
][128], NAMES_B1
,
1354 ctype
->plane_size
* ctype
->plane_cnt
* sizeof (u_int32_t
));
1356 /* Copy values from collection. */
1357 for (idx2
= 0; idx2
< ctype
->map_collection_act
[idx
]; ++idx2
)
1358 if (ctype
->map_collection
[idx
][idx2
] != 0)
1359 MAP_B1
[idx
][128 + ctype
->charnames
[idx2
]] =
1360 ctype
->map_collection
[idx
][idx2
];
1362 /* Mirror first 127 entries. We must take care not to map entry
1363 -1 because EOF == -1. */
1364 for (idx2
= 0; idx2
< 127; ++idx2
)
1365 MAP_B1
[idx
][idx2
] = MAP_B1
[idx
][256 + idx2
];
1367 /* EOF must map to EOF. */
1368 MAP_B1
[idx
][127] = EOF
;
1370 /* And now the other byte order. */
1371 for (idx2
= 0; idx2
< ctype
->plane_size
* ctype
->plane_cnt
+ 128; ++idx2
)
1372 MAP_B2
[idx
][idx2
] = SWAPU32 (MAP_B1
[idx
][idx2
]);
1375 /* Extra array for class and map names. */
1376 ctype
->class_name_ptr
= (u_int32_t
*) xmalloc (ctype
->nr_charclass
1377 * sizeof (u_int32_t
));
1378 ctype
->map_name_ptr
= (u_int32_t
*) xmalloc (ctype
->map_collection_nr
1379 * sizeof (u_int32_t
));
1381 /* Array for width information. Because the expected width are very
1382 small we use only one single byte. This save space and we need
1383 not provide the information twice with both endianesses. */
1384 ctype
->width
= (unsigned char *) xmalloc (ctype
->plane_size
1385 * ctype
->plane_cnt
);
1386 /* Initialize with default width value. */
1387 memset (ctype
->width
, charset
->width_default
,
1388 ctype
->plane_size
* ctype
->plane_cnt
);
1389 if (charset
->width_rules
!= NULL
)
1393 for (cnt
= 0; cnt
< charset
->nwidth_rules
; ++cnt
)
1394 if (charset
->width_rules
[cnt
].width
!= charset
->width_default
)
1395 for (idx
= charset
->width_rules
[cnt
].from
;
1396 idx
<= charset
->width_rules
[cnt
].to
; ++idx
)
1398 size_t nr
= idx
% ctype
->plane_size
;
1401 while (NAMES_B1
[nr
+ depth
* ctype
->plane_size
] != nr
)
1403 assert (depth
< ctype
->plane_cnt
);
1405 ctype
->width
[nr
+ depth
* ctype
->plane_size
]
1406 = charset
->width_rules
[cnt
].width
;
1410 /* Compute MB_CUR_MAX. Please note the value mb_cur_max in the
1411 character set definition gives the number of bytes in the wide
1412 character representation. We compute the number of bytes used
1413 for the UTF-8 encoded form. */
1414 ctype
->mb_cur_max
= ((int []) { 2, 3, 5, 6 }) [charset
->mb_cur_max
- 1];
1416 /* We need the name of the currently used 8-bit character set to
1417 make correct conversion between this 8-bit representation and the
1418 ISO 10646 character set used internally for wide characters. */
1419 ctype
->codeset_name
= charset
->code_set_name
;