Index: lib/libkiconv/Makefile =================================================================== RCS file: /home/ncvs/src/lib/libkiconv/Makefile,v retrieving revision 1.3 diff -u -r1.3 Makefile --- lib/libkiconv/Makefile 22 Jul 2005 17:19:01 -0000 1.3 +++ lib/libkiconv/Makefile 4 Aug 2005 15:11:57 -0000 @@ -2,7 +2,7 @@ LIB= kiconv SHLIBDIR?= /lib -SRCS= xlat16_iconv.c xlat16_sysctl.c +SRCS= sysctl.c xlat16_iconv.c xlat16_sysctl.c SRCS+= quirks.c SHLIB_MAJOR= 2 Index: lib/libkiconv/sysctl.c =================================================================== RCS file: lib/libkiconv/sysctl.c diff -N lib/libkiconv/sysctl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libkiconv/sysctl.c 4 Aug 2005 15:20:27 -0000 @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2005 Ryuichiro Imura + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include +#include +#include +#include + +int +kiconv_lookupconv(const char *drvname) +{ + size_t size; + char *drivers, *drvp; + int error; + + if (sysctlbyname("kern.iconv.drvlist", NULL, &size, NULL, 0) == -1) + return (errno); + if (size > 0) { + drivers = malloc(size); + if (drivers == NULL) + return (ENOMEM); + if (sysctlbyname("kern.iconv.drvlist", drivers, &size, NULL, 0) == -1) { + error = errno; + free(drivers); + return (errno); + } + } + for (drvp = drivers; *drvp != '\0'; drvp += strlen(drvp) + 1) + if (strcmp(drvp, drvname) == 0) { + free(drivers); + return (0); + } + return (ENOENT); +} + +int +kiconv_lookupcs(const char *tocode, const char *fromcode) +{ + size_t i, size; + struct iconv_cspair_info *csi, *csip; + int error; + + if (sysctlbyname("kern.iconv.cslist", NULL, &size, NULL, 0) == -1) + return (errno); + if (size > 0) { + csi = malloc(size); + if (csi == NULL) + return (ENOMEM); + if (sysctlbyname("kern.iconv.cslist", csi, &size, NULL, 0) == -1) { + error = errno; + free(csi); + return (error); + } + for (i = 0, csip = csi; i < (size/sizeof(*csi)); i++, csip++){ + if (strcmp(csip->cs_to, tocode) == 0 && + strcmp(csip->cs_from, fromcode) == 0) { + free(csi); + return (0); + } + } + } + return (ENOENT); +} Index: lib/libkiconv/xlat16_iconv.c =================================================================== RCS file: /home/ncvs/src/lib/libkiconv/xlat16_iconv.c,v retrieving revision 1.3 diff -u -r1.3 xlat16_iconv.c --- lib/libkiconv/xlat16_iconv.c 14 Mar 2004 05:14:00 -0000 1.3 +++ lib/libkiconv/xlat16_iconv.c 7 Aug 2005 15:00:16 -0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003 Ryuichiro Imura + * Copyright (c) 2003, 2005 Ryuichiro Imura * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,9 +41,11 @@ #include #include #include +#include #include #include #include +#include #include "quirks.h" @@ -56,6 +58,7 @@ }; static struct xlat16_table kiconv_xlat16_open(const char *, const char *, int); +static chklocale(int, const char *); static int my_iconv_init(void); static iconv_t (*my_iconv_open)(const char *, const char *); @@ -67,30 +70,18 @@ kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag) { int error; - size_t i, size, idxsize; - struct iconv_cspair_info *csi; + size_t idxsize; struct xlat16_table xt; void *data; char *p; - if (sysctlbyname("kern.iconv.cslist", NULL, &size, NULL, 0) == -1) - return (-1); - if (size > 0) { - csi = malloc(size); - if (csi == NULL) - return (-1); - if (sysctlbyname("kern.iconv.cslist", csi, &size, NULL, 0) == -1) { - free(csi); - return (-1); - } - for (i = 0; i < (size/sizeof(*csi)); i++, csi++){ - if (strcmp(csi->cs_to, tocode) == 0 && - strcmp(csi->cs_from, fromcode) == 0) - return (0); - } - } + if (kiconv_lookupcs(tocode, fromcode) == 0) + return (0); - xt = kiconv_xlat16_open(tocode, fromcode, flag); + if (flag & KICONV_WCTYPE) + xt = kiconv_xlat16_open(fromcode, fromcode, flag); + else + xt = kiconv_xlat16_open(tocode, fromcode, flag); if (xt.size == 0) return (-1); @@ -117,7 +108,7 @@ int kiconv_add_xlat16_cspairs(const char *foreigncode, const char *localcode) { - int error; + int error, locale; error = kiconv_add_xlat16_cspair(foreigncode, localcode, KICONV_FROM_LOWER | KICONV_FROM_UPPER); @@ -127,6 +118,13 @@ KICONV_LOWER | KICONV_UPPER); if (error) return (error); + locale = chklocale(LC_CTYPE, localcode); + if (locale == 0) { + error = kiconv_add_xlat16_cspair(KICONV_WCTYPE_NAME, localcode, + KICONV_WCTYPE); + if (error) + return (error); + } return (0); } @@ -175,6 +173,31 @@ bzero(dst, outbytesleft); c = ((ls & 0x100 ? us | 0x80 : us) << 8) | (u_char)ls; + + if (lcase & KICONV_WCTYPE) { + if ((c & 0xff) == 0) + c >>= 8; + if (iswupper(c)) { + c = towlower(c); + if ((c & 0xff00) == 0) + c <<= 8; + table[us] = c | XLAT16_HAS_LOWER_CASE; + } else if (iswlower(c)) { + c = towupper(c); + if ((c & 0xff00) == 0) + c <<= 8; + table[us] = c | XLAT16_HAS_UPPER_CASE; + } else + table[us] = 0; + /* + * store not NULL + */ + if (table[us]) + xt.idx[ls] = table; + + continue; + } + c = quirk_vendor2unix(c, pre_q_list, pre_q_size); src[0] = (u_char)(c >> 8); src[1] = (u_char)c; @@ -258,6 +281,24 @@ } static int +chklocale(int category, const char *code) +{ + char *p; + int error = -1; + + p = strchr(setlocale(category, NULL), '.'); + if (p++) { + error = strcasecmp(code, p); + if (error) { + /* XXX - can't avoid calling quirk here... */ + error = strcasecmp(code, kiconv_quirkcs(p, + KICONV_VENDOR_MICSFT)); + } + } + return (error); +} + +static int my_iconv_init(void) { void *iconv_lib;