# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include $(SRC)/Makefile.master # Hammerhead: amd64-only SUBDIRS = $(MACH64) all : TARGET = all clean : TARGET = clean clobber : TARGET = clobber install : TARGET = install echo : TARGET = echo .KEEP_STATE: all clean clobber install echo: $(SUBDIRS) .PARALLEL: $(SUBDIRS) $(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) FRC: # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Copyright (c) 2018, Joyent, Inc. SRCS = tcvn%UCS-2.c \ tcvn%UTF-8.c \ tcvn%viscii.c \ UCS-2%tcvn.c \ UCS-2%viscii.c \ UTF-8%tcvn.c \ UTF-8%viscii.c \ viscii%tcvn.c \ viscii%UCS-2.c \ viscii%UTF-8.c COMMON = ../common/ LINK_TARGETS = UCS-2BE%tcvn.so tcvn%UCS-2BE.so LINK_TARGETS += UCS-2BE%viscii.so viscii%UCS-2BE.so # needs work SMOFF += all_func_returns,deref_check dummy: all tcvn%UCS-2LE.o: $(COMMON)tcvn%UCS-2.c $(CC) $(CPPFLAGS) $(CFLAGS) -DUCS_2LE -c -o $@ $^ tcvn%UCS-2BE.o: $(COMMON)tcvn%UCS-2.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $^ viscii%UCS-2LE.o: $(COMMON)viscii%UCS-2.c $(CC) $(CPPFLAGS) $(CFLAGS) -DUCS_2LE -c -o $@ $^ viscii%UCS-2BE.o: $(COMMON)viscii%UCS-2.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $^ UCS-2LE%tcvn.o: $(COMMON)UCS-2%tcvn.c $(CC) $(CPPFLAGS) $(CFLAGS) -DUCS_2LE -c -o $@ $^ UCS-2BE%tcvn.o: $(COMMON)UCS-2%tcvn.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $^ UCS-2LE%viscii.o: $(COMMON)UCS-2%viscii.c $(CC) $(CPPFLAGS) $(CFLAGS) -DUCS_2LE -c -o $@ $^ UCS-2BE%viscii.o: $(COMMON)UCS-2%viscii.c $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $^ include $(SRC)/lib/iconv_modules/Makefile.iconv $(CREATE_LINKS): $(ICONV_LINK_TARGETS) $(SYMLINK) -f tcvn%UCS-2BE.so $(ICONV_DIR)/tcvn%UCS-2.so $(SYMLINK) -f UCS-2BE%tcvn.so $(ICONV_DIR)/UCS-2%tcvn.so $(SYMLINK) -f UCS-2BE%viscii.so $(ICONV_DIR)/UCS-2%viscii.so $(SYMLINK) -f viscii%UCS-2BE.so $(ICONV_DIR)/viscii%UCS-2.so $(TOUCH) $@ ALL_SOS = tcvn%UCS-2LE.so tcvn%UCS-2BE.so ALL_SOS += viscii%UCS-2LE.so viscii%UCS-2BE.so ALL_SOS += UCS-2LE%tcvn.so UCS-2BE%tcvn.so ALL_SOS += UCS-2LE%viscii.so UCS-2BE%viscii.so ALL_SOS += UTF-8%tcvn.so tcvn%UTF-8.so ALL_SOS += UTF-8%viscii.so viscii%UTF-8.so ALL_SOS += tcvn%viscii.so viscii%tcvn.so all: $(ALL_SOS) # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2017 Alexander Pyhalov # include ../Makefile.com include ../../Makefile.iconv.64 CFLAGS += -I.. -I../common/ ICONV_LIBS = $(ALL_SOS:%=$(ICONV_DIR_64)/%) $(ICONV_LIBS) : FILEMODE= 755 ICONV_LINK_TARGETS = $(LINK_TARGETS:%=$(ICONV_DIR_64)/%) $(ICONV_LINK_TARGETS) : FILEMODE= 755 ICONV_DIR = $(ICONV_DIR_64) install: all $(ICONV_DIR_64) .WAIT $(ICONV_LIBS) $(CREATE_LINKS) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_UNI_2_TCVN__ #include /* Unicode to TCVN mapping table */ #include "common_defs.h" #define NON_ID_CHAR '?' /* non-identified character */ typedef struct _icv_state { int _errno; /* internal errno */ } _iconv_st; /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int no_id_char_num = 0; #ifdef DEBUG fprintf(stderr, "========== iconv(): UCS-2 --> TCVN5712 ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* Rreset internal errno */ errno = 0; /* Rreset external errno */ /* Convert UCS-2 encoding to TCVN5712 */ while (*inbytesleft > 0 && *outbytesleft > 0) { unsigned long uni = 0; unsigned char c1 = 0, c2 = 0; unsigned char ch = 0; c1 = **inbuf; if (*inbytesleft <= 1 ) { errno = EINVAL; return ((size_t)-1); } (*inbuf)++; (*inbytesleft) -= 1; c2 = **inbuf; (*inbuf)++; (*inbytesleft) -= 1; #if defined(UCS_2LE) uni |= (unsigned long)c1; uni |= (unsigned long)c2<< 8; #else uni |= (unsigned long)c1<< 8; uni |= (unsigned long)c2; #endif if ( *inbytesleft > 0 && *outbytesleft <= 0 ) { errno = E2BIG; (*inbuf) -= 2; (*inbytesleft) +=2; return ((size_t)-1); } if (uni_2_tcvn(uni, &ch) == 1) { **outbuf = ch; } else { **outbuf = NON_ID_CHAR; no_id_char_num += 1; } (*outbuf) += 1; (*outbytesleft) -= 1; } return ((size_t)no_id_char_num); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_UNI_2_VISCII__ #include /* Unicode to VISCII mapping table */ #include "common_defs.h" #define NON_ID_CHAR '?' /* non-identified character */ typedef struct _icv_state { int _errno; /* internal errno */ } _iconv_st; /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int no_id_char_num = 0; #ifdef DEBUG fprintf(stderr, "========== iconv(): UCS-2 --> viscii ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* reset internal errno */ errno = 0; /* reset external errno */ /* convert UCS-2 encoding to viscii */ while (*inbytesleft > 0 && *outbytesleft > 0) { unsigned long uni = 0; unsigned char c1 = 0, c2 = 0; unsigned char ch = 0; c1 = **inbuf; if (*inbytesleft <= 1) { errno = EINVAL; return ((size_t)-1); } (*inbuf)++; (*inbytesleft) -= 1; c2 = **inbuf; (*inbuf)++; (*inbytesleft) -= 1; #if defined(UCS_2LE) uni |= (unsigned long)c1; uni |= (unsigned long)c2 << 8; #else uni |= (unsigned long)c1 << 8; uni |= (unsigned long)c2; #endif if ( *inbytesleft > 0 && *outbytesleft <= 0 ) { errno = E2BIG; return ((size_t)-1); } if (uni_2_viscii(uni, &ch) == 1) { **outbuf = ch; } else { **outbuf = NON_ID_CHAR; no_id_char_num += 1; } (*outbuf) += 1; (*outbytesleft) -= 1; } return ((size_t)no_id_char_num); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_UNI_2_TCVN__ #include /* Unicode to TCVN mapping table */ #include "common_defs.h" #define NON_ID_CHAR '?' /* non-identified character */ typedef struct _icv_state { int _errno; /* internal errno */ } _iconv_st; /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int utf8_len = 1; int no_id_char_num = 0; unsigned char *op = (unsigned char*)*inbuf; #ifdef DEBUG fprintf(stderr, "========== iconv(): UCS-2 --> TCVN5712 ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* Rreset internal errno */ errno = 0; /* Rreset external errno */ /* Convert UTF-8 encoding to TCVN5712 */ while (*inbytesleft > 0 && *outbytesleft > 0) { unsigned long uni = 0; unsigned char ch = 0; unsigned long temp1 = 0, temp2 = 0, temp3 = 0; if(0x00 == (*op & 0x80)) { /* 1 byte UTF-8 Charater.*/ uni = (unsigned short)*op; utf8_len = 1; goto conving; } if (*inbytesleft < 2) goto errexit; if ( 0xc0 == (*op & 0xe0) && 0x80 == (*(op + 1) & 0xc0) ) { /* 2 bytes UTF-8 Charater.*/ temp1 = (unsigned short)(*op & 0x1f); temp1 <<= 6; temp1 |= (unsigned short)(*(op + 1) & 0x3f); uni = temp1; utf8_len = 2; goto conving; } if (*inbytesleft < 3) goto errexit; if ( 0xe0 == (*op & 0xf0) && 0x80 == (*(op + 1) & 0xc0) && 0x80 == (*(op + 2) & 0xc0) ) { /* 3bytes UTF-8 Charater.*/ temp1 = (unsigned short)(*op &0x0f); temp1 <<= 12; temp2 = (unsigned short)(*(op+1) & 0x3F); temp2 <<= 6; temp1 = temp1 | temp2 | (unsigned short)(*(op+2) & 0x3F); uni = temp1; utf8_len = 3; goto conving; } if (*inbytesleft < 4) goto errexit; if ( 0xf0 == (*op & 0xf8) && 0x80 == (*(op + 1) & 0xc0) && 0x80 == (*(op + 2) & 0xc0) ) { /* 4bytes UTF-8 Charater.*/ temp1 = *op &0x07; temp1 <<= 18; temp2 = (*(op+1) & 0x3F); temp2 <<= 12; temp3 = (*(op+1) & 0x3F); temp3 <<= 6; temp1 = temp1 | temp2 | temp3 |(unsigned long)(*(op+2) & 0x3F); uni = temp1; utf8_len = 4; goto conving; } /* unrecognize byte. */ st->_errno = errno = EILSEQ; errno = EILSEQ; return ((size_t)-1); conving: if (uni_2_tcvn(uni, &ch) == 1) { **outbuf = ch; } else { **outbuf = NON_ID_CHAR; no_id_char_num += 1; } (*outbuf) += 1; (*outbytesleft) -= 1; op += utf8_len; (*inbytesleft) -= utf8_len; } return ((size_t)no_id_char_num); errexit: st->_errno = errno = EINVAL; errno = EINVAL; return ((size_t)-1); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_UNI_2_VISCII__ #include /* Unicode to viscii mapping table */ #include "common_defs.h" #define MSB 0x80 /* most significant bit */ #define ONEBYTE 0xff /* right most byte */ #define NON_ID_CHAR '?' /* non-identified character */ typedef struct _icv_state { char keepc[6]; /* maximum # byte of UTF8 code */ short ustate; int _errno; /* internal errno */ } _iconv_st; enum _USTATE { U0, U1, U2, U3, U4, U5, U6, U7 }; /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->ustate = U0; st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ /*========================================================= * * State Machine for interpreting UTF8 code * *========================================================= * 4 byte unicode * +----->------->------------> U5 -----> U6-------> U7---+ * | | * | 3 byte unicode | * +----->------->-------+ | * | | | * ^ v | * | 2 byte U2 ---> U3 | * | unicode v | * +------> U0 -------> U1 +-------->U4---+ | * ^ ascii | | ^ | | * | | +-------->--------->--------+ | | * | v v V * +----<---+-----<------------<------------<------------+---------+ * *=========================================================*/ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { char c1 = '\0', c2 = '\0'; int uconv_num = 0; unsigned long uni = 0; int utf8_len = 0; #ifdef DEBUG fprintf(stderr, "========== iconv(): UTF2 --> GBK2K ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->ustate = U0; st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* reset internal errno */ errno = 0; /* reset external errno */ /* a state machine for interpreting UTF8 code */ while (*inbytesleft > 0 && *outbytesleft > 0) { uchar_t first_byte; unsigned short ch = 0; switch (st->ustate) { case U0: /* * assuming ASCII in the beginning */ if ((**inbuf & MSB) == 0) { /* ASCII */ **outbuf = **inbuf; (*outbuf)++; (*outbytesleft)--; } else { if ((**inbuf & 0xe0) == 0xc0) { /* 2 byte unicode 0xc0..0xdf */ /* invalid sequence if the first char is either 0xc0 or 0xc1 */ if ( number_of_bytes_in_utf8_char[((uchar_t)**inbuf)] == ICV_TYPE_ILLEGAL_CHAR ) st->_errno = errno = EILSEQ; else { st->ustate = U1; st->keepc[0] = **inbuf; } } else if ((**inbuf & 0xf0) == 0xe0) { /* 3 byte 0xe0..0xf0 */ st->ustate = U2; st->keepc[0] = **inbuf; } else { /* four bytes of UTF-8 sequences */ if ( number_of_bytes_in_utf8_char[((uchar_t)**inbuf)] == ICV_TYPE_ILLEGAL_CHAR ) st->_errno = errno = EILSEQ; else { st->ustate = U5; st->keepc[0] = **inbuf; } } } break; case U1: /* 2 byte utf-8 encoding */ if ((**inbuf & 0xc0) == MSB) { utf8_len = 2; st->keepc[1] = **inbuf; c1 = (st->keepc[0]&0x1c)>>2; c2 = ((st->keepc[0]&0x03)<<6) | ((st->keepc[1])&0x3f); st->ustate = U4; #ifdef DEBUG fprintf(stderr, "UTF8: %02x%02x --> ", st->keepc[0]&ONEBYTE, st->keepc[1]&ONEBYTE); #endif continue; /* should not advance *inbuf */ } else { st->_errno = errno = EILSEQ; } break; case U2: /* 3 byte unicode - 2nd byte */ first_byte = (uchar_t)st->keepc[0]; /* if the first byte is 0xed, it is illegal sequence if the second * one is between 0xa0 and 0xbf because surrogate section is ill-formed */ if (((uchar_t)**inbuf) < valid_min_2nd_byte[first_byte] || ((uchar_t)**inbuf) > valid_max_2nd_byte[first_byte] ) st->_errno = errno = EILSEQ; else { st->ustate = U3; st->keepc[1] = **inbuf; } break; case U3: /* 3 byte unicode - 3rd byte */ if ((**inbuf & 0xc0) == MSB) { st->ustate = U4; utf8_len = 3; st->keepc[2] = **inbuf; c1 = ((st->keepc[0]&0x0f)<<4) | ((st->keepc[1]&0x3c)>>2); c2 = ((st->keepc[1]&0x03)<<6) | ((**inbuf)&0x3f); #ifdef DEBUG fprintf(stderr, "UTF8: %02x%02x%02x --> ", st->keepc[0]&ONEBYTE, st->keepc[1]&ONEBYTE, **inbuf&ONEBYTE); #endif continue; /* should not advance *inbuf */ } else { st->_errno = errno = EILSEQ; } break; case U4: uni = (unsigned long) ((c1 & ONEBYTE) << 8) + (c2 & ONEBYTE); if (!uni_2_viscii(uni, (unsigned char*)&ch)) { **outbuf = NON_ID_CHAR; uconv_num += utf8_len; } else { **outbuf = ch; } (*outbuf)++; (*outbytesleft)--; st->ustate = U0; break; case U5: first_byte = st->keepc[0]; /* if the first byte is 0xf0, it is illegal sequence if * the second one is between 0x80 and 0x8f * for Four-Byte UTF: U+10000..U+10FFFF * */ if (((uchar_t)**inbuf) < valid_min_2nd_byte[first_byte] || ((uchar_t)**inbuf) > valid_max_2nd_byte[first_byte] ) st->_errno = errno = EILSEQ; else { st->ustate = U6; st->keepc[1] = **inbuf; } break; case U6: if ((**inbuf & 0xc0) == MSB) { /* 0x80..0xbf */ st->ustate = U7; st->keepc[2] = **inbuf; } else st->_errno = errno = EILSEQ; break; case U7: if ((**inbuf & 0xc0) == MSB) { /* 0x80..0xbf */ /* replace with double NON_ID_CHARs */ if ( *outbytesleft < 1 ) st->_errno = errno = E2BIG; else { **outbuf = NON_ID_CHAR; (*outbytesleft) -= 1; uconv_num++; st->ustate = U0; } } else st->_errno = errno = EILSEQ; break; default: /* should never come here */ st->_errno = errno = EILSEQ; st->ustate = U0; /* reset state */ break; } if (st->_errno) { #ifdef DEBUG fprintf(stderr, "!!!!!\tst->_errno = %d\tst->ustate = %d\n", st->_errno, st->ustate); #endif break; } (*inbuf)++; (*inbytesleft)--; } if (*inbytesleft == 0 && st->ustate != U0) errno = EINVAL; if (*inbytesleft > 0 && *outbytesleft == 0) errno = E2BIG; if (errno) { int num_reversed_bytes = 0; switch (st->ustate) { case U1: num_reversed_bytes = 1; break; case U2: num_reversed_bytes = 1; break; case U3: num_reversed_bytes = 2; break; case U4: num_reversed_bytes = utf8_len - 1; break; case U5: num_reversed_bytes = 1; break; case U6: num_reversed_bytes = 2; break; case U7: num_reversed_bytes = 3; break; } /* * if error, *inbuf points to the byte following the last byte * successfully used in conversion. */ *inbuf -= num_reversed_bytes; *inbytesleft += num_reversed_bytes; st->ustate = U0; return ((size_t) -1); } return uconv_num; } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_TCVN_2_UNI__ #include /* Unicode to tcvn mapping table */ #include #include "common_defs.h" typedef struct _icv_state { int _errno; /* internal errno */ unsigned long last; } _iconv_st; #if defined(UCS_2LE) #define SET_UCS(UNI) *(*outbuf)++ = (unsigned char)((UNI)&0xff); \ *(*outbuf)++ = (unsigned char)(((UNI)>>8)&0xff); #else #define SET_UCS(UNI) *(*outbuf)++ = (unsigned char)(((UNI)>>8)&0xff); \ *(*outbuf)++ = (unsigned char)((UNI)&0xff); #endif static int binsearch(unsigned long x, Combine_map v[], int n); /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; st->last = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int unidx = -1; #ifdef DEBUG fprintf(stderr, "========== iconv(): TCVN5712 -->UCS-2 ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* Reset internal errno */ errno = 0; /* Reset external errno */ /* Convert tcvn encoding to UCS-2 */ while (*inbytesleft > 0 && *outbytesleft > 1) { unsigned long uni = 0; tcvn_2_uni((unsigned char*)*inbuf, &uni); if (st->last != 0) { if (ISCOMB_UNI(uni)) { /* * Composed characters with combine character */ unsigned int k = 0; switch (uni) { case 0x0300: k = 0; break; case 0x0301: k = 1; break; case 0x0303: k = 2; break; case 0x0309: k = 3; break; case 0x0323: k = 4; break; default: break; } unidx = binsearch(st->last, vi_comb_data, VOWEL_NUM); if (unidx >= 0) { uni = vi_comb_data[unidx].composed[k]; } else { errno = EBADF; return ((size_t)-1); } st->last = 0; } else { SET_UCS(st->last); (*outbytesleft) -= 2; } st->last = 0; } else { if (uni >= 0x0041 && uni <= 0x01b0 && ((tcvn_comp_bases_mask[(uni-0x0040) >> 5] >> (uni & 0x1f)) & 1)) { /* * uni is vowel, it's a possible match with combine character. * Buffer it. * */ st->last = uni; (*inbuf)++; (*inbytesleft)--; continue; } } SET_UCS(uni); (*outbytesleft) -= 2; (*inbuf)++; (*inbytesleft)--; } if ( *inbytesleft > 0 && *outbytesleft <= 1 ) { errno = E2BIG; st->last = 0; return ((size_t)-1); } if (st->last!=0 ) { SET_UCS(st->last); st->last = 0; (*outbytesleft) -= 2; } return ((size_t)(*inbytesleft)); } /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ static int binsearch(unsigned long x, Combine_map v[], int n) { int low = 0; int mid = 0; int high = n - 1; low = 0; while (low <= high) { mid = ((high - low)>>1) + low; if (x < v[mid].base) high = mid - 1; else if (x > v[mid].base) low = mid + 1; else /* found match */ return mid; } /* no match */ return (-1); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_TCVN_2_UNI__ #include /* Unicode to tcvn mapping table */ #include #include "common_defs.h" typedef struct _icv_state { int _errno; /* internal errno */ unsigned short last; } _iconv_st; static int binsearch(unsigned long x, Combine_map v[], int n); /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int unidx = -1; #ifdef DEBUG fprintf(stderr, "========== iconv(): TCVN5712 -->UCS-2 ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* Reset internal errno */ errno = 0; /* Reset external errno */ /* Convert tcvn encoding to UCS-2 */ while (*inbytesleft > 0 && *outbytesleft > 0) { unsigned long uni = 0; tcvn_2_uni((unsigned char*)*inbuf, &uni); if (st->last != 0) { if (ISCOMB_UNI(uni)) { /* * Composed characters with combine character */ unsigned int k = 0; switch (uni) { case 0x0300: k = 0; break; case 0x0301: k = 1; break; case 0x0303: k = 2; break; case 0x0309: k = 3; break; case 0x0323: k = 4; break; default: break; } unidx = binsearch(st->last, vi_comb_data, VOWEL_NUM); if (unidx >= 0) { uni = vi_comb_data[unidx].composed[k]; } else { errno = EBADF; } st->last = 0; } else { if (st->last < 0x80) { *(*outbuf)++ = (char)st->last; (*outbytesleft) -= 1; } else if (st->last >= 0x0080 && st->last <= 0x07ff) { if (*outbytesleft < 2) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((st->last >> 6) & 0x1f) | 0xc0; *(*outbuf)++ = (char)(st->last & 0x3f) | 0x80; (*outbytesleft) -= 2; } else if (st->last >= 0x0800) { if (*outbytesleft < 3) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((st->last >> 12) & 0xf) | 0xe0; *(*outbuf)++ = (char)((st->last >>6) & 0x3f) | 0x80; *(*outbuf)++ = (char)(st->last & 0x3f) | 0x80; (*outbytesleft) -= 3; } } st->last = 0; } else { if (uni >= 0x0041 && uni <= 0x01b0 && ((tcvn_comp_bases_mask[(uni-0x0040) >> 5] >> (uni & 0x1f)) & 1)) { /* * uni is vowel, it's a possible match with combine character. * Buffer it. * */ st->last = uni; (*inbuf)++; (*inbytesleft)--; continue; } } if (uni < 0x80) { *(*outbuf)++ = (char)uni; (*outbytesleft) -= 1; } else if (uni >= 0x0080 && uni <= 0x07ff) { if (*outbytesleft < 2) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((uni >> 6) & 0x1f) | 0xc0; *(*outbuf)++ = (char)(uni & 0x3f) | 0x80; (*outbytesleft) -= 2; } else if (uni >= 0x0800 && uni <= 0xffff) { if (*outbytesleft < 3) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((uni >> 12) & 0xf) | 0xe0; *(*outbuf)++ = (char)((uni >>6) & 0x3f) | 0x80; *(*outbuf)++ = (char)(uni & 0x3f) | 0x80; (*outbytesleft) -= 3; } (*inbuf)++; (*inbytesleft)--; } if ( *inbytesleft > 0 && *outbytesleft <= 0 ) { errno = E2BIG; st->last = 0; return ((size_t)-1); } if (st->last !=0 ) { if (st->last < 0x80) { *(*outbuf)++ = (char)st->last; (*outbytesleft) -= 1; } else if (st->last >= 0x0080 && st->last <= 0x07ff) { if (*outbytesleft < 2 ) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((st->last >> 6) & 0x1f) | 0xc0; *(*outbuf)++ = (char)(st->last & 0x3f) | 0x80; (*outbytesleft) -= 2; } else if (st->last >= 0x0800) { if (*outbytesleft < 3) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((st->last >> 12) & 0xf) | 0xe0; *(*outbuf)++ = (char)((st->last >>6) & 0x3f) | 0x80; *(*outbuf)++ = (char)(st->last & 0x3f) | 0x80; (*outbytesleft) -= 3; } st->last = 0; } return ((size_t)(*inbytesleft)); } /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ static int binsearch(unsigned long x, Combine_map v[], int n) { int low = 0; int mid = 0; int high = n - 1; low = 0; while (low <= high) { mid = (low + high) / 2; if (x < v[mid].base) high = mid - 1; else if (x > v[mid].base) low = mid + 1; else /* found match */ return mid; } /* no match */ return (-1); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_TCVN_2_VISCII__ #include /* VISCII <-> TCVN mapping table */ #include #include "common_defs.h" #define NON_ID_CHAR '?' /* non-identified character */ typedef struct _icv_state { int _errno; /* internal errno */ unsigned short last; } _iconv_st; static int binsearch(unsigned short x, Combine_map_tcvn v[], int n); /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; st->last = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int unconv = 0; int idx = -1; unsigned char chout = 0; #ifdef DEBUG fprintf(stderr, "========== iconv(): TCVN5712 -->UCS-2 ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* Reset internal errno */ errno = 0; /* Reset external errno */ /* Convert tcvn encoding to UCS-2 */ while (*inbytesleft > 0 && *outbytesleft > 0) { unsigned char ch = 0; if (st->last != 0) { if (ISCOMB_TCVN((unsigned char)**inbuf)) { /* * Composed characters with combine character */ idx = binsearch(st->last, tcvn_comb_data, VOWEL_NUM); if (idx >= 0) { ch = tcvn_comb_data[idx].composed[(unsigned char)**inbuf - 0xb0]; } else { errno = EBADF; return ((size_t)-1); } st->last = 0; } else { tcvn_2_viscii(st->last, &chout); if (st->last != 0x0 && chout == 0x0) { unconv++; chout = NON_ID_CHAR; } *(*outbuf)++ = chout; (*outbytesleft) -= 1; ch = (unsigned char)**inbuf; } st->last = 0; } else { ch = (unsigned char)**inbuf; if (ch >= 0x41 && ch <= 0xad && ((tcvn_comp_bases_mask0[(ch-0x40) >> 5] >> (ch & 0x1f)) & 1)) { /* * uni is vowel, it's a possible match with combine character. * Buffer it. * */ st->last = ch; (*inbuf)++; (*inbytesleft)--; continue; } } tcvn_2_viscii(ch, &chout); if (ch != 0x0 && chout == 0x0) { unconv++; chout = NON_ID_CHAR; } *(*outbuf)++ = chout; (*outbytesleft) -= 1; (*inbuf)++; (*inbytesleft)--; } if ( *inbytesleft > 0 && *outbytesleft <= 0 ) { errno = E2BIG; st->last = 0; return ((size_t)-1); } if (st->last != 0) { tcvn_2_viscii(st->last, &chout); if (**inbuf != 0x0 && chout == 0x0) { unconv++; chout = NON_ID_CHAR; } st->last = 0; *(*outbuf)++ = chout; (*outbytesleft) -= 1; } return ((size_t)unconv); } /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ static int binsearch(unsigned short x, Combine_map_tcvn v[], int n) { int low = 0; int mid = 0; int high = n - 1; low = 0; while (low <= high) { mid = (low + high) / 2; if (x < (unsigned short)v[mid].base) high = mid - 1; else if (x > (unsigned short)v[mid].base) low = mid + 1; else /* found match */ return mid; } /* no match */ return (-1); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_VISCII_2_UNI__ #include /* Unicode to viscii mapping table */ #include "common_defs.h" typedef struct _icv_state { int _errno; /* internal errno */ } _iconv_st; /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { #ifdef DEBUG fprintf(stderr, "========== iconv(): viscii -->UCS-2 ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* reset internal errno */ errno = 0; /* reset external errno */ /* convert viscii encoding to UCS-2 */ while (*inbytesleft > 0 && *outbytesleft > 1) { unsigned long uni = 0; viscii_2_uni((unsigned char*)*inbuf, &uni); #if defined(UCS_2LE) *(*outbuf)++ = (unsigned char)(uni&0xff); *(*outbuf)++ = (unsigned char)((uni>>8)&0xff); #else *(*outbuf)++ = (unsigned char)((uni>>8)&0xff); *(*outbuf)++ = (unsigned char)((uni)&0xff); #endif (*outbytesleft) -= 2; (*inbuf)++; (*inbytesleft)--; } if ( *inbytesleft > 0 && *outbytesleft <= 1 ) { errno = E2BIG; return ((size_t)-1); } return ((size_t)(*inbytesleft)); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_VISCII_2_UNI__ #include /* Unicode to viscii mapping table */ #include "common_defs.h" typedef struct _icv_state { char keepc[4]; /* maximum # byte of UCS code */ int _errno; /* internal errno */ } _iconv_st; /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { #ifdef DEBUG fprintf(stderr, "========== iconv(): viscii -->UTF-8 ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* reset internal errno */ errno = 0; /* reset external errno */ /* convert viscii encoding to UTF-8 */ while (*inbytesleft > 0 && *outbytesleft > 0) { unsigned long uni = 0; viscii_2_uni((unsigned char*)*inbuf, &uni); if (uni < 0x80) { *(*outbuf)++ = (char)uni; (*outbytesleft) -= 1; } else if (uni >= 0x0080 && uni <= 0x07ff) { if (*outbytesleft < 2 ) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((uni >> 6) & 0x1f) | 0xc0; *(*outbuf)++ = (char)(uni & 0x3f) | 0x80; *outbytesleft -= 2; } else if (uni >= 0x0800 && uni <= 0xffff) { if (*outbytesleft < 3) { errno = E2BIG; return((size_t)-1); } *(*outbuf)++ = (char)((uni >> 12) & 0xf) | 0xe0; *(*outbuf)++ = (char)((uni >>6) & 0x3f) | 0x80; *(*outbuf)++ = (char)(uni & 0x3f) | 0x80; *outbytesleft -= 3; } (*inbuf)++; (*inbytesleft)--; } if ( *inbytesleft > 0 && *outbytesleft <= 0 ) { errno = E2BIG; return ((size_t)-1); } return ((size_t)(*inbytesleft)); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, by Sun Microsystems, Inc. * All rights reserved. */ #include #include #include #include #define __NEED_VISCII_2_TCVN__ #include /* VISCII <-> TCVN mapping table */ #include "common_defs.h" #define NON_ID_CHAR '?' /* non-identified character */ typedef struct _icv_state { int _errno; /* internal errno */ } _iconv_st; /* * Open; called from iconv_open() */ void * _icv_open() { _iconv_st *st; if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) { errno = ENOMEM; return ((void *) -1); } st->_errno = 0; return ((void *) st); } /* * Close; called from iconv_close() */ void _icv_close(_iconv_st *st) { if (!st) errno = EBADF; else free(st); } /* * Actual conversion; called from iconv() */ size_t _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int unconv = 0; #ifdef DEBUG fprintf(stderr, "========== iconv(): viscii -->tcvn ==========\n"); #endif if (st == NULL) { errno = EBADF; return ((size_t) -1); } if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */ st->_errno = 0; return ((size_t) 0); } st->_errno = 0; /* reset internal errno */ errno = 0; /* reset external errno */ /* convert viscii encoding to tcvn. */ while (*inbytesleft > 0 && *outbytesleft > 0) { unsigned char ch = 0; viscii_2_tcvn((unsigned char*)*inbuf, &ch); if (**inbuf != 0x0 && ch == 0) { unconv++; ch = NON_ID_CHAR; } **outbuf = ch; (*outbuf) += 1; (*outbytesleft) -= 1; (*inbuf)++; (*inbytesleft)--; } if ( *inbytesleft > 0 && *outbytesleft <= 0 ) { errno = E2BIG; return ((size_t)-1); } return ((size_t)unconv); }