6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore/*
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.
5aec55eb0591d2fcdd38d7dd5408a6ff3456e596Garrett D'Amore * You may only use this file in accordance with the terms of version
5aec55eb0591d2fcdd38d7dd5408a6ff3456e596Garrett D'Amore * 1.0 of the CDDL.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore *
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 * http://www.illumos.org/license/CDDL.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore */
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore/*
017c01f878134ff71877f2c67cca171a4ad2cd93Yuri Pankov * Copyright 2010,2011 Nexenta Systems, Inc. All rights reserved.
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * Copyright 2013 DEY Storage Systems, Inc.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore */
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore/*
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * LC_CTYPE database generation routines for localedef.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore */
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <stdio.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <stdlib.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <string.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <sys/types.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <sys/avl.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <wchar.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <ctype.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <wctype.h>
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include <unistd.h>
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore#include "_ctype.h"
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include "localedef.h"
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include "parser.tab.h"
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore#include "runefile.h"
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorestatic avl_tree_t ctypes;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorestatic wchar_t last_ctype;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoretypedef struct ctype_node {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore wchar_t wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore int32_t ctype;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore int32_t toupper;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore int32_t tolower;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore avl_node_t avl;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore} ctype_node_t;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amoretypedef struct width_node {
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore wchar_t start;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore wchar_t end;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore int8_t width;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore avl_node_t avl;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore} width_node_t;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorestatic int
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorectype_compare(const void *n1, const void *n2)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore const ctype_node_t *c1 = n1;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore const ctype_node_t *c2 = n2;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return (c1->wc < c2->wc ? -1 : c1->wc > c2->wc ? 1 : 0);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorevoid
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoreinit_ctype(void)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore avl_create(&ctypes, ctype_compare, sizeof (ctype_node_t),
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore offsetof(ctype_node_t, avl));
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorestatic void
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoreadd_ctype_impl(ctype_node_t *ctn)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore switch (last_kw) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISUPPER:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISUPPER | _ISALPHA | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISLOWER:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISLOWER | _ISALPHA | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISALPHA:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISALPHA | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISDIGIT:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISDIGIT | _ISGRAPH | _ISPRINT | _ISXDIGIT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISSPACE:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISSPACE;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISCNTRL:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISCNTRL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISGRAPH:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISPRINT:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISPRINT;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISPUNCT:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISPUNCT | _ISGRAPH | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISXDIGIT:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISXDIGIT | _ISPRINT);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISBLANK:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_ISBLANK | _ISSPACE);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISPHONOGRAM:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_E1 | _ISPRINT | _ISGRAPH);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISIDEOGRAM:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_E2 | _ISPRINT | _ISGRAPH);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISENGLISH:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_E3 | _ISPRINT | _ISGRAPH);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISNUMBER:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_E4 | _ISPRINT | _ISGRAPH);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISSPECIAL:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= (_E5 | _ISPRINT | _ISGRAPH);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_ISALNUM:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore /*
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 */
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore default:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore errf(_("not a valid character class"));
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorestatic ctype_node_t *
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoreget_ctype(wchar_t wc)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctype_node_t srch;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctype_node_t *ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore avl_index_t where;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore srch.wc = wc;
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(_("out of memory"));
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return (NULL);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->wc = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore avl_insert(&ctypes, ctn, where);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return (ctn);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorevoid
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoreadd_ctype(int val)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctype_node_t *ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn = get_ctype(val)) == NULL) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore INTERR;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore add_ctype_impl(ctn);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_ctype = ctn->wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorevoid
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoreadd_ctype_range(int end)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctype_node_t *ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore wchar_t cur;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (end < last_ctype) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore errf(_("malformed character range (%u ... %u))"),
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_ctype, end);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore for (cur = last_ctype + 1; cur <= end; cur++) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn = get_ctype(cur)) == NULL) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore INTERR;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore add_ctype_impl(ctn);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_ctype = end;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore/*
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * A word about widths: if the width mask is specified, then libc
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * unconditionally honors it. Otherwise, it assumes printable
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * characters have width 1, and non-printable characters have width
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * -1 (except for NULL which is special with with 0). Hence, we have
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * no need to inject defaults here -- the "default" unset value of 0
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore * indicates that libc should use its own logic in wcwidth as described.
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore */
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amorevoid
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amoreadd_width(int wc, int width)
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore{
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore ctype_node_t *ctn;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore if ((ctn = get_ctype(wc)) == NULL) {
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore INTERR;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore return;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore }
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore ctn->ctype &= ~(_CTYPE_SWM);
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore switch (width) {
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore case 0:
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore ctn->ctype |= _CTYPE_SW0;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore break;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore case 1:
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore ctn->ctype |= _CTYPE_SW1;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore break;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore case 2:
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore ctn->ctype |= _CTYPE_SW2;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore break;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore case 3:
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore ctn->ctype |= _CTYPE_SW3;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore break;
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore }
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore}
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amorevoid
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amoreadd_width_range(int start, int end, int width)
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore{
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore for (; start <= end; start++) {
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore add_width(start, width);
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore }
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore}
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorevoid
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoreadd_caseconv(int val, int wc)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctype_node_t *ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn = get_ctype(val);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn == NULL) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore INTERR;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore switch (last_kw) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_TOUPPER:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->toupper = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore case T_TOLOWER:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->tolower = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore default:
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore INTERR;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore break;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amorevoid
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amoredump_ctype(void)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore{
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore FILE *f;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore _FileRuneLocale rl;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctype_node_t *ctn, *last_ct, *last_lo, *last_up;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore _FileRuneEntry *ct = NULL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore _FileRuneEntry *lo = NULL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore _FileRuneEntry *up = NULL;
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner wchar_t wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (void) memset(&rl, 0, sizeof (rl));
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_ct = NULL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_lo = NULL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_up = NULL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((f = open_category()) == NULL)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
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
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner /*
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner * Initialize the identity map.
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner */
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner for (wc = 0; (unsigned)wc < _CACHED_RUNES; wc++) {
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner rl.maplower[wc] = wc;
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner rl.mapupper[wc] = wc;
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner for (ctn = avl_first(&ctypes); ctn; ctn = AVL_NEXT(&ctypes, ctn)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore int conflict = 0;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
2da1cd3a39e2d3da7f9d15071ea9462919c011acGarrett D'Amore
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner wc = ctn->wc;
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore /*
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * POSIX requires certain portable characters have
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * certain types. Add them if they are missing.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore */
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((wc >= 1) && (wc <= 127)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((wc >= 'A') && (wc <= 'Z'))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISUPPER;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((wc >= 'a') && (wc <= 'z'))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISLOWER;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((wc >= '0') && (wc <= '9'))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISDIGIT;
5a4ef21a18dfdc65328821a265582d03e85a97c9Lauri Tirkkonen if (wc == ' ')
5a4ef21a18dfdc65328821a265582d03e85a97c9Lauri Tirkkonen ctn->ctype |= _ISPRINT;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (strchr(" \f\n\r\t\v", (char)wc) != NULL)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISSPACE;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (strchr("0123456789ABCDEFabcdef", (char)wc) != NULL)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISXDIGIT;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (strchr(" \t", (char)wc))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISBLANK;
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore /*
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * Technically these settings are only
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * required for the C locale. However, it
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * turns out that because of the historical
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * version of isprint(), we need them for all
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * locales as well. Note that these are not
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * necessarily valid punctation characters in
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * the current language, but ispunct() needs
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore * to return TRUE for them.
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore */
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore if (strchr("!\"'#$%&()*+,-./:;<=>?@[\\]^_`{|}~",
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore (char)wc))
723fee089c0a7e1bd9527b9a4b0f0abf5970336cGarrett D'Amore ctn->ctype |= _ISPUNCT;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore /*
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * POSIX also requires that certain types imply
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore * others. Add any inferred types here.
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore */
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn->ctype & (_ISUPPER |_ISLOWER))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISALPHA;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn->ctype & _ISDIGIT)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISXDIGIT;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn->ctype & _ISBLANK)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISSPACE;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn->ctype & (_ISALPHA|_ISDIGIT|_ISXDIGIT))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISGRAPH;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn->ctype & _ISGRAPH)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ctn->ctype |= _ISPRINT;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore /*
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 */
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn->ctype & _ISALPHA) &&
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (ctn->ctype & (_ISPUNCT|_ISDIGIT)))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore conflict++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn->ctype & _ISPUNCT) &
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (ctn->ctype & (_ISDIGIT|_ISALPHA|_ISXDIGIT)))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore conflict++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn->ctype & _ISSPACE) && (ctn->ctype & _ISGRAPH))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore conflict++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((ctn->ctype & _ISCNTRL) & _ISPRINT)
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore conflict++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((wc == ' ') && (ctn->ctype & (_ISPUNCT|_ISGRAPH)))
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore conflict++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (conflict) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore warn("conflicting classes for character 0x%x (%x)",
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore wc, ctn->ctype);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore /*
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 */
5080145bebcdf447671b26bba8c9815a208dff4fGarrett D'Amore if ((unsigned)wc < _CACHED_RUNES) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore rl.runetype[wc] = ctn->ctype;
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner if (ctn->tolower)
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner rl.maplower[wc] = ctn->tolower;
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner if (ctn->toupper)
6125cca6ecc6873dbb8a11234fff6cbe12f66573David Höppner rl.mapupper[wc] = ctn->toupper;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore continue;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if ((last_ct != NULL) && (last_ct->ctype == ctn->ctype)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ct[rl.runetype_ext_nranges-1].max = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_ct = ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore } else {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore rl.runetype_ext_nranges++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ct = realloc(ct,
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore sizeof (*ct) * rl.runetype_ext_nranges);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ct[rl.runetype_ext_nranges - 1].min = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ct[rl.runetype_ext_nranges - 1].max = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore ct[rl.runetype_ext_nranges - 1].map = ctn->ctype;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_ct = ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
017c01f878134ff71877f2c67cca171a4ad2cd93Yuri Pankov if (ctn->tolower == 0) {
017c01f878134ff71877f2c67cca171a4ad2cd93Yuri Pankov last_lo = NULL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore } else if ((last_lo != NULL) &&
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (last_lo->tolower + 1 == ctn->tolower)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore lo[rl.maplower_ext_nranges-1].max = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_lo = ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore } else {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore rl.maplower_ext_nranges++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore lo = realloc(lo,
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore sizeof (*lo) * rl.maplower_ext_nranges);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore lo[rl.maplower_ext_nranges - 1].min = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore lo[rl.maplower_ext_nranges - 1].max = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore lo[rl.maplower_ext_nranges - 1].map = ctn->tolower;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_lo = ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore if (ctn->toupper == 0) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_up = NULL;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore } else if ((last_up != NULL) &&
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore (last_up->toupper + 1 == ctn->toupper)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore up[rl.mapupper_ext_nranges-1].max = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_up = ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore } else {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore rl.mapupper_ext_nranges++;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore up = realloc(up,
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore sizeof (*up) * rl.mapupper_ext_nranges);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore up[rl.mapupper_ext_nranges - 1].min = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore up[rl.mapupper_ext_nranges - 1].max = wc;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore up[rl.mapupper_ext_nranges - 1].map = ctn->toupper;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore last_up = ctn;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
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)) {
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore return;
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore }
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore close_category(f);
6b5e5868e7ebf1aff3a5abd7d0c4ef0e5fbf3648Garrett D'Amore}