summaryrefslogtreecommitdiffstats
path: root/lib/libkiconv/xlat16_iconv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkiconv/xlat16_iconv.c')
-rw-r--r--lib/libkiconv/xlat16_iconv.c93
1 files changed, 69 insertions, 24 deletions
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