ctype.c revision 6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * This file and its contents are supplied under the terms of the
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * You may only use this file in accordance with the terms version 1.0
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * of the CDDL.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * A full copy of the text of the CDDL should have accompanied this
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * source. A copy of the CDDL is also available via the Internet at
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * LC_CTYPE database generation routines for localedef.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoretypedef struct ctype_node {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorectype_compare(const void *n1, const void *n2)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return (c1->wc < c2->wc ? -1 : c1->wc > c2->wc ? 1 : 0);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore avl_create(&ctypes, ctype_compare, sizeof (ctype_node_t),
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISUPPER | _ISALPHA | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISLOWER | _ISALPHA | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISALPHA | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISDIGIT | _ISGRAPH | _ISPRINT | _ISXDIGIT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISPUNCT | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * We can't do anything with this. The character
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * should already be specified as a digit or alpha.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn = avl_find(&ctypes, &srch, &where)) == NULL) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn = calloc(1, sizeof (*ctn))) == NULL) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore errf(_("malformed character range (%u ... %u))"),
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore for (cur = last_ctype + 1; cur <= end; cur++) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctype_node_t *ctn, *last_ct, *last_lo, *last_up;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (void) memcpy(rl.magic, _FILE_RUNE_MAGIC_1, 8);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (void) strncpy(rl.encoding, get_wide_encoding(), sizeof (rl.encoding));
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore for (ctn = avl_first(&ctypes); ctn; ctn = AVL_NEXT(&ctypes, ctn)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * POSIX requires certain portable characters have
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * certain types. Add them if they are missing.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (strchr(" \f\n\r\t\v", (char)wc) != NULL)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (strchr("0123456789ABCDEFabcdef", (char)wc) != NULL)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * POSIX also requires that certain types imply
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * others. Add any inferred types here.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn->ctype & (_ISALPHA|_ISDIGIT|_ISXDIGIT))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * Finally, POSIX requires that certain combinations
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * are invalid. We don't flag this as a fatal error,
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * but we will warn about.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (ctn->ctype & (_ISDIGIT|_ISALPHA|_ISXDIGIT)))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn->ctype & _ISSPACE) && (ctn->ctype & _ISGRAPH))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((wc == ' ') && (ctn->ctype & (_ISPUNCT|_ISGRAPH)))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore warn("conflicting classes for character 0x%x (%x)",
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * Handle the lower 256 characters using the simple
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * optimization. Note that if we have not defined the
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * upper/lower case, then we identity map it.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore rl.maplower[wc] = ctn->tolower ? ctn->tolower : wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore rl.mapupper[wc] = ctn->toupper ? ctn->toupper : wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((last_ct != NULL) && (last_ct->ctype == ctn->ctype)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ct[rl.runetype_ext_nranges - 1].map = ctn->ctype;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore lo[rl.maplower_ext_nranges - 1].map = ctn->tolower;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore up[rl.mapupper_ext_nranges - 1].map = ctn->toupper;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((wr_category(&rl, sizeof (rl), f) < 0) ||
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (wr_category(ct, sizeof (*ct) * rl.runetype_ext_nranges, f) < 0) ||
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (wr_category(lo, sizeof (*lo) * rl.maplower_ext_nranges, f) < 0) ||
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (wr_category(up, sizeof (*up) * rl.mapupper_ext_nranges, f) < 0)) {