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$"); 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; 67 char *v, *e; 68 69 rl->sgetrune = _EUC_sgetrune; 70 rl->sputrune = _EUC_sputrune; 71 72 if (!rl->variable) { 73 free(rl); 74 return (EFTYPE); 75 } 76 v = (char *) rl->variable; 77 78 while (*v == ' ' || *v == '\t') 79 ++v; 80 81 if ((ei = malloc(sizeof(_EucInfo))) == NULL) { 82 free(rl); 83 return (ENOMEM); 84 } 85 __mb_cur_max = 0; 86 for (x = 0; x < 4; ++x) { 87 ei->count[x] = (int) strtol(v, &e, 0); 88 if (v == e || !(v = e)) { 89 free(rl); 90 free(ei); 91 return (EFTYPE); 92 } 93 if (__mb_cur_max < ei->count[x]) 94 __mb_cur_max = ei->count[x]; 95 while (*v == ' ' || *v == '\t') 96 ++v; 97 ei->bits[x] = (int) strtol(v, &e, 0); 98 if (v == e || !(v = e)) { 99 free(rl); 100 free(ei); 101 return (EFTYPE); 102 } 103 while (*v == ' ' || *v == '\t') 104 ++v; 105 } 106 ei->mask = (int)strtol(v, &e, 0); 107 if (v == e || !(v = e)) { 108 free(rl); 109 free(ei); 110 return (EFTYPE); 111 } 112 if (sizeof(_EucInfo) <= rl->variable_len) { 113 memcpy(rl->variable, ei, sizeof(_EucInfo)); 114 free(ei); 115 } else { 116 rl->variable = &ei; 117 } 118 rl->variable_len = sizeof(_EucInfo); 119 _CurrentRuneLocale = rl; 120 return (0); 121 } 122 123 #define CEI ((_EucInfo *)(_CurrentRuneLocale->variable)) 124 125 #define _SS2 0x008e 126 #define _SS3 0x008f 127 128 #define GR_BITS 0x80808080 /* XXX: to be fixed */ 129 130 static inline int 131 _euc_set(c) 132 u_int c; 133 { 134 c &= 0xff; 135 136 return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); 137 } 138 rune_t 139 _EUC_sgetrune(string, n, result) 140 const char *string; 141 size_t n; 142 char const **result; 143 { 144 rune_t rune = 0; 145 int len, set; 146 147 if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) { 148 if (result) 149 *result = string; 150 return (_INVALID_RUNE); 151 } 152 switch (set) { 153 case 3: 154 case 2: 155 --len; 156 ++string; 157 /* FALLTHROUGH */ 158 case 1: 159 case 0: 160 while (len-- > 0) 161 rune = (rune << 8) | ((u_int)(*string++) & 0xff); 162 break; 163 } 164 if (result) 165 *result = string; 166 return ((rune & ~CEI->mask) | CEI->bits[set]); 167 } 168 169 int 170 _EUC_sputrune(c, string, n, result) 171 rune_t c; 172 char *string, **result; 173 size_t n; 174 { 175 rune_t m = c & CEI->mask; 176 rune_t nm = c & ~m; 177 int i, len; 178 179 if (m == CEI->bits[1]) { 180 CodeSet1: 181 /* Codeset 1: The first byte must have 0x80 in it. */ 182 i = len = CEI->count[1]; 183 if (n >= len) { 184 if (result) 185 *result = string + len; 186 while (i-- > 0) 187 *string++ = (nm >> (i << 3)) | 0x80; 188 } else 189 if (result) 190 *result = (char *) 0; 191 } else { 192 if (m == CEI->bits[0]) { 193 i = len = CEI->count[0]; 194 if (n < len) { 195 if (result) 196 *result = NULL; 197 return (len); 198 } 199 } else 200 if (m == CEI->bits[2]) { 201 i = len = CEI->count[2]; 202 if (n < len) { 203 if (result) 204 *result = NULL; 205 return (len); 206 } 207 *string++ = _SS2; 208 --i; 209 /* SS2 designates G2 into GR */ 210 nm |= GR_BITS; 211 } else 212 if (m == CEI->bits[3]) { 213 i = len = CEI->count[3]; 214 if (n < len) { 215 if (result) 216 *result = NULL; 217 return (len); 218 } 219 *string++ = _SS3; 220 --i; 221 /* SS3 designates G3 into GR */ 222 nm |= GR_BITS; 223 } else 224 goto CodeSet1; /* Bletch */ 225 while (i-- > 0) 226 *string++ = (nm >> (i << 3)) & 0xff; 227 if (result) 228 *result = string; 229 } 230 return (len); 231 } 232