15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * CDDL HEADER START
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * The contents of this file are subject to the terms of the
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Common Development and Distribution License (the "License").
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * You may not use this file except in compliance with the License.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * or http://www.opensolaris.org/os/licensing.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * See the License for the specific language governing permissions
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * and limitations under the License.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * When distributing Covered Code, include this CDDL HEADER in each
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * If applicable, add the following below this CDDL HEADER, with the
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * fields enclosed by brackets "[]" replaced with your own identifying
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * information: Portions Copyright [yyyy] [name of copyright owner]
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * CDDL HEADER END
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Use is subject to license terms.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#pragma ident "%Z%%M% %I% %E% SMI"
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/types.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/param.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/sysmacros.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/systm.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/debug.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kmem.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/sunddi.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/byteorder.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/errno.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/modctl.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/u8_textprep.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kiconv.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kiconv_cck_common.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kiconv_ko.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kiconv_uhc_utf8.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kiconv_utf8_uhc.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kiconv_euckr_utf8.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#include <sys/kiconv_utf8_euckr.h>
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int8_t utf8_to_euckr(uint32_t utf8, uchar_t **inbuf, uchar_t *ibtail,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob, uchar_t *obtail, size_t *ret_val);
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int8_t utf8_to_uhc(uint32_t utf8, uchar_t **inbuf, uchar_t *ibtail,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob, uchar_t *obtail, size_t *ret_val);
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int8_t ko_to_utf8(uint32_t ko_val, uchar_t *ob, uchar_t *obtail,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t *ret_val, kiconv_table_array_t *table, size_t nitems);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#define KICONV_KO_EUCKR (0x01)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#define KICONV_KO_UHC (0x02)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy#define KICONV_KO_MAX_MAGIC_ID (0x02)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic void *
15d9d0b528387242011cdcc6190c9e598cfe3a07yyopen_fr_euckr()
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return ((void *)KICONV_KO_EUCKR);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic void *
15d9d0b528387242011cdcc6190c9e598cfe3a07yyopen_fr_uhc()
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return ((void *)KICONV_KO_UHC);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int
15d9d0b528387242011cdcc6190c9e598cfe3a07yyclose_fr_ko(void *s)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if ((uintptr_t)s > KICONV_KO_MAX_MAGIC_ID)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (EBADF);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (0);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Encoding convertor from EUC-KR to UTF-8.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconv_fr_euckr(void *kcd, char **inbuf, size_t *inbufleft,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy char **outbuf, size_t *outbufleft, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ibtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *obtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t ret_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int8_t sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uint32_t euckr_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /* Check on the kiconv code conversion descriptor. */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (kcd == NULL || kcd == (void *)-1) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *errno = EBADF;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return ((size_t)-1);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /* If this is a state reset request, process and return. */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (inbuf == NULL || *inbuf == NULL) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (0);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ret_val = 0;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = (uchar_t *)*inbuf;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob = (uchar_t *)*outbuf;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ibtail = ib + *inbufleft;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy obtail = ob + *outbufleft;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy while (ib < ibtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (KICONV_IS_ASCII(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ob >= obtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy continue;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Issue EILSEQ error if the first byte is not a
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * valid EUC-KR leading byte.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_EUCKR_BYTE(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Issue EINVAL error if input buffer has an incomplete
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * character at the end of the buffer.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ibtail - ib < 2) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(EINVAL);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Issue EILSEQ error if the remaining byte is not
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * a valid EUC-KR byte.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_EUCKR_BYTE(*(ib + 1))) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy euckr_val = (uint32_t)(*ib) << 8 | *(ib + 1);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy sz = ko_to_utf8(euckr_val, ob, obtail, &ret_val,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_euckr_utf8, KICONV_EUCKR_UTF8_MAX);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (sz < 0) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib += 2;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob += sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *inbuf = (char *)ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *inbufleft = ibtail - ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *outbuf = (char *)ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *outbufleft = obtail - ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (ret_val);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * String based encoding convertor from EUC-KR to UTF-8.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconvstr_fr_euckr(char *inarray, size_t *inlen, char *outarray,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t *outlen, int flag, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ibtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *obtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *oldib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t ret_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int8_t sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uint32_t euckr_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy boolean_t do_not_ignore_null;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ret_val = 0;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = (uchar_t *)inarray;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob = (uchar_t *)outarray;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ibtail = ib + *inlen;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy obtail = ob + *outlen;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy while (ib < ibtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (*ib == '\0' && do_not_ignore_null)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy break;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (KICONV_IS_ASCII(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ob >= obtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy continue;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy oldib = ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_EUCKR_BYTE(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_WITH_FLAG(1, EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ibtail - ib < 2) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_WITH_FLAG(1, EINVAL);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_EUCKR_BYTE(*(ib + 1))) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_WITH_FLAG(2, EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy euckr_val = *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy euckr_val = (euckr_val << 8) | *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy sz = ko_to_utf8(euckr_val, ob, obtail, &ret_val,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_euckr_utf8, KICONV_EUCKR_UTF8_MAX);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (sz < 0) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = oldib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob += sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy continue;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yyREPLACE_INVALID:
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (obtail - ob < KICONV_UTF8_REPLACEMENT_CHAR_LEN) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = oldib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = KICONV_UTF8_REPLACEMENT_CHAR1;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = KICONV_UTF8_REPLACEMENT_CHAR2;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = KICONV_UTF8_REPLACEMENT_CHAR3;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ret_val++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *inlen = ibtail - ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *outlen = obtail - ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (ret_val);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Encoding convertor from Unified Hangul Code to UTF-8.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconv_fr_uhc(void *kcd, char **inbuf, size_t *inbufleft,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy char **outbuf, size_t *outbufleft, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ibtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *obtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t ret_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int8_t sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uint32_t uhc_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /* Check on the kiconv code conversion descriptor. */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (kcd == NULL || kcd == (void *)-1) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *errno = EBADF;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return ((size_t)-1);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /* If this is a state reset request, process and return. */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (inbuf == NULL || *inbuf == NULL) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (0);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ret_val = 0;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = (uchar_t *)*inbuf;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob = (uchar_t *)*outbuf;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ibtail = ib + *inbufleft;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy obtail = ob + *outbufleft;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy while (ib < ibtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (KICONV_IS_ASCII(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ob >= obtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy continue;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Issue EILSEQ error if the first byte is not a
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * valid UHC leading byte.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_UHC_1st_BYTE(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Issue EINVAL error if input buffer has an incomplete
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * character at the end of the buffer.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ibtail - ib < 2) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(EINVAL);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Issue EILSEQ error if the remaining byte is not
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * a valid UHC byte.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_UHC_2nd_BYTE(*(ib + 1))) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uhc_val = (uint32_t)(*ib) << 8 | *(ib + 1);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy sz = ko_to_utf8(uhc_val, ob, obtail, &ret_val,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_uhc_utf8, KICONV_UHC_UTF8_MAX);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (sz < 0) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib += 2;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob += sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *inbuf = (char *)ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *inbufleft = ibtail - ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *outbuf = (char *)ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *outbufleft = obtail - ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (ret_val);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * String based encoding convertor from Unified Hangul Code to UTF-8.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconvstr_fr_uhc(char *inarray, size_t *inlen, char *outarray,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t *outlen, int flag, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ibtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *obtail;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *oldib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t ret_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int8_t sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uint32_t uhc_val;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy boolean_t do_not_ignore_null;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ret_val = 0;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = (uchar_t *)inarray;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob = (uchar_t *)outarray;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ibtail = ib + *inlen;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy obtail = ob + *outlen;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy while (ib < ibtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (*ib == '\0' && do_not_ignore_null)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy break;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (KICONV_IS_ASCII(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ob >= obtail) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy continue;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy oldib = ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_UHC_1st_BYTE(*ib)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_WITH_FLAG(1, EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (ibtail - ib < 2) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_WITH_FLAG(1, EINVAL);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (! KICONV_KO_IS_UHC_2nd_BYTE(*(ib + 1))) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_WITH_FLAG(2, EILSEQ);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uhc_val = *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uhc_val = (uhc_val << 8) | *ib++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy sz = ko_to_utf8(uhc_val, ob, obtail, &ret_val,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_uhc_utf8, KICONV_UHC_UTF8_MAX);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (sz < 0) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = oldib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ob += sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy continue;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yyREPLACE_INVALID:
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (obtail - ob < KICONV_UTF8_REPLACEMENT_CHAR_LEN) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ib = oldib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_SET_ERRNO_AND_BREAK(E2BIG);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = KICONV_UTF8_REPLACEMENT_CHAR1;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = KICONV_UTF8_REPLACEMENT_CHAR2;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = KICONV_UTF8_REPLACEMENT_CHAR3;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy ret_val++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *inlen = ibtail - ib;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *outlen = obtail - ob;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (ret_val);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Encoding convertor from UTF-8 to EUC-KR.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconv_to_euckr(void *kcd, char **inbuf, size_t *inbytesleft,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy char **outbuf, size_t *outbytesleft, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (kiconv_utf8_to_cck(kcd, inbuf, inbytesleft, outbuf,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy outbytesleft, errno, utf8_to_euckr));
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Encoding convertor from UTF-8 to Unified Hangul Code.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconv_to_uhc(void *kcd, char **inbuf, size_t *inbytesleft,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy char **outbuf, size_t *outbytesleft, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (kiconv_utf8_to_cck(kcd, inbuf, inbytesleft, outbuf,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy outbytesleft, errno, utf8_to_uhc));
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * String based encoding convertor from UTF-8 to EUC-KR.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconvstr_to_euckr(char *inarray, size_t *inlen, char *outarray,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t *outlen, int flag, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return kiconvstr_utf8_to_cck((uchar_t *)inarray, inlen,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (uchar_t *)outarray, outlen, flag, errno, utf8_to_euckr);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * String based encoding convertor from UTF-8 to Unified Hangul Code.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic size_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yykiconvstr_to_uhc(char *inarray, size_t *inlen, char *outarray,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t *outlen, int flag, int *errno)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return kiconvstr_utf8_to_cck((uchar_t *)inarray, inlen,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (uchar_t *)outarray, outlen, flag, errno, utf8_to_uhc);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Convert an UTF-8 character to a character of ko encodings
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * (EUC-KR or UHC).
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int8_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yyutf8_to_ko(uint32_t utf8, uchar_t *ob, uchar_t *obtail, size_t *ret_val,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_table_t *table, size_t nitems)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t index;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t kocode;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int8_t kolen;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (KICONV_KO_IS_UDC_IN_UTF8(utf8)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /* User Definable Area handing. */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kocode = (((utf8 & 0xF0000) >> 4) | ((utf8 & 0x3F00) >> 2) |
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (utf8 & 0x3F)) - KICONV_KO_UDA_UCS4_START;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (kocode < KICONV_KO_UDA_RANGE) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kocode = (KICONV_KO_UDA_EUC_SEG1 << 8) |
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (kocode + KICONV_KO_UDA_OFFSET_START);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy } else {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /* 0x43 = 0xA1 - 0x5E */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kocode = (KICONV_KO_UDA_EUC_SEG2 << 8) |
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (kocode + 0x43);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy index = 1;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy } else {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy index = kiconv_binsearch(utf8, table, nitems);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kocode = table[index].value;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kolen = (kocode <= 0xFF) ? 1 : 2;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (obtail - ob < kolen) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ret_val = (size_t)-1;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (-1);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (index == 0)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (*ret_val)++;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (kolen > 1)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = (uchar_t)(kocode >> 8);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob = (uchar_t)(kocode & 0xFF);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (kolen);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Convert an UTF-8 character to Unified Hangual Code.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/* ARGSUSED */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int8_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yyutf8_to_uhc(uint32_t utf8, uchar_t **inbuf, uchar_t *ibtail,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob, uchar_t *obtail, size_t *ret_val)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (utf8_to_ko(utf8, ob, obtail, ret_val, kiconv_utf8_uhc,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_UTF8_UHC_MAX));
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Convert an UTF-8 character to EUC-KR.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/* ARGSUSED */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int8_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yyutf8_to_euckr(uint32_t utf8, uchar_t **inbuf, uchar_t *ibtail,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *ob, uchar_t *obtail, size_t *ret_val)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (utf8_to_ko(utf8, ob, obtail, ret_val, kiconv_utf8_euckr,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_UTF8_EUCKR_MAX));
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy/*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Convert a single ko encoding (EUC-KR or UHC) character to UTF-8.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic int8_t
15d9d0b528387242011cdcc6190c9e598cfe3a07yyko_to_utf8(uint32_t ko_val, uchar_t *ob, uchar_t *obtail, size_t *ret_val,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_table_array_t *table, size_t nitems)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy size_t index;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int8_t sz;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t udc[3];
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uchar_t *u8;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (KICONV_KO_IS_UDC_IN_EUC(ko_val)) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /* UDA(User Definable Area) handling. */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy uint32_t u32;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy u32 = (ko_val & 0xFF) + (((ko_val & 0xFF00) == 0xC900) ?
15d9d0b528387242011cdcc6190c9e598cfe3a07yy KICONV_KO_UDA_OFFSET_1 : KICONV_KO_UDA_OFFSET_2);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy udc[0] = 0xEF;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy udc[1] = (uchar_t)(0x80 | (u32 & 0x00000FC0) >> 6);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy udc[2] = (uchar_t)(0x80 | (u32 & 0x0000003F));
15d9d0b528387242011cdcc6190c9e598cfe3a07yy u8 = udc;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy index = 1;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy } else {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy index = kiconv_binsearch(ko_val, table, nitems);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy u8 = table[index].u8;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy sz = u8_number_of_bytes[u8[0]];
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (obtail - ob < sz) {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ret_val = (size_t)-1;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (-1);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (index == 0)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (*ret_val)++; /* Non-identical conversion */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy for (index = 0; index < sz; index++)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *ob++ = u8[index];
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (sz);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic kiconv_ops_t kiconv_ko_ops_tbl[] = {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy "euc-kr", "utf-8", kiconv_open_to_cck, kiconv_to_euckr,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_close_to_cck, kiconvstr_to_euckr
15d9d0b528387242011cdcc6190c9e598cfe3a07yy },
15d9d0b528387242011cdcc6190c9e598cfe3a07yy {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy "utf-8", "euc-kr", open_fr_euckr, kiconv_fr_euckr,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy close_fr_ko, kiconvstr_fr_euckr
15d9d0b528387242011cdcc6190c9e598cfe3a07yy },
15d9d0b528387242011cdcc6190c9e598cfe3a07yy {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy "unifiedhangul", "utf-8", kiconv_open_to_cck, kiconv_to_uhc,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_close_to_cck, kiconvstr_to_uhc
15d9d0b528387242011cdcc6190c9e598cfe3a07yy },
15d9d0b528387242011cdcc6190c9e598cfe3a07yy {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy "utf-8", "unifiedhangul", open_fr_uhc, kiconv_fr_uhc,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy close_fr_ko, kiconvstr_fr_uhc
15d9d0b528387242011cdcc6190c9e598cfe3a07yy }
15d9d0b528387242011cdcc6190c9e598cfe3a07yy};
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic kiconv_module_info_t kiconv_ko_info = {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy "kiconv_ko", /* module name */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy sizeof (kiconv_ko_ops_tbl) / sizeof (kiconv_ko_ops_tbl[0]),
15d9d0b528387242011cdcc6190c9e598cfe3a07yy kiconv_ko_ops_tbl,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy 0,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy NULL,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy NULL,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy 0
15d9d0b528387242011cdcc6190c9e598cfe3a07yy};
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic struct modlkiconv modlkiconv_ko = {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy &mod_kiconvops,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy "kiconv korean module 1.0",
15d9d0b528387242011cdcc6190c9e598cfe3a07yy &kiconv_ko_info
15d9d0b528387242011cdcc6190c9e598cfe3a07yy};
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yystatic struct modlinkage modlinkage = {
15d9d0b528387242011cdcc6190c9e598cfe3a07yy MODREV_1,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy (void *)&modlkiconv_ko,
15d9d0b528387242011cdcc6190c9e598cfe3a07yy NULL
15d9d0b528387242011cdcc6190c9e598cfe3a07yy};
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yyint
15d9d0b528387242011cdcc6190c9e598cfe3a07yy_init(void)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int err;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy err = mod_install(&modlinkage);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (err)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy cmn_err(CE_WARN, "kiconv_ko: failed to load kernel module");
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (err);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yyint
15d9d0b528387242011cdcc6190c9e598cfe3a07yy_fini(void)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy int err;
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy /*
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * If this module is being used, then, we cannot remove the module.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * The following checking will catch pretty much all usual cases.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy *
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * Any remaining will be catached by the kiconv_unregister_module()
15d9d0b528387242011cdcc6190c9e598cfe3a07yy * during mod_remove() at below.
15d9d0b528387242011cdcc6190c9e598cfe3a07yy */
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (kiconv_module_ref_count(KICONV_MODULE_ID_KO))
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (EBUSY);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy err = mod_remove(&modlinkage);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy if (err)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy cmn_err(CE_WARN, "kiconv_ko: failed to remove kernel module");
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (err);
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}
15d9d0b528387242011cdcc6190c9e598cfe3a07yy
15d9d0b528387242011cdcc6190c9e598cfe3a07yyint
15d9d0b528387242011cdcc6190c9e598cfe3a07yy_info(struct modinfo *modinfop)
15d9d0b528387242011cdcc6190c9e598cfe3a07yy{
15d9d0b528387242011cdcc6190c9e598cfe3a07yy return (mod_info(&modlinkage, modinfop));
15d9d0b528387242011cdcc6190c9e598cfe3a07yy}