1 /*- 2 * Copyright (c) 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Paul Borman at Krystal Technologies. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #if defined(LIBC_SCCS) && !defined(lint) 38 static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93"; 39 #endif /* LIBC_SCCS and not lint */ 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD: src/lib/libc/locale/euc.c,v 1.3.6.2 2002/08/12 11:17:37 ache Exp $"); 42 43 #include <sys/types.h> 44 45 #include <errno.h> 46 #include <rune.h> 47 #include <stddef.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 52 rune_t _EUC_sgetrune(const char *, size_t, char const **); 53 int _EUC_sputrune(rune_t, char *, size_t, char **); 54 55 typedef struct { 56 int count[4]; 57 rune_t bits[4]; 58 rune_t mask; 59 } _EucInfo; 60 61 int 62 _EUC_init(rl) 63 _RuneLocale *rl; 64 { 65 _EucInfo *ei; 66 int x, new__mb_cur_max; 67 char *v, *e; 68 69 rl->sgetrune = _EUC_sgetrune; 70 rl->sputrune = _EUC_sputrune; 71 72 if (rl->variable == NULL) 73 return (EFTYPE); 74 75 v = (char *)rl->variable; 76 77 while (*v == ' ' || *v == '\t') 78 ++v; 79 80 if ((ei = malloc(sizeof(_EucInfo))) == NULL) 81 return (errno == 0 ? ENOMEM : errno); 82 83 new__mb_cur_max = 0; 84 for (x = 0; x < 4; ++x) { 85 ei->count[x] = (int)strtol(v, &e, 0); 86 if (v == e || !(v = e)) { 87 free(ei); 88 return (EFTYPE); 89 } 90 if (new__mb_cur_max < ei->count[x]) 91 new__mb_cur_max = ei->count[x]; 92 while (*v == ' ' || *v == '\t') 93 ++v; 94 ei->bits[x] = (int)strtol(v, &e, 0); 95 if (v == e || !(v = e)) { 96 free(ei); 97 return (EFTYPE); 98 } 99 while (*v == ' ' || *v == '\t') 100 ++v; 101 } 102 ei->mask = (int)strtol(v, &e, 0); 103 if (v == e || !(v = e)) { 104 free(ei); 105 return (EFTYPE); 106 } 107 rl->variable = ei; 108 rl->variable_len = sizeof(_EucInfo); 109 _CurrentRuneLocale = rl; 110 __mb_cur_max = new__mb_cur_max; 111 return (0); 112 } 113 114 #define CEI ((_EucInfo *)(_CurrentRuneLocale->variable)) 115 116 #define _SS2 0x008e 117 #define _SS3 0x008f 118 119 #define GR_BITS 0x80808080 /* XXX: to be fixed */ 120 121 static inline int 122 _euc_set(c) 123 u_int c; 124 { 125 c &= 0xff; 126 127 return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); 128 } 129 rune_t 130 _EUC_sgetrune(string, n, result) 131 const char *string; 132 size_t n; 133 char const **result; 134 { 135 rune_t rune = 0; 136 int len, set; 137 138 if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) { 139 if (result) 140 *result = string; 141 return (_INVALID_RUNE); 142 } 143 switch (set) { 144 case 3: 145 case 2: 146 --len; 147 ++string; 148 /* FALLTHROUGH */ 149 case 1: 150 case 0: 151 while (len-- > 0) 152 rune = (rune << 8) | ((u_int)(*string++) & 0xff); 153 break; 154 } 155 if (result) 156 *result = string; 157 return ((rune & ~CEI->mask) | CEI->bits[set]); 158 } 159 160 int 161 _EUC_sputrune(c, string, n, result) 162 rune_t c; 163 char *string, **result; 164 size_t n; 165 { 166 rune_t m = c & CEI->mask; 167 rune_t nm = c & ~m; 168 int i, len; 169 170 if (m == CEI->bits[1]) { 171 CodeSet1: 172 /* Codeset 1: The first byte must have 0x80 in it. */ 173 i = len = CEI->count[1]; 174 if (n >= len) { 175 if (result) 176 *result = string + len; 177 while (i-- > 0) 178 *string++ = (nm >> (i << 3)) | 0x80; 179 } else 180 if (result) 181 *result = (char *) 0; 182 } else { 183 if (m == CEI->bits[0]) { 184 i = len = CEI->count[0]; 185 if (n < len) { 186 if (result) 187 *result = NULL; 188 return (len); 189 } 190 } else 191 if (m == CEI->bits[2]) { 192 i = len = CEI->count[2]; 193 if (n < len) { 194 if (result) 195 *result = NULL; 196 return (len); 197 } 198 *string++ = _SS2; 199 --i; 200 /* SS2 designates G2 into GR */ 201 nm |= GR_BITS; 202 } else 203 if (m == CEI->bits[3]) { 204 i = len = CEI->count[3]; 205 if (n < len) { 206 if (result) 207 *result = NULL; 208 return (len); 209 } 210 *string++ = _SS3; 211 --i; 212 /* SS3 designates G3 into GR */ 213 nm |= GR_BITS; 214 } else 215 goto CodeSet1; /* Bletch */ 216 while (i-- > 0) 217 *string++ = (nm >> (i << 3)) & 0xff; 218 if (result) 219 *result = string; 220 } 221 return (len); 222 } 223