diff options
Diffstat (limited to 'intl/unicharutil/ucdata.c')
-rw-r--r-- | intl/unicharutil/ucdata.c | 1162 |
1 files changed, 1162 insertions, 0 deletions
diff --git a/intl/unicharutil/ucdata.c b/intl/unicharutil/ucdata.c new file mode 100644 index 000000000..090399ead --- /dev/null +++ b/intl/unicharutil/ucdata.c @@ -0,0 +1,1162 @@ +/* + * Copyright 1996, 1997, 1998 Computing Research Labs, + * New Mexico State University + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef lint +#ifdef __GNUC__ +static char rcsid[] __attribute__ ((unused)) = "$Id: ucdata.c,v 1.1 1999/01/08 00:19:11 ftang%netscape.com Exp $"; +#else +static char rcsid[] = "$Id: ucdata.c,v 1.1 1999/01/08 00:19:11 ftang%netscape.com Exp $"; +#endif +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef WIN32 +#include <unistd.h> +#endif + +#include "ucdata.h" + +/************************************************************************** + * + * Miscellaneous types, data, and support functions. + * + **************************************************************************/ + +typedef struct { + unsigned short bom; + unsigned short cnt; + union { + unsigned long bytes; + unsigned short len[2]; + } size; +} _ucheader_t; + +/* + * A simple array of 32-bit masks for lookup. + */ +static unsigned long masks32[32] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, + 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, + 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, + 0x40000000, 0x80000000 +}; + +#define endian_short(cc) (((cc) >> 8) | (((cc) & 0xff) << 8)) +#define endian_long(cc) ((((cc) & 0xff) << 24)|((((cc) >> 8) & 0xff) << 16)|\ + ((((cc) >> 16) & 0xff) << 8)|((cc) >> 24)) + +static FILE * +#ifdef __STDC__ +_ucopenfile(char *paths, char *filename, char *mode) +#else +_ucopenfile(paths, filename, mode) +char *paths, *filename, *mode; +#endif +{ + FILE *f; + char *fp, *dp, *pp, path[BUFSIZ]; + + if (filename == 0 || *filename == 0) + return 0; + + dp = paths; + while (dp && *dp) { + pp = path; + while (*dp && *dp != ':') + *pp++ = *dp++; + *pp++ = '/'; + + fp = filename; + while (*fp) + *pp++ = *fp++; + *pp = 0; + + if ((f = fopen(path, mode)) != 0) + return f; + + if (*dp == ':') + dp++; + } + + return 0; +} + +/************************************************************************** + * + * Support for the character properties. + * + **************************************************************************/ + +static unsigned long _ucprop_size; +static unsigned short *_ucprop_offsets; +static unsigned long *_ucprop_ranges; + +static void +#ifdef __STDC__ +_ucprop_load(char *paths, int reload) +#else +_ucprop_load(paths, reload) +char *paths; +int reload; +#endif +{ + FILE *in; + unsigned long size, i; + _ucheader_t hdr; + + if (_ucprop_size > 0) { + if (!reload) + /* + * The character properties have already been loaded. + */ + return; + + /* + * Unload the current character property data in preparation for + * loading a new copy. Only the first array has to be deallocated + * because all the memory for the arrays is allocated as a single + * block. + */ + free((char *) _ucprop_offsets); + _ucprop_size = 0; + } + + if ((in = _ucopenfile(paths, "ctype.dat", "rb")) == 0) + return; + + /* + * Load the header. + */ + fread((char *) &hdr, sizeof(_ucheader_t), 1, in); + + if (hdr.bom == 0xfffe) { + hdr.cnt = endian_short(hdr.cnt); + hdr.size.bytes = endian_long(hdr.size.bytes); + } + + if ((_ucprop_size = hdr.cnt) == 0) { + fclose(in); + return; + } + + /* + * Allocate all the storage needed for the lookup table. + */ + _ucprop_offsets = (unsigned short *) malloc(hdr.size.bytes); + + /* + * Calculate the offset into the storage for the ranges. The offsets + * array is on a 4-byte boundary and one larger than the value provided in + * the header count field. This means the offset to the ranges must be + * calculated after aligning the count to a 4-byte boundary. + */ + if ((size = ((hdr.cnt + 1) * sizeof(unsigned short))) & 3) + size += 4 - (size & 3); + size >>= 1; + _ucprop_ranges = (unsigned long *) (_ucprop_offsets + size); + + /* + * Load the offset array. + */ + fread((char *) _ucprop_offsets, sizeof(unsigned short), size, in); + + /* + * Do an endian swap if necessary. Don't forget there is an extra node on + * the end with the final index. + */ + if (hdr.bom == 0xfffe) { + for (i = 0; i <= _ucprop_size; i++) + _ucprop_offsets[i] = endian_short(_ucprop_offsets[i]); + } + + /* + * Load the ranges. The number of elements is in the last array position + * of the offsets. + */ + fread((char *) _ucprop_ranges, sizeof(unsigned long), + _ucprop_offsets[_ucprop_size], in); + + fclose(in); + + /* + * Do an endian swap if necessary. + */ + if (hdr.bom == 0xfffe) { + for (i = 0; i < _ucprop_offsets[_ucprop_size]; i++) + _ucprop_ranges[i] = endian_long(_ucprop_ranges[i]); + } +} + +static void +#ifdef __STDC__ +_ucprop_unload(void) +#else +_ucprop_unload() +#endif +{ + if (_ucprop_size == 0) + return; + + /* + * Only need to free the offsets because the memory is allocated as a + * single block. + */ + free((char *) _ucprop_offsets); + _ucprop_size = 0; +} + +static int +#ifdef __STDC__ +_ucprop_lookup(unsigned long code, unsigned long n) +#else +_ucprop_lookup(code, n) +unsigned long code, n; +#endif +{ + long l, r, m; + + /* + * There is an extra node on the end of the offsets to allow this routine + * to work right. If the index is 0xffff, then there are no nodes for the + * property. + */ + if ((l = _ucprop_offsets[n]) == 0xffff) + return 0; + + /* + * Locate the next offset that is not 0xffff. The sentinel at the end of + * the array is the max index value. + */ + for (m = 1; + n + m < _ucprop_size && _ucprop_offsets[n + m] == 0xffff; m++) ; + + r = _ucprop_offsets[n + m] - 1; + + while (l <= r) { + /* + * Determine a "mid" point and adjust to make sure the mid point is at + * the beginning of a range pair. + */ + m = (l + r) >> 1; + m -= (m & 1); + if (code > _ucprop_ranges[m + 1]) + l = m + 2; + else if (code < _ucprop_ranges[m]) + r = m - 2; + else if (code >= _ucprop_ranges[m] && code <= _ucprop_ranges[m + 1]) + return 1; + } + return 0; +} + +int +#ifdef __STDC__ +ucisprop(unsigned long code, unsigned long mask1, unsigned long mask2) +#else +ucisprop(code, mask1, mask2) +unsigned long code, mask1, mask2; +#endif +{ + unsigned long i; + + if (mask1 == 0 && mask2 == 0) + return 0; + + for (i = 0; mask1 && i < 32; i++) { + if ((mask1 & masks32[i]) && _ucprop_lookup(code, i)) + return 1; + } + + for (i = 32; mask2 && i < _ucprop_size; i++) { + if ((mask2 & masks32[i & 31]) && _ucprop_lookup(code, i)) + return 1; + } + + return 0; +} + +/************************************************************************** + * + * Support for case mapping. + * + **************************************************************************/ + +static unsigned long _uccase_size; +static unsigned short _uccase_len[2]; +static unsigned long *_uccase_map; + +static void +#ifdef __STDC__ +_uccase_load(char *paths, int reload) +#else +_uccase_load(paths, reload) +char *paths; +int reload; +#endif +{ + FILE *in; + unsigned long i; + _ucheader_t hdr; + + if (_uccase_size > 0) { + if (!reload) + /* + * The case mappings have already been loaded. + */ + return; + + free((char *) _uccase_map); + _uccase_size = 0; + } + + if ((in = _ucopenfile(paths, "case.dat", "rb")) == 0) + return; + + /* + * Load the header. + */ + fread((char *) &hdr, sizeof(_ucheader_t), 1, in); + + if (hdr.bom == 0xfffe) { + hdr.cnt = endian_short(hdr.cnt); + hdr.size.len[0] = endian_short(hdr.size.len[0]); + hdr.size.len[1] = endian_short(hdr.size.len[1]); + } + + /* + * Set the node count and lengths of the upper and lower case mapping + * tables. + */ + _uccase_size = hdr.cnt * 3; + _uccase_len[0] = hdr.size.len[0] * 3; + _uccase_len[1] = hdr.size.len[1] * 3; + + _uccase_map = (unsigned long *) + malloc(_uccase_size * sizeof(unsigned long)); + + /* + * Load the case mapping table. + */ + fread((char *) _uccase_map, sizeof(unsigned long), _uccase_size, in); + + /* + * Do an endian swap if necessary. + */ + if (hdr.bom == 0xfffe) { + for (i = 0; i < _uccase_size; i++) + _uccase_map[i] = endian_long(_uccase_map[i]); + } +} + +static void +#ifdef __STDC__ +_uccase_unload(void) +#else +_uccase_unload() +#endif +{ + if (_uccase_size == 0) + return; + + free((char *) _uccase_map); + _uccase_size = 0; +} + +static unsigned long +#ifdef __STDC__ +_uccase_lookup(unsigned long code, long l, long r, int field) +#else +_uccase_lookup(code, l, r, field) +unsigned long code; +long l, r; +int field; +#endif +{ + long m; + + /* + * Do the binary search. + */ + while (l <= r) { + /* + * Determine a "mid" point and adjust to make sure the mid point is at + * the beginning of a case mapping triple. + */ + m = (l + r) >> 1; + m -= (m % 3); + if (code > _uccase_map[m]) + l = m + 3; + else if (code < _uccase_map[m]) + r = m - 3; + else if (code == _uccase_map[m]) + return _uccase_map[m + field]; + } + + return code; +} + +unsigned long +#ifdef __STDC__ +uctoupper(unsigned long code) +#else +uctoupper(code) +unsigned long code; +#endif +{ + int field; + long l, r; + + if (ucisupper(code)) + return code; + + if (ucislower(code)) { + /* + * The character is lower case. + */ + field = 1; + l = _uccase_len[0]; + r = (l + _uccase_len[1]) - 1; + } else { + /* + * The character is title case. + */ + field = 2; + l = _uccase_len[0] + _uccase_len[1]; + r = _uccase_size - 1; + } + return _uccase_lookup(code, l, r, field); +} + +unsigned long +#ifdef __STDC__ +uctolower(unsigned long code) +#else +uctolower(code) +unsigned long code; +#endif +{ + int field; + long l, r; + + if (ucislower(code)) + return code; + + if (ucisupper(code)) { + /* + * The character is upper case. + */ + field = 1; + l = 0; + r = _uccase_len[0] - 1; + } else { + /* + * The character is title case. + */ + field = 2; + l = _uccase_len[0] + _uccase_len[1]; + r = _uccase_size - 1; + } + return _uccase_lookup(code, l, r, field); +} + +unsigned long +#ifdef __STDC__ +uctotitle(unsigned long code) +#else +uctotitle(code) +unsigned long code; +#endif +{ + int field; + long l, r; + + if (ucistitle(code)) + return code; + + /* + * The offset will always be the same for converting to title case. + */ + field = 2; + + if (ucisupper(code)) { + /* + * The character is upper case. + */ + l = 0; + r = _uccase_len[0] - 1; + } else { + /* + * The character is lower case. + */ + l = _uccase_len[0]; + r = (l + _uccase_len[1]) - 1; + } + return _uccase_lookup(code, l, r, field); +} + +/************************************************************************** + * + * Support for decompositions. + * + **************************************************************************/ + +static unsigned long _ucdcmp_size; +static unsigned long *_ucdcmp_nodes; +static unsigned long *_ucdcmp_decomp; + +static void +#ifdef __STDC__ +_ucdcmp_load(char *paths, int reload) +#else +_ucdcmp_load(paths, reload) +char *paths; +int reload; +#endif +{ + FILE *in; + unsigned long size, i; + _ucheader_t hdr; + + if (_ucdcmp_size > 0) { + if (!reload) + /* + * The decompositions have already been loaded. + */ + return; + + free((char *) _ucdcmp_nodes); + _ucdcmp_size = 0; + } + + if ((in = _ucopenfile(paths, "decomp.dat", "rb")) == 0) + return; + + /* + * Load the header. + */ + fread((char *) &hdr, sizeof(_ucheader_t), 1, in); + + if (hdr.bom == 0xfffe) { + hdr.cnt = endian_short(hdr.cnt); + hdr.size.bytes = endian_long(hdr.size.bytes); + } + + _ucdcmp_size = hdr.cnt << 1; + _ucdcmp_nodes = (unsigned long *) malloc(hdr.size.bytes); + _ucdcmp_decomp = _ucdcmp_nodes + (_ucdcmp_size + 1); + + /* + * Read the decomposition data in. + */ + size = hdr.size.bytes / sizeof(unsigned long); + fread((char *) _ucdcmp_nodes, sizeof(unsigned long), size, in); + + /* + * Do an endian swap if necessary. + */ + if (hdr.bom == 0xfffe) { + for (i = 0; i < size; i++) + _ucdcmp_nodes[i] = endian_long(_ucdcmp_nodes[i]); + } +} + +static void +#ifdef __STDC__ +_ucdcmp_unload(void) +#else +_ucdcmp_unload() +#endif +{ + if (_ucdcmp_size == 0) + return; + + /* + * Only need to free the offsets because the memory is allocated as a + * single block. + */ + free((char *) _ucdcmp_nodes); + _ucdcmp_size = 0; +} + +int +#ifdef __STDC__ +ucdecomp(unsigned long code, unsigned long *num, unsigned long **decomp) +#else +ucdecomp(code, num, decomp) +unsigned long code, *num, **decomp; +#endif +{ + long l, r, m; + + l = 0; + r = _ucdcmp_nodes[_ucdcmp_size] - 1; + + while (l <= r) { + /* + * Determine a "mid" point and adjust to make sure the mid point is at + * the beginning of a code+offset pair. + */ + m = (l + r) >> 1; + m -= (m & 1); + if (code > _ucdcmp_nodes[m]) + l = m + 2; + else if (code < _ucdcmp_nodes[m]) + r = m - 2; + else if (code == _ucdcmp_nodes[m]) { + *num = _ucdcmp_nodes[m + 3] - _ucdcmp_nodes[m + 1]; + *decomp = &_ucdcmp_decomp[_ucdcmp_nodes[m + 1]]; + return 1; + } + } + return 0; +} + +int +#ifdef __STDC__ +ucdecomp_hangul(unsigned long code, unsigned long *num, unsigned long decomp[]) +#else +ucdecomp_hangul(code, num, decomp) +unsigned long code, *num, decomp[]; +#endif +{ + if (!ucishangul(code)) + return 0; + + code -= 0xac00; + decomp[0] = 0x1100 + (unsigned long) (code / 588); + decomp[1] = 0x1161 + (unsigned long) ((code % 588) / 28); + decomp[2] = 0x11a7 + (unsigned long) (code % 28); + *num = (decomp[2] != 0x11a7) ? 3 : 2; + + return 1; +} + +/************************************************************************** + * + * Support for combining classes. + * + **************************************************************************/ + +static unsigned long _uccmcl_size; +static unsigned long *_uccmcl_nodes; + +static void +#ifdef __STDC__ +_uccmcl_load(char *paths, int reload) +#else +_uccmcl_load(paths, reload) +char *paths; +int reload; +#endif +{ + FILE *in; + unsigned long i; + _ucheader_t hdr; + + if (_uccmcl_size > 0) { + if (!reload) + /* + * The combining classes have already been loaded. + */ + return; + + free((char *) _uccmcl_nodes); + _uccmcl_size = 0; + } + + if ((in = _ucopenfile(paths, "cmbcl.dat", "rb")) == 0) + return; + + /* + * Load the header. + */ + fread((char *) &hdr, sizeof(_ucheader_t), 1, in); + + if (hdr.bom == 0xfffe) { + hdr.cnt = endian_short(hdr.cnt); + hdr.size.bytes = endian_long(hdr.size.bytes); + } + + _uccmcl_size = hdr.cnt * 3; + _uccmcl_nodes = (unsigned long *) malloc(hdr.size.bytes); + + /* + * Read the combining classes in. + */ + fread((char *) _uccmcl_nodes, sizeof(unsigned long), _uccmcl_size, in); + + /* + * Do an endian swap if necessary. + */ + if (hdr.bom == 0xfffe) { + for (i = 0; i < _uccmcl_size; i++) + _uccmcl_nodes[i] = endian_long(_uccmcl_nodes[i]); + } +} + +static void +#ifdef __STDC__ +_uccmcl_unload(void) +#else +_uccmcl_unload() +#endif +{ + if (_uccmcl_size == 0) + return; + + free((char *) _uccmcl_nodes); + _uccmcl_size = 0; +} + +unsigned long +#ifdef __STDC__ +uccombining_class(unsigned long code) +#else +uccombining_class(code) +unsigned long code; +#endif +{ + long l, r, m; + + l = 0; + r = _uccmcl_size - 1; + + while (l <= r) { + m = (l + r) >> 1; + m -= (m % 3); + if (code > _uccmcl_nodes[m + 1]) + l = m + 3; + else if (code < _uccmcl_nodes[m]) + r = m - 3; + else if (code >= _uccmcl_nodes[m] && code <= _uccmcl_nodes[m + 1]) + return _uccmcl_nodes[m + 2]; + } + return 0; +} + +/************************************************************************** + * + * Support for numeric values. + * + **************************************************************************/ + +static unsigned long *_ucnum_nodes; +static unsigned long _ucnum_size; +static short *_ucnum_vals; + +static void +#ifdef __STDC__ +_ucnumb_load(char *paths, int reload) +#else +_ucnumb_load(paths, reload) +char *paths; +int reload; +#endif +{ + FILE *in; + unsigned long size, i; + _ucheader_t hdr; + + if (_ucnum_size > 0) { + if (!reload) + /* + * The numbers have already been loaded. + */ + return; + + free((char *) _ucnum_nodes); + _ucnum_size = 0; + } + + if ((in = _ucopenfile(paths, "num.dat", "rb")) == 0) + return; + + /* + * Load the header. + */ + fread((char *) &hdr, sizeof(_ucheader_t), 1, in); + + if (hdr.bom == 0xfffe) { + hdr.cnt = endian_short(hdr.cnt); + hdr.size.bytes = endian_long(hdr.size.bytes); + } + + _ucnum_size = hdr.cnt; + _ucnum_nodes = (unsigned long *) malloc(hdr.size.bytes); + _ucnum_vals = (short *) (_ucnum_nodes + _ucnum_size); + + /* + * Read the combining classes in. + */ + fread((char *) _ucnum_nodes, sizeof(unsigned char), hdr.size.bytes, in); + + /* + * Do an endian swap if necessary. + */ + if (hdr.bom == 0xfffe) { + for (i = 0; i < _ucnum_size; i++) + _ucnum_nodes[i] = endian_long(_ucnum_nodes[i]); + + /* + * Determine the number of values that have to be adjusted. + */ + size = (hdr.size.bytes - + (_ucnum_size * (sizeof(unsigned long) << 1))) / + sizeof(short); + + for (i = 0; i < size; i++) + _ucnum_vals[i] = endian_short(_ucnum_vals[i]); + } +} + +static void +#ifdef __STDC__ +_ucnumb_unload(void) +#else +_ucnumb_unload() +#endif +{ + if (_ucnum_size == 0) + return; + + free((char *) _ucnum_nodes); + _ucnum_size = 0; +} + +int +#ifdef __STDC__ +ucnumber_lookup(unsigned long code, struct ucnumber *num) +#else +ucnumber_lookup(code, num) +unsigned long code; +struct ucnumber *num; +#endif +{ + long l, r, m; + short *vp; + + l = 0; + r = _ucnum_size - 1; + while (l <= r) { + /* + * Determine a "mid" point and adjust to make sure the mid point is at + * the beginning of a code+offset pair. + */ + m = (l + r) >> 1; + m -= (m & 1); + if (code > _ucnum_nodes[m]) + l = m + 2; + else if (code < _ucnum_nodes[m]) + r = m - 2; + else { + vp = _ucnum_vals + _ucnum_nodes[m + 1]; + num->numerator = (int) *vp++; + num->denominator = (int) *vp; + return 1; + } + } + return 0; +} + +int +#ifdef __STDC__ +ucdigit_lookup(unsigned long code, int *digit) +#else +ucdigit_lookup(code, digit) +unsigned long code; +int *digit; +#endif +{ + long l, r, m; + short *vp; + + l = 0; + r = _ucnum_size - 1; + while (l <= r) { + /* + * Determine a "mid" point and adjust to make sure the mid point is at + * the beginning of a code+offset pair. + */ + m = (l + r) >> 1; + m -= (m & 1); + if (code > _ucnum_nodes[m]) + l = m + 2; + else if (code < _ucnum_nodes[m]) + r = m - 2; + else { + vp = _ucnum_vals + _ucnum_nodes[m + 1]; + if (*vp == *(vp + 1)) { + *digit = *vp; + return 1; + } + return 0; + } + } + return 0; +} + +struct ucnumber +#ifdef __STDC__ +ucgetnumber(unsigned long code) +#else +ucgetnumber(code) +unsigned long code; +#endif +{ + struct ucnumber num; + + /* + * Initialize with some arbitrary value, because the caller simply cannot + * tell for sure if the code is a number without calling the ucisnumber() + * macro before calling this function. + */ + num.numerator = num.denominator = -111; + + (void) ucnumber_lookup(code, &num); + + return num; +} + +int +#ifdef __STDC__ +ucgetdigit(unsigned long code) +#else +ucgetdigit(code) +unsigned long code; +#endif +{ + int dig; + + /* + * Initialize with some arbitrary value, because the caller simply cannot + * tell for sure if the code is a number without calling the ucisdigit() + * macro before calling this function. + */ + dig = -111; + + (void) ucdigit_lookup(code, &dig); + + return dig; +} + +/************************************************************************** + * + * Setup and cleanup routines. + * + **************************************************************************/ + +void +#ifdef __STDC__ +ucdata_load(char *paths, int masks) +#else +ucdata_load(paths, masks) +char *paths; +int masks; +#endif +{ + if (masks & UCDATA_CTYPE) + _ucprop_load(paths, 0); + if (masks & UCDATA_CASE) + _uccase_load(paths, 0); + if (masks & UCDATA_DECOMP) + _ucdcmp_load(paths, 0); + if (masks & UCDATA_CMBCL) + _uccmcl_load(paths, 0); + if (masks & UCDATA_NUM) + _ucnumb_load(paths, 0); +} + +void +#ifdef __STDC__ +ucdata_unload(int masks) +#else +ucdata_unload(masks) +int masks; +#endif +{ + if (masks & UCDATA_CTYPE) + _ucprop_unload(); + if (masks & UCDATA_CASE) + _uccase_unload(); + if (masks & UCDATA_DECOMP) + _ucdcmp_unload(); + if (masks & UCDATA_CMBCL) + _uccmcl_unload(); + if (masks & UCDATA_NUM) + _ucnumb_unload(); +} + +void +#ifdef __STDC__ +ucdata_reload(char *paths, int masks) +#else +ucdata_reload(paths, masks) +char *paths; +int masks; +#endif +{ + if (masks & UCDATA_CTYPE) + _ucprop_load(paths, 1); + if (masks & UCDATA_CASE) + _uccase_load(paths, 1); + if (masks & UCDATA_DECOMP) + _ucdcmp_load(paths, 1); + if (masks & UCDATA_CMBCL) + _uccmcl_load(paths, 1); + if (masks & UCDATA_NUM) + _ucnumb_load(paths, 1); +} + +#ifdef TEST + +void +#ifdef __STDC__ +main(void) +#else +main() +#endif +{ + int dig; + unsigned long i, lo, *dec; + struct ucnumber num; + + ucdata_setup("."); + + if (ucisweak(0x30)) + printf("WEAK\n"); + else + printf("NOT WEAK\n"); + + printf("LOWER 0x%04lX\n", uctolower(0xff3a)); + printf("UPPER 0x%04lX\n", uctoupper(0xff5a)); + + if (ucisalpha(0x1d5)) + printf("ALPHA\n"); + else + printf("NOT ALPHA\n"); + + if (ucisupper(0x1d5)) { + printf("UPPER\n"); + lo = uctolower(0x1d5); + printf("0x%04lx\n", lo); + lo = uctotitle(0x1d5); + printf("0x%04lx\n", lo); + } else + printf("NOT UPPER\n"); + + if (ucistitle(0x1d5)) + printf("TITLE\n"); + else + printf("NOT TITLE\n"); + + if (uciscomposite(0x1d5)) + printf("COMPOSITE\n"); + else + printf("NOT COMPOSITE\n"); + + if (ucdecomp(0x1d5, &lo, &dec)) { + for (i = 0; i < lo; i++) + printf("0x%04lx ", dec[i]); + putchar('\n'); + } + + if ((lo = uccombining_class(0x41)) != 0) + printf("0x41 CCL %ld\n", lo); + + if (ucisxdigit(0xfeff)) + printf("0xFEFF HEX DIGIT\n"); + else + printf("0xFEFF NOT HEX DIGIT\n"); + + if (ucisdefined(0x10000)) + printf("0x10000 DEFINED\n"); + else + printf("0x10000 NOT DEFINED\n"); + + if (ucnumber_lookup(0x30, &num)) { + if (num.numerator != num.denominator) + printf("UCNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator); + else + printf("UCNUMBER: 0x30 = %d\n", num.numerator); + } else + printf("UCNUMBER: 0x30 NOT A NUMBER\n"); + + if (ucnumber_lookup(0xbc, &num)) { + if (num.numerator != num.denominator) + printf("UCNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator); + else + printf("UCNUMBER: 0xbc = %d\n", num.numerator); + } else + printf("UCNUMBER: 0xbc NOT A NUMBER\n"); + + + if (ucnumber_lookup(0xff19, &num)) { + if (num.numerator != num.denominator) + printf("UCNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator); + else + printf("UCNUMBER: 0xff19 = %d\n", num.numerator); + } else + printf("UCNUMBER: 0xff19 NOT A NUMBER\n"); + + if (ucnumber_lookup(0x4e00, &num)) { + if (num.numerator != num.denominator) + printf("UCNUMBER: 0x4e00 = %d/%d\n", num.numerator, num.denominator); + else + printf("UCNUMBER: 0x4e00 = %d\n", num.numerator); + } else + printf("UCNUMBER: 0x4e00 NOT A NUMBER\n"); + + if (ucdigit_lookup(0x06f9, &dig)) + printf("UCDIGIT: 0x6f9 = %d\n", dig); + else + printf("UCDIGIT: 0x6f9 NOT A NUMBER\n"); + + dig = ucgetdigit(0x0969); + printf("UCGETDIGIT: 0x969 = %d\n", dig); + + num = ucgetnumber(0x30); + if (num.numerator != num.denominator) + printf("UCGETNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator); + else + printf("UCGETNUMBER: 0x30 = %d\n", num.numerator); + + num = ucgetnumber(0xbc); + if (num.numerator != num.denominator) + printf("UCGETNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator); + else + printf("UCGETNUMBER: 0xbc = %d\n", num.numerator); + + num = ucgetnumber(0xff19); + if (num.numerator != num.denominator) + printf("UCGETNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator); + else + printf("UCGETNUMBER: 0xff19 = %d\n", num.numerator); + + ucdata_cleanup(); + exit(0); +} + +#endif /* TEST */ |