Mon Jun 5 04:02:26 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[glibc.git] / locale / ctype.c
blob1ce09bab2b45901e211f4c96087836a3389c48d0
1 /* Copyright (C) 1995 Free Software Foundation, Inc.
3 The GNU C Library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public License as
5 published by the Free Software Foundation; either version 2 of the
6 License, or (at your option) any later version.
8 The GNU C Library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public
14 License along with the GNU C Library; see the file COPYING.LIB. If
15 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
16 Cambridge, MA 02139, USA. */
18 #include <alloca.h>
19 #include <fcntl.h>
20 #include <libintl.h>
21 #include <locale.h>
22 #include <localeinfo.h>
23 #include <langinfo.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <netinet/in.h>
27 #include <sys/uio.h>
29 #include "localedef.h"
30 #include "token.h"
32 /* Arrays representing ctype tables. They must be initialized for the
33 right size to hold the full charmap. */
34 static u16 *ctype_b;
35 static i32 *names_b, *toupper_b, *tolower_b;
37 /* For accessing the element of the (possibly sparse) array we use this
38 macro. */
39 #define ELEM(arr, idx) \
40 (arr)[({ int h = idx % charmap_data.hash_size; \
41 int n = 0; \
42 while (n < charmap_data.hash_layers \
43 && names_b[n * charmap_data.hash_size + h] != idx) \
44 ++n; \
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. */
71 void
72 ctype_input (int token)
74 char *ptr;
75 int len;
77 /* If necessary allocate arrays. */
78 allocate_arrays ();
80 while (token != TOK_END)
82 switch (token)
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);
92 int was_ell = 0;
93 int last = -1;
95 if ((class_done & bit) != 0)
97 char tmp[len + 1];
98 memcpy (tmp, ptr, len);
99 tmp[len] = '\0';
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);
105 class_done |= bit;
109 token = xlocfile_lex (&ptr, &len);
111 if (token == TOK_ENDOFLINE)
113 SYNTAX_ERROR;
114 break;
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);
123 break;
125 was_ell = 1;
126 continue;
129 if (token != TOK_CHAR)
131 if (token != TOK_ILL_CHAR)
132 SYNTAX_ERROR;
133 was_ell = 0;
134 last = -1;
135 continue;
138 if (len < 0 || !valid_char (len))
140 was_ell = 0;
141 last = -1;
142 continue;
145 /* We have found a valid character. Include it to
146 the class' bit set. */
147 if (was_ell == 0)
149 ELEM (ctype_b, len) |= bit;
150 last = len;
152 else
154 int i;
156 if (last > len)
158 error (0, 0, gettext ("%s:%Zd: lower bound of "
159 "ellipsis not smaller"),
160 locfile_data.filename, locfile_data.line_no);
161 was_ell = 0;
162 last = -1;
163 continue;
166 for (i = last + 1; i <= len; ++i)
167 ELEM (ctype_b, i) |= bit;
169 last = -1;
171 was_ell = 0;
173 while ((token = locfile_lex (&ptr, &len)) == TOK_CHAR
174 && len == ';');
176 /* Rest of the line should be empty. */
177 ignore_to_eol (token, 0);
179 break;
180 case TOK_TOUPPER: case TOK_TOLOWER:
182 int from;
183 int to = -1;
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);
195 int ignore;
197 token = xlocfile_lex (&ptr, &len);
198 if (token != TOK_CHAR || len != '(')
200 SYNTAX_ERROR;
201 break;
204 token = xlocfile_lex (&ptr, &len);
205 if (token != TOK_CHAR && token != TOK_ILL_CHAR)
207 SYNTAX_ERROR;
208 break;
210 from = len;
211 ignore = token == TOK_ILL_CHAR;
213 token = xlocfile_lex (&ptr, &len);
214 if (token != TOK_CHAR || len != ',')
216 SYNTAX_ERROR;
217 break;
220 token = xlocfile_lex (&ptr, &len);
221 if (token != TOK_CHAR && token != TOK_ILL_CHAR)
223 SYNTAX_ERROR;
224 break;
226 to = len;
227 ignore |= token == TOK_ILL_CHAR;
229 token = xlocfile_lex (&ptr, &len);
230 if (token != TOK_CHAR || len != ')')
232 SYNTAX_ERROR;
233 break;
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
241 && len == ';');
243 /* Rest of the line should be empty. */
244 ignore_to_eol (token, 1);
246 break;
247 default:
248 SYNTAX_ERROR;
249 ignore_to_eol (0, 0);
250 break;
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);
266 else
267 ignore_to_eol (0, posix_conformance);
271 void
272 ctype_check(void)
274 /* Here are a lot of things to check. See POSIX.2, table 2-6. */
275 #define NCLASS 11
276 static const struct
278 const char *name;
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;
298 u16 tmp;
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)
307 continue;
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])
317 case 'M':
318 if (!eq)
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);
322 break;
323 case 'X':
324 if (eq)
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);
328 break;
329 case 'D':
330 ELEM (ctype_b, names_b[ch]) |= 1 << cls2;
331 break;
332 default:
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);
354 else
355 ELEM (ctype_b, space_char) |= BIT (TOK_PRINT);
359 /* These macros can change little to big endian and vice versa. */
360 #define SWAP16(v) \
361 ((u16) (((((unsigned short) (v)) & 0x00ff) << 8) \
362 | ((((unsigned short) (v)) & 0xff00) >> 8)))
363 #define SWAP32(v) \
364 ((u32) (((((u32) (v)) & 0x000000ff) << 24) \
365 | ((((u32) (v)) & 0x0000ff00) << 8) \
366 | ((((u32) (v)) & 0x00ff0000) >> 8) \
367 | ((((u32) (v)) & 0xff000000) >> 24)))
371 ctype_output (void)
373 char *path, *t;
374 int ch;
375 /* File descriptor for output file. */
376 int fd;
377 /* Magic number. */
378 i32 magic = LIMAGIC (LC_CTYPE);
379 /* Number of table. */
380 int tables = 6;
381 /* Number ints in leading information table. */
382 #if 0
383 i32 n = 2 + 2 * tables;
384 #else
385 i32 n = 5;
386 #endif
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. */
396 i32 pos[14] =
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. */
403 #if 0
404 4 * (2 + n),
405 1 + 4 * (2 + n),
406 2 + 4 * (2 + n),
407 2 + 4 * (3 + n),
408 2 + 4 * (4 + n),
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),
418 #else
419 4 * (2 + n),
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)),
424 #endif
426 /* Parameter to writev. */
427 struct iovec iov[11] =
429 { &magic, sizeof (i32) },
430 { &n, sizeof (i32) },
431 #if 0
432 { pos, sizeof (pos) },
433 { &mb_cur_min, 1 },
434 { &mb_cur_max, 1 },
435 { &hash_size, sizeof (i32) },
436 { &hash_layers, sizeof (i32) },
437 #else
438 { pos, 5 * 4 },
439 #endif
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) }
445 int result = 0;
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. */
455 ctype_b[-1] = 0;
456 toupper_b[-1] = -1;
457 tolower_b[-1] = -1;
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);
470 if (fd == -1)
472 error (0, 0, gettext ("cannot open output file `%s': %m"), path);
473 result = 1;
475 else
477 int idx;
479 #if 0
480 if (writev (fd, iov, 10) == -1)
481 #else
482 if (writev (fd, iov, 6) == -1)
483 #endif
485 error (0, 0, gettext ("cannot write output file `%s': %m"), path);
486 result = 1;
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]);
497 if (idx >= 0)
498 names_b[idx] = SWAP32 (names_b[idx]);
501 #if 0
502 if (writev (fd, iov + 5, 6) == -1)
503 #else
504 if (writev (fd, iov + 3, 2) == -1)
505 #endif
507 error (0, 0, gettext ("cannot write output file `%s': %m"), path);
508 result = 1;
511 close_and_return:
512 close (fd);
515 return result;
519 /* If necessary allocate the memory for the arrays according to the
520 current character map. */
521 static void
522 allocate_arrays (void)
524 /* Init ctype data structures. */
525 if (ctype_b == NULL)
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. */
533 int ch, h, n;
534 char *ptr;
535 int size = charmap_data.hash_size * charmap_data.hash_layers;
537 ctype_b = (u16 *) xcalloc (size - (-128), sizeof (u16));
538 ctype_b += 128;
541 names_b = (i32 *) xcalloc (size, sizeof (i32));
543 toupper_b = (i32 *) xcalloc ((size - (-128)), sizeof (i32));
544 toupper_b += 128;
546 tolower_b = (i32 *) xcalloc ((size - (-128)), sizeof (i32));
547 tolower_b += 128;
549 ptr = NULL;
550 /* Mark the place of the NUL character as occupied. */
551 names_b[0] = 1;
553 while (iterate_table (&charmap_data.table, (void **) &ptr,
554 (void **) &ch))
556 /* We already handled the NUL character. */
557 if (ch == 0)
558 continue;
560 h = ch % charmap_data.hash_size;
561 n = 0;
562 while (names_b[h + n * charmap_data.hash_size] != 0)
563 ++n;
565 names_b[h + n * charmap_data.hash_size] = ch;
566 toupper_b[h + n * charmap_data.hash_size] = ch;
567 tolower_b[h + n * charmap_data.hash_size] = ch;
569 /* Correct the value for NUL character. */
570 names_b[0] = 0;
574 static void
575 set_class_defaults (void)
577 /* These function defines the default values for the classes and conversions
578 according to POSIX.2 2.5.2.1.
579 It may seem that the order of these if-blocks is arbitrary but it is NOT.
580 Don't move them unless you know what you do! */
582 void set_default (int bit, int from, int to)
584 char tmp[4];
585 int ch;
586 /* Define string. */
587 strcpy (tmp, "<?>");
589 for (ch = from; ch <= to; ++ch)
591 int code;
592 tmp[1] = ch;
594 code = find_char (tmp + 1, 1);
595 if (code == -1)
596 error (5, 0, gettext ("character `%s' not defined while needed "
597 "as default value"), tmp);
598 ELEM (ctype_b, code) |= bit;
602 /* If necessary allocate arrays. */
603 allocate_arrays ();
605 /* Set default values if keyword was not present. */
606 if ((class_done & BIT (TOK_UPPER)) == 0)
607 /* "If this keyword [lower] is not specified, the lowercase letters
608 `A' through `Z', ..., shall automatically belong to this class,
609 with implementation defined character values." */
610 set_default (BIT (TOK_UPPER), 'A', 'Z');
612 if ((class_done & BIT (TOK_LOWER)) == 0)
613 /* "If this keyword [lower] is not specified, the lowercase letters
614 `a' through `z', ..., shall automatically belong to this class,
615 with implementation defined character values." */
616 set_default (BIT (TOK_LOWER), 'a', 'z');
618 if ((class_done & BIT (TOK_DIGIT)) == 0)
619 /* "If this keyword [digit] is not specified, the digits `0' through
620 `9', ..., shall automatically belong to this class, with
621 implementation-defined character values." */
622 set_default (BIT (TOK_DIGIT), '0', '9');
624 if ((class_done & BIT (TOK_SPACE)) == 0)
625 /* "If this keyword [space] is not specified, the characters <space>,
626 <form-feed>, <newline>, <carriage-return>, <tab>, and
627 <vertical-tab>, ..., shall automatically belong to this class,
628 with implementtation-defined character values." */
630 int code;
632 code = find_char ("space", 5);
633 if (code == -1)
634 error (5, 0, gettext ("character `%s' not defined while needed as "
635 "default value"), "<space>");
636 ELEM (ctype_b, code) |= BIT (TOK_SPACE);
638 code = find_char ("form-feed", 9);
639 if (code == -1)
640 error (5, 0, gettext ("character `%s' not defined while needed as "
641 "default value"), "<form-feed>");
642 ELEM (ctype_b, code) |= BIT (TOK_SPACE);
644 code = find_char ("newline", 7);
645 if (code == -1)
646 error (5, 0, gettext ("character `%s' not defined while needed as "
647 "default value"), "<newline>");
648 ELEM (ctype_b, code) |= BIT (TOK_SPACE);
650 code = find_char ("carriage-return", 15);
651 if (code == -1)
652 error (5, 0, gettext ("character `%s' not defined while needed as "
653 "default value"), "<carriage-return>");
654 ELEM (ctype_b, code) |= BIT (TOK_SPACE);
656 code = find_char ("tab", 3);
657 if (code == -1)
658 error (5, 0, gettext ("character `%s' not defined while needed as "
659 "default value"), "<tab>");
660 ELEM (ctype_b, code) |= BIT (TOK_SPACE);
662 code = find_char ("vertical-tab", 11);
663 if (code == -1)
664 error (5, 0, gettext ("character `%s' not defined while needed as "
665 "default value"), "<vertical-tab>");
666 ELEM (ctype_b, code) |= BIT (TOK_SPACE);
669 if ((class_done & BIT (TOK_XDIGIT)) == 0)
670 /* "If this keyword is not specified, the digits `0' to `9', the
671 uppercase letters `A' through `F', and the lowercase letters `a'
672 through `f', ..., shell automatically belong to this class, with
673 implementation defined character values." */
675 if ((class_done & BIT (TOK_XDIGIT)) == 0)
676 set_default (BIT (TOK_XDIGIT), '0', '9');
678 if ((class_done & BIT (TOK_XDIGIT)) == 0)
679 set_default (BIT (TOK_XDIGIT), 'A', 'F');
681 if ((class_done & BIT (TOK_XDIGIT)) == 0)
682 set_default (BIT (TOK_XDIGIT), 'a', 'f');
685 if ((class_done & BIT (TOK_BLANK)) == 0)
686 /* "If this keyword [blank] is unspecified, the characters <space> and
687 <tab> shall belong to this character class." */
689 int code;
691 code = find_char ("space", 5);
692 if (code == -1)
693 error (5, 0, gettext ("character `%s' not defined while needed as "
694 "default value"), "<space>");
695 ELEM (ctype_b, code) |= BIT (TOK_BLANK);
697 code = find_char ("tab", 3);
698 if (code == -1)
699 error (5, 0, gettext ("character `%s' not defined while needed as "
700 "default value"), "<tab>");
701 ELEM (ctype_b, code) |= BIT (TOK_BLANK);
704 if ((class_done & BIT (TOK_GRAPH)) == 0)
705 /* "If this keyword [graph] is not specified, characters specified for
706 the keywords `upper', `lower', `alpha', `digit', `xdigit' and `punct',
707 shall belong to this character class." */
709 int ch;
710 unsigned short int mask = BIT (TOK_UPPER) | BIT (TOK_LOWER) |
711 BIT (TOK_ALPHA) | BIT (TOK_DIGIT) | BIT (TOK_XDIGIT) | BIT (TOK_PUNCT);
713 for (ch = 0; ch < charmap_data.hash_size * charmap_data.hash_layers;
714 ++ch)
716 if (ch != 0 && names_b[ch] == 0)
717 continue;
718 if ((ELEM (ctype_b, names_b[ch]) & mask) != 0)
719 ELEM (ctype_b, names_b[ch]) |= BIT (TOK_GRAPH);
723 if ((class_done & BIT (TOK_PRINT)) == 0)
724 /* "If this keyword [print] is not provided, characters specified for
725 the keywords `upper', `lower', `alpha', `digit', `xdigit', `punct',
726 and the <space> character shall belong to this character class." */
728 int ch;
729 int space = find_char ("space", 5);
730 unsigned short int mask = BIT (TOK_UPPER) | BIT (TOK_LOWER) |
731 BIT (TOK_ALPHA) | BIT (TOK_DIGIT) | BIT (TOK_XDIGIT) | BIT (TOK_PUNCT);
733 if (space == -1)
734 error (5, 0, gettext ("character `%s' not defined while needed as "
735 "default value"), "<space>");
737 for (ch = 0; ch < charmap_data.hash_size * charmap_data.hash_layers;
738 ++ch)
740 if (ch != 0 && names_b[ch] == 0)
741 continue;
742 if ((ELEM (ctype_b, names_b[ch]) & mask) != 0)
743 ELEM (ctype_b, names_b[ch]) |= BIT (TOK_PRINT);
745 ELEM (ctype_b, space) |= BIT (TOK_PRINT);
748 if (toupper_done == 0)
749 /* "If this keyword [toupper] is not spcified, the lowercase letters
750 `a' through `z', and their corresponding uppercase letters `A' to
751 `Z', ..., shall automatically be included, with implementation-
752 defined character values." */
754 char tmp[4];
755 int ch;
757 strcpy (tmp, "<?>");
759 for (ch = 'a'; ch <= 'z'; ++ch)
761 int code_to, code_from;
763 tmp[1] = ch;
764 code_from = find_char (tmp + 1, 1);
765 if (code_from == -1)
766 error (5, 0, gettext ("character `%s' not defined while needed "
767 "as default value"), tmp);
769 /* This conversion is implementation defined. */
770 tmp[1] = ch + ('A' - 'a');
771 code_to = find_char (tmp + 1, 1);
772 if (code_to == -1)
773 error (5, 0, gettext ("character `%s' not defined while needed "
774 "as default value"), tmp);
776 ELEM (toupper_b, code_from) = code_to;
780 if (tolower_done == 0)
781 /* "If this keyword [tolower] is not specified, the mapping shall be
782 the reverse mapping of the one specified to `toupper'." */
784 int ch;
786 for (ch = 0; ch < charmap_data.hash_size * charmap_data.hash_layers;
787 ++ch)
789 if (ch != 0 && names_b[ch] == 0)
790 continue;
792 if (toupper_b[ch] != names_b[ch])
793 ELEM (tolower_b, toupper_b[ch]) = names_b[ch];
799 /* Test whether the given character is valid for the current charmap. */
800 static int
801 valid_char (int ch)
803 /* FIXME: this assumes 32-bit integers. */
804 int ok = ch >= 0
805 && (charmap_data.mb_cur_max < 4
806 ? ch < 1 << (8 * charmap_data.mb_cur_max) : 1);
808 return ok;
813 * Local Variables:
814 * mode:c
815 * c-basic-offset:2
816 * End: