summaryrefslogtreecommitdiffstats
path: root/lib/libkiconv
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2009-06-22 17:09:46 +0000
committerdelphij <delphij@FreeBSD.org>2009-06-22 17:09:46 +0000
commit3216be3a5a453bb6570d9a31504f54f067832fad (patch)
treeff466c24979a5205b616c97267983e5b0216ed4c /lib/libkiconv
parent903095e7105f537fbdcb5a7a542bd833c6b35b3b (diff)
downloadFreeBSD-src-3216be3a5a453bb6570d9a31504f54f067832fad.zip
FreeBSD-src-3216be3a5a453bb6570d9a31504f54f067832fad.tar.gz
Split tolower/toupper code from usual xlat16 kiconv table, and make it
possible to do tolower/toupper independently without code conversion. Submitted by: imura (but bugs are mine) Obtained from: http://people.freebsd.org/~imura/kiconv/ (1_kiconv_wctype_kern.diff, 1_kiconv_wctype_user.diff)
Diffstat (limited to 'lib/libkiconv')
-rw-r--r--lib/libkiconv/Makefile2
-rw-r--r--lib/libkiconv/kiconv_sysctl.c93
-rw-r--r--lib/libkiconv/xlat16_iconv.c93
3 files changed, 163 insertions, 25 deletions
diff --git a/lib/libkiconv/Makefile b/lib/libkiconv/Makefile
index afb6392..e66e718 100644
--- a/lib/libkiconv/Makefile
+++ b/lib/libkiconv/Makefile
@@ -2,7 +2,7 @@
LIB= kiconv
SHLIBDIR?= /lib
-SRCS= xlat16_iconv.c xlat16_sysctl.c
+SRCS= kiconv_sysctl.c xlat16_iconv.c xlat16_sysctl.c
SRCS+= quirks.c
SHLIB_MAJOR= 3
diff --git a/lib/libkiconv/kiconv_sysctl.c b/lib/libkiconv/kiconv_sysctl.c
new file mode 100644
index 0000000..0030f4d
--- /dev/null
+++ b/lib/libkiconv/kiconv_sysctl.c
@@ -0,0 +1,93 @@
+/*-
+ * 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 <sys/types.h>
+#include <sys/iconv.h>
+#include <sys/sysctl.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+kiconv_lookupconv(const char *drvname)
+{
+ size_t size;
+ int error;
+
+ if (sysctlbyname("kern.iconv.drvlist", NULL, &size, NULL, 0) == -1)
+ return (errno);
+ if (size > 0) {
+ char *drivers, *drvp;
+
+ 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);
+}
diff --git a/lib/libkiconv/xlat16_iconv.c b/lib/libkiconv/xlat16_iconv.c
index db304c3..ce06324 100644
--- a/lib/libkiconv/xlat16_iconv.c
+++ b/lib/libkiconv/xlat16_iconv.c
@@ -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 <dlfcn.h>
#include <err.h>
#include <errno.h>
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <wctype.h>
#include "quirks.h"
@@ -56,6 +58,7 @@ struct xlat16_table {
};
static struct xlat16_table kiconv_xlat16_open(const char *, const char *, int);
+static int chklocale(int, const char *);
static int my_iconv_init(void);
static iconv_t (*my_iconv_open)(const char *, const char *);
@@ -67,30 +70,18 @@ int
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 @@ kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag)
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,7 +118,14 @@ kiconv_add_xlat16_cspairs(const char *foreigncode, const char *localcode)
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 @@ kiconv_xlat16_open(const char *tocode, const char *fromcode, int lcase)
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 @@ kiconv_xlat16_open(const char *tocode, const char *fromcode, int lcase)
}
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;
@@ -380,17 +421,21 @@ my_iconv_char(iconv_t cd, const u_char **ibuf, size_t * ilen, u_char **obuf,
#else /* statically linked */
+#include <sys/types.h>
+#include <sys/iconv.h>
#include <errno.h>
int
-kiconv_add_xlat16_cspair(const char *tocode, const char *fromcode, int flag)
+kiconv_add_xlat16_cspair(const char *tocode __unused, const char *fromcode __unused,
+ int flag __unused)
{
+
errno = EINVAL;
return (-1);
}
int
-kiconv_add_xlat16_cspairs(const char *tocode, const char *fromcode)
+kiconv_add_xlat16_cspairs(const char *tocode __unused, const char *fromcode __unused)
{
errno = EINVAL;
return (-1);
OpenPOWER on IntegriCloud