1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1999 by Sun Microsystems, Inc. 23 * All rights reserved. 24 */ 25 26 27 #include <stdlib.h> 28 #include <errno.h> 29 #include <sys/types.h> 30 #include <sys/isa_defs.h> 31 #include "utf_ebcdic_to_utf8.h" 32 33 void * 34 _icv_open() 35 { 36 return((void *)MAGIC_NUMBER); 37 } 38 39 40 void 41 _icv_close(int *cd) 42 { 43 if (! cd || cd != (int *)MAGIC_NUMBER) 44 errno = EBADF; 45 } 46 47 48 #define OUTBUF_SIZE_CHECK(sz) \ 49 if ((obtail - ob) < (sz)) { \ 50 ib = ib_org;\ 51 errno = E2BIG; \ 52 ret_val = (size_t)-1; \ 53 break; \ 54 } 55 56 #define UTFEBICDIC_I8(utfe) utf_ebcdic_to_i8[(utfe)] 57 58 size_t 59 _icv_iconv(int *cd, char **inbuf, size_t *inbufleft, char **outbuf, 60 size_t *outbufleft) 61 { 62 size_t ret_val = 0; 63 uchar_t *ib; 64 uchar_t *ob; 65 uchar_t *ibtail; 66 uchar_t *obtail; 67 68 if (cd != (int *)MAGIC_NUMBER) { 69 errno = EBADF; 70 return((size_t)-1); 71 } 72 73 if (!inbuf || !(*inbuf)) 74 return((size_t)0); 75 76 ib = (uchar_t *)*inbuf; 77 ob = (uchar_t *)*outbuf; 78 ibtail = ib + *inbufleft; 79 obtail = ob + *outbufleft; 80 81 while (ib < ibtail) { 82 uchar_t *ib_org; 83 uint_t u4; 84 signed char sz; /* must be signed for loop condition */ 85 86 sz = number_of_bytes_in_utf_ebcidc[*ib]; 87 if ((sz > UTF_EBCDIC_LEAD_OCTET_MAX) || 88 (sz < UTF_EBCDIC_LEAD_OCTET_MIN)) { 89 errno = EILSEQ; 90 ret_val = (size_t)-1; 91 break; 92 } 93 /* sz == 0 means control character. and it need 1 byte */ 94 if ((ibtail - ib) < ((sz == 0)? 1: sz)) { 95 errno = EINVAL; 96 ret_val = (size_t)-1; 97 break; 98 } 99 100 ib_org = ib; 101 102 u4 = (UTFEBICDIC_I8(*ib++) & utf_ebcdic_masks_tbl[sz]); 103 104 /* correct size */ 105 if (sz == 0){ 106 sz = 1; 107 } 108 for (; sz > 1; sz--) { 109 if (number_of_bytes_in_utf_ebcidc[*ib] != 110 UTF_EBCDIC_TRAILING_OCTET) { 111 ib = ib_org; 112 errno = EILSEQ; 113 ret_val = (size_t)-1; 114 goto illegal_char_err; 115 } 116 u4 = ((u4 << UTF_EBCDIC_BIT_SHIFT) | 117 (((uint_t)(UTFEBICDIC_I8(*ib))) 118 & UTF_EBCDIC_BIT_MASK)); 119 ib++; 120 } 121 122 if (u4 <= 0x7f) { 123 OUTBUF_SIZE_CHECK(1); 124 *ob++ = (uchar_t)u4; 125 } else if (u4 <= 0x7ff) { 126 OUTBUF_SIZE_CHECK(2); 127 *ob++ = (uchar_t)(0xc0 | ((u4 & 0x07c0) >> 6)); 128 *ob++ = (uchar_t)(0x80 | (u4 & 0x003f)); 129 } else if (u4 <= 0xd7ff) { 130 OUTBUF_SIZE_CHECK(3); 131 *ob++ = (uchar_t)(0xe0 | ((u4 & 0x0f000) >> 12)); 132 *ob++ = (uchar_t)(0x80 | ((u4 & 0x00fc0) >> 6)); 133 *ob++ = (uchar_t)(0x80 | (u4 & 0x0003f)); 134 } else if (u4 <= 0x00dfff) { 135 /* S zone */ 136 errno = EILSEQ; 137 ret_val = (size_t)-1; 138 break; 139 } else if (u4 <= 0x00fffd) { 140 OUTBUF_SIZE_CHECK(3); 141 *ob++ = (uchar_t)(0xe0 | ((u4 & 0x0f000) >> 12)); 142 *ob++ = (uchar_t)(0x80 | ((u4 & 0x00fc0) >> 6)); 143 *ob++ = (uchar_t)(0x80 | (u4 & 0x0003f)); 144 } else if (u4 <= 0x00ffff) { 145 errno = EILSEQ; 146 ret_val = (size_t)-1; 147 break; 148 } else if (u4 <= 0x1fffff) { 149 OUTBUF_SIZE_CHECK(4); 150 *ob++ = (uchar_t)(0xf0 | ((u4 & 0x01c0000) >> 18)); 151 *ob++ = (uchar_t)(0x80 | ((u4 & 0x003f000) >> 12)); 152 *ob++ = (uchar_t)(0x80 | ((u4 & 0x0000fc0) >> 6)); 153 *ob++ = (uchar_t)(0x80 | (u4 & 0x000003f)); 154 } else if (u4 <= 0x3ffffff) { 155 OUTBUF_SIZE_CHECK(5); 156 *ob++ = (uchar_t)(0xf8 | ((u4 & 0x03000000) >> 24)); 157 *ob++ = (uchar_t)(0x80 | ((u4 & 0x00fc0000) >> 18)); 158 *ob++ = (uchar_t)(0x80 | ((u4 & 0x0003f000) >> 12)); 159 *ob++ = (uchar_t)(0x80 | ((u4 & 0x00000fc0) >> 6)); 160 *ob++ = (uchar_t)(0x80 | (u4 & 0x0000003f)); 161 } else if (u4 <= 0x7fffffff) { 162 OUTBUF_SIZE_CHECK(6); 163 *ob++ = (uchar_t)(0xfc | ((u4 & 0x40000000) >> 30)); 164 *ob++ = (uchar_t)(0x80 | ((u4 & 0x3f000000) >> 24)); 165 *ob++ = (uchar_t)(0x80 | ((u4 & 0x00fc0000) >> 18)); 166 *ob++ = (uchar_t)(0x80 | ((u4 & 0x0003f000) >> 12)); 167 *ob++ = (uchar_t)(0x80 | ((u4 & 0x00000fc0) >> 6)); 168 *ob++ = (uchar_t)(0x80 | (u4 & 0x0000003f)); 169 170 } else { 171 ib = ib_org; 172 errno = EILSEQ; 173 ret_val = (size_t)-1; 174 break; 175 } 176 } 177 178 illegal_char_err: 179 *inbuf = (char *)ib; 180 *inbufleft = ibtail - ib; 181 *outbuf = (char *)ob; 182 *outbufleft = obtail - ob; 183 184 return(ret_val); 185 } 186