]>
git.ipfire.org Git - thirdparty/glibc.git/blob - locale/programs/ld-ctype.c
1 /* Copyright (C) 1995, 1996, 1997, 1998 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 /* To be compatible with former implementations we for now restrict
61 the number of bits for character classes to 16. When compatibility
62 is not necessary anymore increase the number to 32. */
63 #define char_class_t u_int16_t
64 #define CHAR_CLASS_TRANS SWAPU16
65 #define char_class32_t u_int32_t
66 #define CHAR_CLASS32_TRANS SWAPU32
69 /* The real definition of the struct for the LC_CTYPE locale. */
72 unsigned int *charnames
;
76 /* We will allow up to 8 * sizeof(u_int32_t) - 1 character classes. */
77 #define MAX_NR_CHARCLASS (8 * sizeof (u_int32_t) - 1)
79 const char *classnames
[MAX_NR_CHARCLASS
];
80 unsigned long int current_class_mask
;
81 unsigned int last_class_char
;
82 u_int32_t
*class_collection
;
83 size_t class_collection_max
;
84 size_t class_collection_act
;
85 unsigned long int class_done
;
87 /* If the following number ever turns out to be too small simply
88 increase it. But I doubt it will. --drepper@gnu */
89 #define MAX_NR_CHARMAP 16
90 const char *mapnames
[MAX_NR_CHARMAP
];
91 u_int32_t
*map_collection
[MAX_NR_CHARMAP
];
92 size_t map_collection_max
[MAX_NR_CHARMAP
];
93 size_t map_collection_act
[MAX_NR_CHARMAP
];
94 size_t map_collection_nr
;
96 unsigned int from_map_char
;
100 /* The arrays for the binary representation. */
101 u_int32_t plane_size
;
103 char_class_t
*ctype_b
;
104 char_class32_t
*ctype32_b
;
109 u_int32_t
*class_name_ptr
;
110 u_int32_t
*map_name_ptr
;
111 unsigned char *width
;
112 u_int32_t mb_cur_max
;
113 const char *codeset_name
;
117 /* Prototypes for local functions. */
118 static void ctype_class_newP (struct linereader
*lr
,
119 struct locale_ctype_t
*ctype
, const char *name
);
120 static void ctype_map_newP (struct linereader
*lr
,
121 struct locale_ctype_t
*ctype
,
122 const char *name
, struct charset_t
*charset
);
123 static u_int32_t
*find_idx (struct locale_ctype_t
*ctype
, u_int32_t
**table
,
124 size_t *max
, size_t *act
, unsigned int idx
);
125 static void set_class_defaults (struct locale_ctype_t
*ctype
,
126 struct charset_t
*charset
);
127 static void allocate_arrays (struct locale_ctype_t
*ctype
,
128 struct charset_t
*charset
);
132 ctype_startup (struct linereader
*lr
, struct localedef_t
*locale
,
133 struct charset_t
*charset
)
136 struct locale_ctype_t
*ctype
;
138 /* It is important that we always use UCS1 encoding for strings now. */
139 encoding_method
= ENC_UCS1
;
141 /* Allocate the needed room. */
142 locale
->categories
[LC_CTYPE
].ctype
= ctype
=
143 (struct locale_ctype_t
*) xmalloc (sizeof (struct locale_ctype_t
));
145 /* We have no names seen yet. */
146 ctype
->charnames_max
= charset
->mb_cur_max
== 1 ? 256 : 512;
148 (unsigned int *) xmalloc (ctype
->charnames_max
* sizeof (unsigned int));
149 for (cnt
= 0; cnt
< 256; ++cnt
)
150 ctype
->charnames
[cnt
] = cnt
;
151 ctype
->charnames_act
= 256;
153 /* Fill character class information. */
154 ctype
->nr_charclass
= 0;
155 ctype
->current_class_mask
= 0;
156 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
157 /* The order of the following instructions determines the bit
159 ctype_class_newP (lr
, ctype
, "upper");
160 ctype_class_newP (lr
, ctype
, "lower");
161 ctype_class_newP (lr
, ctype
, "alpha");
162 ctype_class_newP (lr
, ctype
, "digit");
163 ctype_class_newP (lr
, ctype
, "xdigit");
164 ctype_class_newP (lr
, ctype
, "space");
165 ctype_class_newP (lr
, ctype
, "print");
166 ctype_class_newP (lr
, ctype
, "graph");
167 ctype_class_newP (lr
, ctype
, "blank");
168 ctype_class_newP (lr
, ctype
, "cntrl");
169 ctype_class_newP (lr
, ctype
, "punct");
170 ctype_class_newP (lr
, ctype
, "alnum");
172 ctype
->class_collection_max
= charset
->mb_cur_max
== 1 ? 256 : 512;
173 ctype
->class_collection
174 = (u_int32_t
*) xmalloc (sizeof (unsigned long int)
175 * ctype
->class_collection_max
);
176 memset (ctype
->class_collection
, '\0',
177 sizeof (unsigned long int) * ctype
->class_collection_max
);
178 ctype
->class_collection_act
= 256;
180 /* Fill character map information. */
181 ctype
->map_collection_nr
= 0;
182 ctype
->last_map_idx
= MAX_NR_CHARMAP
;
183 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
184 ctype_map_newP (lr
, ctype
, "toupper", charset
);
185 ctype_map_newP (lr
, ctype
, "tolower", charset
);
187 /* Fill first 256 entries in `toupper' and `tolower' arrays. */
188 for (cnt
= 0; cnt
< 256; ++cnt
)
190 ctype
->map_collection
[0][cnt
] = cnt
;
191 ctype
->map_collection
[1][cnt
] = cnt
;
197 ctype_finish (struct localedef_t
*locale
, struct charset_t
*charset
)
199 /* See POSIX.2, table 2-6 for the meaning of the following table. */
204 const char allow
[NCLASS
];
206 valid_table
[NCLASS
] =
208 /* The order is important. See token.h for more information.
209 M = Always, D = Default, - = Permitted, X = Mutually exclusive */
210 { "upper", "--MX-XDDXXX-" },
211 { "lower", "--MX-XDDXXX-" },
212 { "alpha", "---X-XDDXXX-" },
213 { "digit", "XXX--XDDXXX-" },
214 { "xdigit", "-----XDDXXX-" },
215 { "space", "XXXXX------X" },
216 { "print", "---------X--" },
217 { "graph", "---------X--" },
218 { "blank", "XXXXXM-----X" },
219 { "cntrl", "XXXXX-XX--XX" },
220 { "punct", "XXXXX-DD-X-X" },
221 { "alnum", "-----XDDXXX-" }
225 unsigned int space_value
;
226 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
228 /* Set default value for classes not specified. */
229 set_class_defaults (ctype
, charset
);
231 /* Check according to table. */
232 for (cnt
= 0; cnt
< ctype
->class_collection_max
; ++cnt
)
234 unsigned long int tmp
;
236 tmp
= ctype
->class_collection
[cnt
];
240 for (cls1
= 0; cls1
< NCLASS
; ++cls1
)
241 if ((tmp
& (1 << cls1
)) != 0)
242 for (cls2
= 0; cls2
< NCLASS
; ++cls2
)
243 if (valid_table
[cls1
].allow
[cls2
] != '-')
245 int eq
= (tmp
& (1 << cls2
)) != 0;
246 switch (valid_table
[cls1
].allow
[cls2
])
255 value
= ctype
->charnames
[cnt
];
257 if ((value
& 0xff000000) != 0)
258 cp
+= sprintf (cp
, "\\%o", (value
>> 24) & 0xff);
259 if ((value
& 0xffff0000) != 0)
260 cp
+= sprintf (cp
, "\\%o", (value
>> 16) & 0xff);
261 if ((value
& 0xffffff00) != 0)
262 cp
+= sprintf (cp
, "\\%o", (value
>> 8) & 0xff);
263 sprintf (cp
, "\\%o", value
& 0xff);
267 character %s'%s' in class `%s' must be in class `%s'"), value
> 256 ? "L" : "",
268 cp
, valid_table
[cls1
].name
,
269 valid_table
[cls2
].name
);
280 value
= ctype
->charnames
[cnt
];
282 if ((value
& 0xff000000) != 0)
283 cp
+= sprintf (cp
, "\\%o", value
>> 24);
284 if ((value
& 0xffff0000) != 0)
285 cp
+= sprintf (cp
, "\\%o", (value
>> 16) & 0xff);
286 if ((value
& 0xffffff00) != 0)
287 cp
+= sprintf (cp
, "\\%o", (value
>> 8) & 0xff);
288 sprintf (cp
, "\\%o", value
& 0xff);
292 character %s'%s' in class `%s' must not be in class `%s'"),
293 value
> 256 ? "L" : "", cp
,
294 valid_table
[cls1
].name
,
295 valid_table
[cls2
].name
);
300 ctype
->class_collection
[cnt
] |= 1 << cls2
;
304 error (5, 0, _("internal error in %s, line %u"),
305 __FUNCTION__
, __LINE__
);
310 /* ... and now test <SP> as a special case. */
311 space_value
= charset_find_value (&charset
->char_table
, "SP", 2);
312 if ((wchar_t) space_value
== ILLEGAL_CHAR_VALUE
)
315 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)))
325 error (0, 0, _("<SP> character not in class `%s'"),
326 valid_table
[cnt
].name
);
328 else if (((cnt
= BITPOS (tok_punct
),
329 (ELEM (ctype
, class_collection
, , space_value
)
330 & BIT (tok_punct
)) != 0)
331 || (cnt
= BITPOS (tok_graph
),
332 (ELEM (ctype
, class_collection
, , space_value
)
337 error (0, 0, _("<SP> character must not be in class `%s'"),
338 valid_table
[cnt
].name
);
341 ELEM (ctype
, class_collection
, , space_value
) |= BIT (tok_print
);
343 /* Now that the tests are done make sure the name array contains all
344 characters which are handled in the WIDTH section of the
345 character set definition file. */
346 if (charset
->width_rules
!= NULL
)
347 for (cnt
= 0; cnt
< charset
->nwidth_rules
; ++cnt
)
350 for (inner
= charset
->width_rules
[cnt
].from
;
351 inner
<= charset
->width_rules
[cnt
].to
; ++inner
)
352 (void) find_idx (ctype
, NULL
, NULL
, NULL
, inner
);
358 ctype_output (struct localedef_t
*locale
, struct charset_t
*charset
,
359 const char *output_path
)
361 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
362 const size_t nelems
= (_NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
)
363 + 2 * (ctype
->map_collection_nr
- 2));
364 struct iovec iov
[2 + nelems
+ ctype
->nr_charclass
365 + ctype
->map_collection_nr
];
366 struct locale_file data
;
367 u_int32_t idx
[nelems
];
368 size_t elem
, cnt
, offset
, total
;
371 if ((locale
->binary
& (1 << LC_CTYPE
)) != 0)
373 iov
[0].iov_base
= ctype
;
374 iov
[0].iov_len
= locale
->len
[LC_CTYPE
];
376 write_locale_data (output_path
, "LC_CTYPE", 1, iov
);
382 /* Now prepare the output: Find the sizes of the table we can use. */
383 allocate_arrays (ctype
, charset
);
385 data
.magic
= LIMAGIC (LC_CTYPE
);
387 iov
[0].iov_base
= (void *) &data
;
388 iov
[0].iov_len
= sizeof (data
);
390 iov
[1].iov_base
= (void *) idx
;
391 iov
[1].iov_len
= sizeof (idx
);
393 idx
[0] = iov
[0].iov_len
+ iov
[1].iov_len
;
396 for (elem
= 0; elem
< nelems
; ++elem
)
398 if (elem
< _NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
))
401 #define CTYPE_DATA(name, base, len) \
402 case _NL_ITEM_INDEX (name): \
403 iov[2 + elem + offset].iov_base = (base); \
404 iov[2 + elem + offset].iov_len = (len); \
405 if (elem + 1 < nelems) \
406 idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len; \
409 CTYPE_DATA (_NL_CTYPE_CLASS
,
411 (256 + 128) * sizeof (char_class_t
));
413 CTYPE_DATA (_NL_CTYPE_TOUPPER_EB
,
415 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
416 * sizeof (u_int32_t
));
417 CTYPE_DATA (_NL_CTYPE_TOLOWER_EB
,
419 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
420 * sizeof (u_int32_t
));
422 CTYPE_DATA (_NL_CTYPE_TOUPPER_EL
,
424 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
425 * sizeof (u_int32_t
));
426 CTYPE_DATA (_NL_CTYPE_TOLOWER_EL
,
428 (ctype
->plane_size
* ctype
->plane_cnt
+ 128)
429 * sizeof (u_int32_t
));
431 CTYPE_DATA (_NL_CTYPE_CLASS32
,
433 (ctype
->plane_size
* ctype
->plane_cnt
434 * sizeof (char_class32_t
)));
436 CTYPE_DATA (_NL_CTYPE_NAMES_EB
,
437 ctype
->names_eb
, (ctype
->plane_size
* ctype
->plane_cnt
438 * sizeof (u_int32_t
)));
439 CTYPE_DATA (_NL_CTYPE_NAMES_EL
,
440 ctype
->names_el
, (ctype
->plane_size
* ctype
->plane_cnt
441 * sizeof (u_int32_t
)));
443 CTYPE_DATA (_NL_CTYPE_HASH_SIZE
,
444 &ctype
->plane_size
, sizeof (u_int32_t
));
445 CTYPE_DATA (_NL_CTYPE_HASH_LAYERS
,
446 &ctype
->plane_cnt
, sizeof (u_int32_t
));
448 case _NL_ITEM_INDEX (_NL_CTYPE_CLASS_NAMES
):
449 /* The class name array. */
451 for (cnt
= 0; cnt
< ctype
->nr_charclass
; ++cnt
, ++offset
)
453 iov
[2 + elem
+ offset
].iov_base
454 = (void *) ctype
->classnames
[cnt
];
455 iov
[2 + elem
+ offset
].iov_len
456 = strlen (ctype
->classnames
[cnt
]) + 1;
457 total
+= iov
[2 + elem
+ offset
].iov_len
;
459 iov
[2 + elem
+ offset
].iov_base
= (void *) "\0\0\0";
460 iov
[2 + elem
+ offset
].iov_len
= 1 + (4 - ((total
+ 1) % 4));
461 total
+= 1 + (4 - ((total
+ 1) % 4));
463 if (elem
+ 1 < nelems
)
464 idx
[elem
+ 1] = idx
[elem
] + total
;
467 case _NL_ITEM_INDEX (_NL_CTYPE_MAP_NAMES
):
468 /* The class name array. */
470 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
, ++offset
)
472 iov
[2 + elem
+ offset
].iov_base
473 = (void *) ctype
->mapnames
[cnt
];
474 iov
[2 + elem
+ offset
].iov_len
475 = strlen (ctype
->mapnames
[cnt
]) + 1;
476 total
+= iov
[2 + elem
+ offset
].iov_len
;
478 iov
[2 + elem
+ offset
].iov_base
= (void *) "\0\0\0";
479 iov
[2 + elem
+ offset
].iov_len
= 1 + (4 - ((total
+ 1) % 4));
480 total
+= 1 + (4 - ((total
+ 1) % 4));
482 if (elem
+ 1 < nelems
)
483 idx
[elem
+ 1] = idx
[elem
] + total
;
486 CTYPE_DATA (_NL_CTYPE_WIDTH
,
487 ctype
->width
, ctype
->plane_size
* ctype
->plane_cnt
);
489 CTYPE_DATA (_NL_CTYPE_MB_CUR_MAX
,
490 &ctype
->mb_cur_max
, sizeof (u_int32_t
));
492 case _NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME
):
493 total
= strlen (ctype
->codeset_name
) + 1;
495 iov
[2 + elem
+ offset
].iov_base
= (char *) ctype
->codeset_name
;
498 iov
[2 + elem
+ offset
].iov_base
= alloca ((total
+ 3) & ~3);
499 memset (mempcpy (iov
[2 + elem
+ offset
].iov_base
,
500 ctype
->codeset_name
, total
),
501 '\0', 4 - (total
& 3));
502 total
= (total
+ 3) & ~3;
504 iov
[2 + elem
+ offset
].iov_len
= total
;
505 if (elem
+ 1 < nelems
)
506 idx
[elem
+ 1] = idx
[elem
] + iov
[2 + elem
+ offset
].iov_len
;
510 assert (! "unknown CTYPE element");
514 /* Handle extra maps. */
515 size_t nr
= (elem
- _NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
)) >> 1;
517 if (((elem
- _NL_ITEM_INDEX (_NL_NUM_LC_CTYPE
)) & 1) == 0)
518 iov
[2 + elem
+ offset
].iov_base
= ctype
->map_eb
[nr
];
520 iov
[2 + elem
+ offset
].iov_base
= ctype
->map_el
[nr
];
522 iov
[2 + elem
+ offset
].iov_len
= ((ctype
->plane_size
523 * ctype
->plane_cnt
+ 128)
524 * sizeof (u_int32_t
));
526 if (elem
+ 1 < nelems
)
527 idx
[elem
+ 1] = idx
[elem
] + iov
[2 + elem
+ offset
].iov_len
;
531 assert (2 + elem
+ offset
== (nelems
+ ctype
->nr_charclass
532 + ctype
->map_collection_nr
+ 2));
534 write_locale_data (output_path
, "LC_CTYPE", 2 + elem
+ offset
, iov
);
538 /* Character class handling. */
540 ctype_class_new (struct linereader
*lr
, struct localedef_t
*locale
,
541 enum token_t tok
, struct token
*code
,
542 struct charset_t
*charset
)
544 ctype_class_newP (lr
, locale
->categories
[LC_CTYPE
].ctype
,
545 code
->val
.str
.start
);
550 ctype_is_charclass (struct linereader
*lr
, struct localedef_t
*locale
,
555 for (cnt
= 0; cnt
< locale
->categories
[LC_CTYPE
].ctype
->nr_charclass
; ++cnt
)
556 if (strcmp (name
, locale
->categories
[LC_CTYPE
].ctype
->classnames
[cnt
])
565 ctype_class_start (struct linereader
*lr
, struct localedef_t
*locale
,
566 enum token_t tok
, const char *str
,
567 struct charset_t
*charset
)
569 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
613 assert (! "illegal token as class name: should not happen");
616 for (cnt
= 0; cnt
< ctype
->nr_charclass
; ++cnt
)
617 if (strcmp (str
, ctype
->classnames
[cnt
]) == 0)
620 if (cnt
>= ctype
->nr_charclass
)
621 assert (! "unknown class in class definition: should not happen");
623 ctype
->class_done
|= BIT (tok
);
625 ctype
->current_class_mask
= 1 << cnt
;
626 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
631 ctype_class_from (struct linereader
*lr
, struct localedef_t
*locale
,
632 struct token
*code
, struct charset_t
*charset
)
634 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
637 value
= charset_find_value (&charset
->char_table
, code
->val
.str
.start
,
640 ctype
->last_class_char
= value
;
642 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
643 /* In the LC_CTYPE category it is no error when a character is
644 not found. This has to be ignored silently. */
647 *find_idx (ctype
, &ctype
->class_collection
, &ctype
->class_collection_max
,
648 &ctype
->class_collection_act
, value
)
649 |= ctype
->current_class_mask
;
654 ctype_class_to (struct linereader
*lr
, struct localedef_t
*locale
,
655 struct token
*code
, struct charset_t
*charset
)
657 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
658 unsigned int value
, cnt
;
660 value
= charset_find_value (&charset
->char_table
, code
->val
.str
.start
,
663 /* In the LC_CTYPE category it is no error when a character is
664 not found. This has to be ignored silently. */
665 if ((wchar_t) ctype
->last_class_char
!= ILLEGAL_CHAR_VALUE
666 && (wchar_t) value
!= ILLEGAL_CHAR_VALUE
)
667 for (cnt
= ctype
->last_class_char
+ 1; cnt
<= value
; ++cnt
)
668 *find_idx (ctype
, &ctype
->class_collection
, &ctype
->class_collection_max
,
669 &ctype
->class_collection_act
, cnt
)
670 |= ctype
->current_class_mask
;
672 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
677 ctype_class_end (struct linereader
*lr
, struct localedef_t
*locale
)
679 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
681 /* We have no special actions to perform here. */
682 ctype
->current_class_mask
= 0;
683 ctype
->last_class_char
= ILLEGAL_CHAR_VALUE
;
687 /* Character map handling. */
689 ctype_map_new (struct linereader
*lr
, struct localedef_t
*locale
,
690 enum token_t tok
, struct token
*code
,
691 struct charset_t
*charset
)
693 ctype_map_newP (lr
, locale
->categories
[LC_CTYPE
].ctype
,
694 code
->val
.str
.start
, charset
);
699 ctype_is_charconv (struct linereader
*lr
, struct localedef_t
*locale
,
702 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
705 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
)
706 if (strcmp (name
, ctype
->mapnames
[cnt
]) == 0)
714 ctype_map_start (struct linereader
*lr
, struct localedef_t
*locale
,
715 enum token_t tok
, const char *name
, struct charset_t
*charset
)
717 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
723 ctype
->toupper_done
= 1;
727 ctype
->tolower_done
= 1;
733 assert (! "unknown token in category `LC_CTYPE' should not happen");
736 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
)
737 if (strcmp (name
, ctype
->mapnames
[cnt
]) == 0)
740 if (cnt
== ctype
->map_collection_nr
)
741 assert (! "unknown token in category `LC_CTYPE' should not happen");
743 ctype
->last_map_idx
= cnt
;
744 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
749 ctype_map_from (struct linereader
*lr
, struct localedef_t
*locale
,
750 struct token
*code
, struct charset_t
*charset
)
752 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
755 value
= charset_find_value (&charset
->char_table
, code
->val
.str
.start
,
758 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
759 /* In the LC_CTYPE category it is no error when a character is
760 not found. This has to be ignored silently. */
763 assert (ctype
->last_map_idx
< ctype
->map_collection_nr
);
765 ctype
->from_map_char
= value
;
770 ctype_map_to (struct linereader
*lr
, struct localedef_t
*locale
,
771 struct token
*code
, struct charset_t
*charset
)
773 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
776 value
= charset_find_value (&charset
->char_table
, code
->val
.str
.start
,
779 if ((wchar_t) ctype
->from_map_char
== ILLEGAL_CHAR_VALUE
780 || (wchar_t) value
== ILLEGAL_CHAR_VALUE
)
782 /* In the LC_CTYPE category it is no error when a character is
783 not found. This has to be ignored silently. */
784 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
788 *find_idx (ctype
, &ctype
->map_collection
[ctype
->last_map_idx
],
789 &ctype
->map_collection_max
[ctype
->last_map_idx
],
790 &ctype
->map_collection_act
[ctype
->last_map_idx
],
791 ctype
->from_map_char
) = value
;
793 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
798 ctype_map_end (struct linereader
*lr
, struct localedef_t
*locale
)
800 struct locale_ctype_t
*ctype
= locale
->categories
[LC_CTYPE
].ctype
;
802 ctype
->last_map_idx
= MAX_NR_CHARMAP
;
803 ctype
->from_map_char
= ILLEGAL_CHAR_VALUE
;
807 /* Local functions. */
809 ctype_class_newP (struct linereader
*lr
, struct locale_ctype_t
*ctype
,
814 for (cnt
= 0; cnt
< ctype
->nr_charclass
; ++cnt
)
815 if (strcmp (ctype
->classnames
[cnt
], name
) == 0)
818 if (cnt
< ctype
->nr_charclass
)
820 lr_error (lr
, _("character class `%s' already defined"), name
);
824 if (ctype
->nr_charclass
== MAX_NR_CHARCLASS
)
825 /* Exit code 2 is prescribed in P1003.2b. */
827 implementation limit: no more than %d character classes allowed"),
830 ctype
->classnames
[ctype
->nr_charclass
++] = name
;
835 ctype_map_newP (struct linereader
*lr
, struct locale_ctype_t
*ctype
,
836 const char *name
, struct charset_t
*charset
)
838 size_t max_chars
= 0;
841 for (cnt
= 0; cnt
< ctype
->map_collection_nr
; ++cnt
)
843 if (strcmp (ctype
->mapnames
[cnt
], name
) == 0)
846 if (max_chars
< ctype
->map_collection_max
[cnt
])
847 max_chars
= ctype
->map_collection_max
[cnt
];
850 if (cnt
< ctype
->map_collection_nr
)
852 lr_error (lr
, _("character map `%s' already defined"), name
);
856 if (ctype
->map_collection_nr
== MAX_NR_CHARMAP
)
857 /* Exit code 2 is prescribed in P1003.2b. */
859 implementation limit: no more than %d character maps allowed"),
862 ctype
->mapnames
[cnt
] = name
;
865 ctype
->map_collection_max
[cnt
] = charset
->mb_cur_max
== 1 ? 256 : 512;
867 ctype
->map_collection_max
[cnt
] = max_chars
;
869 ctype
->map_collection
[cnt
] = (u_int32_t
*)
870 xmalloc (sizeof (u_int32_t
) * ctype
->map_collection_max
[cnt
]);
871 memset (ctype
->map_collection
[cnt
], '\0',
872 sizeof (u_int32_t
) * ctype
->map_collection_max
[cnt
]);
873 ctype
->map_collection_act
[cnt
] = 256;
875 ++ctype
->map_collection_nr
;
879 /* We have to be prepared that TABLE, MAX, and ACT can be NULL. This
880 is possible if we only want ot extend the name array. */
882 find_idx (struct locale_ctype_t
*ctype
, u_int32_t
**table
, size_t *max
,
883 size_t *act
, unsigned int idx
)
888 return table
== NULL
? NULL
: &(*table
)[idx
];
890 for (cnt
= 256; cnt
< ctype
->charnames_act
; ++cnt
)
891 if (ctype
->charnames
[cnt
] == idx
)
894 /* We have to distinguish two cases: the names is found or not. */
895 if (cnt
== ctype
->charnames_act
)
897 /* Extend the name array. */
898 if (ctype
->charnames_act
== ctype
->charnames_max
)
900 ctype
->charnames_max
*= 2;
901 ctype
->charnames
= (unsigned int *)
902 xrealloc (ctype
->charnames
,
903 sizeof (unsigned int) * ctype
->charnames_max
);
905 ctype
->charnames
[ctype
->charnames_act
++] = idx
;
909 /* We have done everything we are asked to do. */
916 size_t old_max
= *max
;
922 (u_int32_t
*) xrealloc (*table
, *max
* sizeof (unsigned long int));
923 memset (&(*table
)[old_max
], '\0',
924 (*max
- old_max
) * sizeof (u_int32_t
));
931 return &(*table
)[cnt
];
936 set_class_defaults (struct locale_ctype_t
*ctype
, struct charset_t
*charset
)
938 /* These function defines the default values for the classes and conversions
939 according to POSIX.2 2.5.2.1.
940 It may seem that the order of these if-blocks is arbitrary but it is NOT.
941 Don't move them unless you know what you do! */
943 void set_default (int bit
, int from
, int to
)
950 for (ch
= from
; ch
<= to
; ++ch
)
955 value
= charset_find_value (&charset
->char_table
, tmp
, 1);
956 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
960 character `%s' not defined while needed as default value"),
965 ELEM (ctype
, class_collection
, , value
) |= bit
;
969 /* Set default values if keyword was not present. */
970 if ((ctype
->class_done
& BIT (tok_upper
)) == 0)
971 /* "If this keyword [lower] is not specified, the lowercase letters
972 `A' through `Z', ..., shall automatically belong to this class,
973 with implementation defined character values." [P1003.2, 2.5.2.1] */
974 set_default (BIT (tok_upper
), 'A', 'Z');
976 if ((ctype
->class_done
& BIT (tok_lower
)) == 0)
977 /* "If this keyword [lower] is not specified, the lowercase letters
978 `a' through `z', ..., shall automatically belong to this class,
979 with implementation defined character values." [P1003.2, 2.5.2.1] */
980 set_default (BIT (tok_lower
), 'a', 'z');
982 if ((ctype
->class_done
& BIT (tok_alpha
)) == 0)
984 /* Table 2-6 in P1003.2 says that characters in class `upper' or
985 class `lower' *must* be in class `alpha'. */
986 unsigned long int mask
= BIT (tok_upper
) | BIT (tok_lower
);
989 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
990 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
991 ctype
->class_collection
[cnt
] |= BIT (tok_alpha
);
994 if ((ctype
->class_done
& BIT (tok_digit
)) == 0)
995 /* "If this keyword [digit] is not specified, the digits `0' through
996 `9', ..., shall automatically belong to this class, with
997 implementation-defined character values." [P1003.2, 2.5.2.1] */
998 set_default (BIT (tok_digit
), '0', '9');
1000 /* "Only characters specified for the `alpha' and `digit' keyword
1001 shall be specified. Characters specified for the keyword `alpha'
1002 and `digit' are automatically included in this class. */
1004 unsigned long int mask
= BIT (tok_alpha
) | BIT (tok_digit
);
1007 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
1008 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
1009 ctype
->class_collection
[cnt
] |= BIT (tok_alnum
);
1012 if ((ctype
->class_done
& BIT (tok_space
)) == 0)
1013 /* "If this keyword [space] is not specified, the characters <space>,
1014 <form-feed>, <newline>, <carriage-return>, <tab>, and
1015 <vertical-tab>, ..., shall automatically belong to this class,
1016 with implementation-defined character values." [P1003.2, 2.5.2.1] */
1020 value
= charset_find_value (&charset
->char_table
, "space", 5);
1021 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1025 character `%s' not defined while needed as default value"),
1029 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1031 value
= charset_find_value (&charset
->char_table
, "form-feed", 9);
1032 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1036 character `%s' not defined while needed as default value"),
1040 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1042 value
= charset_find_value (&charset
->char_table
, "newline", 7);
1043 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1047 character `%s' not defined while needed as default value"),
1051 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1053 value
= charset_find_value (&charset
->char_table
, "carriage-return", 15);
1054 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1058 character `%s' not defined while needed as default value"),
1059 "<carriage-return>");
1062 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1064 value
= charset_find_value (&charset
->char_table
, "tab", 3);
1065 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1069 character `%s' not defined while needed as default value"),
1073 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1075 value
= charset_find_value (&charset
->char_table
, "vertical-tab", 12);
1076 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1080 character `%s' not defined while needed as default value"),
1084 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_space
);
1087 if ((ctype
->class_done
& BIT (tok_xdigit
)) == 0)
1088 /* "If this keyword is not specified, the digits `0' to `9', the
1089 uppercase letters `A' through `F', and the lowercase letters `a'
1090 through `f', ..., shell automatically belong to this class, with
1091 implementation defined character values." [P1003.2, 2.5.2.1] */
1093 set_default (BIT (tok_xdigit
), '0', '9');
1094 set_default (BIT (tok_xdigit
), 'A', 'F');
1095 set_default (BIT (tok_xdigit
), 'a', 'f');
1098 if ((ctype
->class_done
& BIT (tok_blank
)) == 0)
1099 /* "If this keyword [blank] is unspecified, the characters <space> and
1100 <tab> shall belong to this character class." [P1003.2, 2.5.2.1] */
1104 value
= charset_find_value (&charset
->char_table
, "space", 5);
1105 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1109 character `%s' not defined while needed as default value"),
1113 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_blank
);
1115 value
= charset_find_value (&charset
->char_table
, "tab", 3);
1116 if ((wchar_t) value
== ILLEGAL_CHAR_VALUE
)
1120 character `%s' not defined while needed as default value"),
1124 ELEM (ctype
, class_collection
, , value
) |= BIT (tok_blank
);
1127 if ((ctype
->class_done
& BIT (tok_graph
)) == 0)
1128 /* "If this keyword [graph] is not specified, characters specified for
1129 the keywords `upper', `lower', `alpha', `digit', `xdigit' and `punct',
1130 shall belong to this character class." [P1003.2, 2.5.2.1] */
1132 unsigned long int mask
= BIT (tok_upper
) | BIT (tok_lower
) |
1133 BIT (tok_alpha
) | BIT (tok_digit
) | BIT (tok_xdigit
) | BIT (tok_punct
);
1136 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
1137 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
1138 ctype
->class_collection
[cnt
] |= BIT (tok_graph
);
1141 if ((ctype
->class_done
& BIT (tok_print
)) == 0)
1142 /* "If this keyword [print] is not provided, characters specified for
1143 the keywords `upper', `lower', `alpha', `digit', `xdigit', `punct',
1144 and the <space> character shall belong to this character class."
1145 [P1003.2, 2.5.2.1] */
1147 unsigned long int mask
= BIT (tok_upper
) | BIT (tok_lower
) |
1148 BIT (tok_alpha
) | BIT (tok_digit
) | BIT (tok_xdigit
) | BIT (tok_punct
);
1152 for (cnt
= 0; cnt
< ctype
->class_collection_act
; ++cnt
)
1153 if ((ctype
->class_collection
[cnt
] & mask
) != 0)
1154 ctype
->class_collection
[cnt
] |= BIT (tok_print
);
1156 space
= charset_find_value (&charset
->char_table
, "space", 5);
1157 if (space
== ILLEGAL_CHAR_VALUE
)
1161 character `%s' not defined while needed as default value"),
1165 ELEM (ctype
, class_collection
, , space
) |= BIT (tok_print
);
1168 if (ctype
->toupper_done
== 0)
1169 /* "If this keyword [toupper] is not specified, the lowercase letters
1170 `a' through `z', and their corresponding uppercase letters `A' to
1171 `Z', ..., shall automatically be included, with implementation-
1172 defined character values." [P1003.2, 2.5.2.1] */
1177 strcpy (tmp
, "<?>");
1179 for (ch
= 'a'; ch
<= 'z'; ++ch
)
1181 unsigned int value_from
, value_to
;
1185 value_from
= charset_find_value (&charset
->char_table
, &tmp
[1], 1);
1186 if ((wchar_t) value_from
== ILLEGAL_CHAR_VALUE
)
1190 character `%s' not defined while needed as default value"),
1195 /* This conversion is implementation defined. */
1196 tmp
[1] = (char) (ch
+ ('A' - 'a'));
1197 value_to
= charset_find_value (&charset
->char_table
, &tmp
[1], 1);
1198 if ((wchar_t) value_to
== ILLEGAL_CHAR_VALUE
)
1202 character `%s' not defined while needed as default value"),
1207 /* The index [0] is determined by the order of the
1208 `ctype_map_newP' calls in `ctype_startup'. */
1209 ELEM (ctype
, map_collection
, [0], value_from
) = value_to
;
1213 if (ctype
->tolower_done
== 0)
1214 /* "If this keyword [tolower] is not specified, the mapping shall be
1215 the reverse mapping of the one specified to `toupper'." [P1003.2] */
1219 for (cnt
= 0; cnt
< ctype
->map_collection_act
[0]; ++cnt
)
1220 if (ctype
->map_collection
[0][cnt
] != 0)
1221 ELEM (ctype
, map_collection
, [1],
1222 ctype
->map_collection
[0][cnt
])
1223 = ctype
->charnames
[cnt
];
1229 allocate_arrays (struct locale_ctype_t
*ctype
, struct charset_t
*charset
)
1233 /* First we have to decide how we organize the arrays. It is easy
1234 for a one-byte character set. But multi-byte character set
1235 cannot be stored flat because the chars might be sparsely used.
1236 So we determine an optimal hashing function for the used
1239 We use a very trivial hashing function to store the sparse
1240 table. CH % TABSIZE is used as an index. To solve multiple hits
1241 we have N planes. This guarantees a fixed search time for a
1242 character [N / 2]. In the following code we determine the minmum
1243 value for TABSIZE * N, where TABSIZE >= 256. */
1244 size_t min_total
= UINT_MAX
;
1245 size_t act_size
= 256;
1249 Computing table size for character classes might take a while..."),
1252 while (act_size
< min_total
)
1254 size_t cnt
[act_size
];
1255 size_t act_planes
= 1;
1257 memset (cnt
, '\0', sizeof cnt
);
1259 for (idx
= 0; idx
< 256; ++idx
)
1262 for (idx
= 0; idx
< ctype
->charnames_act
; ++idx
)
1263 if (ctype
->charnames
[idx
] >= 256)
1265 size_t nr
= ctype
->charnames
[idx
] % act_size
;
1267 if (++cnt
[nr
] > act_planes
)
1269 act_planes
= cnt
[nr
];
1270 if (act_size
* act_planes
>= min_total
)
1275 if (act_size
* act_planes
< min_total
)
1277 min_total
= act_size
* act_planes
;
1278 ctype
->plane_size
= act_size
;
1279 ctype
->plane_cnt
= act_planes
;
1286 fputs (_(" done\n"), stderr
);
1289 #if __BYTE_ORDER == __LITTLE_ENDIAN
1290 # define NAMES_B1 ctype->names_el
1291 # define NAMES_B2 ctype->names_eb
1293 # define NAMES_B1 ctype->names_eb
1294 # define NAMES_B2 ctype->names_el
1297 ctype
->names_eb
= (u_int32_t
*) xcalloc (ctype
->plane_size
1299 sizeof (u_int32_t
));
1300 ctype
->names_el
= (u_int32_t
*) xcalloc (ctype
->plane_size
1302 sizeof (u_int32_t
));
1304 for (idx
= 1; idx
< 256; ++idx
)
1305 NAMES_B1
[idx
] = idx
;
1307 /* Trick: change the 0th entry's name to 1 to mark the cell occupied. */
1310 for (idx
= 256; idx
< ctype
->charnames_act
; ++idx
)
1312 size_t nr
= (ctype
->charnames
[idx
] % ctype
->plane_size
);
1315 while (NAMES_B1
[nr
+ depth
* ctype
->plane_size
])
1317 assert (depth
< ctype
->plane_cnt
);
1319 NAMES_B1
[nr
+ depth
* ctype
->plane_size
] = ctype
->charnames
[idx
];
1321 /* Now for faster access remember the index in the NAMES_B array. */
1322 ctype
->charnames
[idx
] = nr
+ depth
* ctype
->plane_size
;
1326 for (idx
= 0; idx
< ctype
->plane_size
* ctype
->plane_cnt
; ++idx
)
1327 NAMES_B2
[idx
] = SWAPU32 (NAMES_B1
[idx
]);
1330 /* You wonder about this amount of memory? This is only because some
1331 users do not manage to address the array with unsigned values or
1332 data types with range >= 256. '\200' would result in the array
1333 index -128. To help these poor people we duplicate the entries for
1334 128 up to 255 below the entry for \0. */
1335 ctype
->ctype_b
= (char_class_t
*) xcalloc (256 + 128,
1336 sizeof (char_class_t
));
1337 ctype
->ctype32_b
= (char_class32_t
*) xcalloc (ctype
->plane_size
1339 sizeof (char_class32_t
));
1341 /* Fill in the character class information. */
1342 #if __BYTE_ORDER == __LITTLE_ENDIAN
1343 # define TRANS(w) CHAR_CLASS_TRANS (w)
1344 # define TRANS32(w) CHAR_CLASS32_TRANS (w)
1346 # define TRANS(w) (w)
1347 # define TRANS32(w) (w)
1350 for (idx
= 0; idx
< ctype
->class_collection_act
; ++idx
)
1351 if (ctype
->charnames
[idx
] < 256)
1352 ctype
->ctype_b
[128 + ctype
->charnames
[idx
]]
1353 = TRANS (ctype
->class_collection
[idx
]);
1355 /* Mirror first 127 entries. We must take care that entry -1 is not
1356 mirrored because EOF == -1. */
1357 for (idx
= 0; idx
< 127; ++idx
)
1358 ctype
->ctype_b
[idx
] = ctype
->ctype_b
[256 + idx
];
1360 /* The 32 bit array contains all characters. */
1361 for (idx
= 0; idx
< ctype
->class_collection_act
; ++idx
)
1362 ctype
->ctype32_b
[ctype
->charnames
[idx
]]
1363 = TRANS32 (ctype
->class_collection
[idx
]);
1365 /* Room for table of mappings. */
1366 ctype
->map_eb
= (u_int32_t
**) xmalloc (ctype
->map_collection_nr
1367 * sizeof (u_int32_t
*));
1368 ctype
->map_el
= (u_int32_t
**) xmalloc (ctype
->map_collection_nr
1369 * sizeof (u_int32_t
*));
1371 /* Fill in all mappings. */
1372 for (idx
= 0; idx
< ctype
->map_collection_nr
; ++idx
)
1376 /* Allocate table. */
1377 ctype
->map_eb
[idx
] = (u_int32_t
*) xmalloc ((ctype
->plane_size
1378 * ctype
->plane_cnt
+ 128)
1379 * sizeof (u_int32_t
));
1380 ctype
->map_el
[idx
] = (u_int32_t
*) xmalloc ((ctype
->plane_size
1381 * ctype
->plane_cnt
+ 128)
1382 * sizeof (u_int32_t
));
1384 #if __BYTE_ORDER == __LITTLE_ENDIAN
1385 # define MAP_B1 ctype->map_el
1386 # define MAP_B2 ctype->map_eb
1388 # define MAP_B1 ctype->map_eb
1389 # define MAP_B2 ctype->map_el
1392 /* Copy default value (identity mapping). */
1393 memcpy (&MAP_B1
[idx
][128], NAMES_B1
,
1394 ctype
->plane_size
* ctype
->plane_cnt
* sizeof (u_int32_t
));
1396 /* Copy values from collection. */
1397 for (idx2
= 0; idx2
< ctype
->map_collection_act
[idx
]; ++idx2
)
1398 if (ctype
->map_collection
[idx
][idx2
] != 0)
1399 MAP_B1
[idx
][128 + ctype
->charnames
[idx2
]] =
1400 ctype
->map_collection
[idx
][idx2
];
1402 /* Mirror first 127 entries. We must take care not to map entry
1403 -1 because EOF == -1. */
1404 for (idx2
= 0; idx2
< 127; ++idx2
)
1405 MAP_B1
[idx
][idx2
] = MAP_B1
[idx
][256 + idx2
];
1407 /* EOF must map to EOF. */
1408 MAP_B1
[idx
][127] = EOF
;
1410 /* And now the other byte order. */
1411 for (idx2
= 0; idx2
< ctype
->plane_size
* ctype
->plane_cnt
+ 128; ++idx2
)
1412 MAP_B2
[idx
][idx2
] = SWAPU32 (MAP_B1
[idx
][idx2
]);
1415 /* Extra array for class and map names. */
1416 ctype
->class_name_ptr
= (u_int32_t
*) xmalloc (ctype
->nr_charclass
1417 * sizeof (u_int32_t
));
1418 ctype
->map_name_ptr
= (u_int32_t
*) xmalloc (ctype
->map_collection_nr
1419 * sizeof (u_int32_t
));
1421 /* Array for width information. Because the expected width are very
1422 small we use only one single byte. This save space and we need
1423 not provide the information twice with both endianesses. */
1424 ctype
->width
= (unsigned char *) xmalloc (ctype
->plane_size
1425 * ctype
->plane_cnt
);
1426 /* Initialize with default width value. */
1427 memset (ctype
->width
, charset
->width_default
,
1428 ctype
->plane_size
* ctype
->plane_cnt
);
1429 if (charset
->width_rules
!= NULL
)
1433 for (cnt
= 0; cnt
< charset
->nwidth_rules
; ++cnt
)
1434 if (charset
->width_rules
[cnt
].width
!= charset
->width_default
)
1435 for (idx
= charset
->width_rules
[cnt
].from
;
1436 idx
<= charset
->width_rules
[cnt
].to
; ++idx
)
1438 size_t nr
= idx
% ctype
->plane_size
;
1441 while (NAMES_B1
[nr
+ depth
* ctype
->plane_size
] != nr
)
1443 assert (depth
< ctype
->plane_cnt
);
1445 ctype
->width
[nr
+ depth
* ctype
->plane_size
]
1446 = charset
->width_rules
[cnt
].width
;
1450 /* Compute MB_CUR_MAX. Please note the value mb_cur_max in the
1451 character set definition gives the number of bytes in the wide
1452 character representation. We compute the number of bytes used
1453 for the UTF-8 encoded form. */
1454 ctype
->mb_cur_max
= ((int []) { 2, 3, 5, 6 }) [charset
->mb_cur_max
- 1];
1456 /* We need the name of the currently used 8-bit character set to
1457 make correct conversion between this 8-bit representation and the
1458 ISO 10646 character set used internally for wide characters. */
1459 ctype
->codeset_name
= charset
->code_set_name
;