1*60471Sbostic /*- 2*60471Sbostic * Copyright (c) 1993 The Regents of the University of California. 3*60471Sbostic * All rights reserved. 4*60471Sbostic * 5*60471Sbostic * This code is derived from software contributed to Berkeley by 6*60471Sbostic * Paul Borman at Krystal Technologies. 7*60471Sbostic * 8*60471Sbostic * %sccs.include.redist.c% 9*60471Sbostic */ 10*60471Sbostic 11*60471Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*60471Sbostic static char sccsid[] = "@(#)euc.c 5.1 (Berkeley) 05/26/93"; 13*60471Sbostic #endif /* LIBC_SCCS and not lint */ 14*60471Sbostic 15*60471Sbostic #include <sys/types.h> 16*60471Sbostic 17*60471Sbostic #include <errno.h> 18*60471Sbostic #include <rune.h> 19*60471Sbostic #include <stddef.h> 20*60471Sbostic #include <stdio.h> 21*60471Sbostic #include <stdlib.h> 22*60471Sbostic 23*60471Sbostic rune_t _EUC_sgetrune __P((const char *, size_t, char const **)); 24*60471Sbostic int _EUC_sputrune __P((rune_t, char *, size_t, char **)); 25*60471Sbostic 26*60471Sbostic typedef struct { 27*60471Sbostic int count[4]; 28*60471Sbostic rune_t bits[4]; 29*60471Sbostic rune_t mask; 30*60471Sbostic } _EucInfo; 31*60471Sbostic 32*60471Sbostic int 33*60471Sbostic _EUC_init(rl) 34*60471Sbostic _RuneLocale *rl; 35*60471Sbostic { 36*60471Sbostic _EucInfo *ei; 37*60471Sbostic int x; 38*60471Sbostic char *v, *e; 39*60471Sbostic 40*60471Sbostic rl->sgetrune = _EUC_sgetrune; 41*60471Sbostic rl->sputrune = _EUC_sputrune; 42*60471Sbostic 43*60471Sbostic if (!rl->variable) { 44*60471Sbostic free(rl); 45*60471Sbostic return (EFTYPE); 46*60471Sbostic } 47*60471Sbostic v = (char *) rl->variable; 48*60471Sbostic 49*60471Sbostic while (*v == ' ' || *v == '\t') 50*60471Sbostic ++v; 51*60471Sbostic 52*60471Sbostic if ((ei = malloc(sizeof(_EucInfo))) == NULL) { 53*60471Sbostic free(rl); 54*60471Sbostic return (ENOMEM); 55*60471Sbostic } 56*60471Sbostic for (x = 0; x < 4; ++x) { 57*60471Sbostic ei->count[x] = (int) strtol(v, &e, 0); 58*60471Sbostic if (v == e || !(v = e)) { 59*60471Sbostic free(rl); 60*60471Sbostic free(ei); 61*60471Sbostic return (EFTYPE); 62*60471Sbostic } 63*60471Sbostic while (*v == ' ' || *v == '\t') 64*60471Sbostic ++v; 65*60471Sbostic ei->bits[x] = (int) strtol(v, &e, 0); 66*60471Sbostic if (v == e || !(v = e)) { 67*60471Sbostic free(rl); 68*60471Sbostic free(ei); 69*60471Sbostic return (EFTYPE); 70*60471Sbostic } 71*60471Sbostic while (*v == ' ' || *v == '\t') 72*60471Sbostic ++v; 73*60471Sbostic } 74*60471Sbostic ei->mask = (int)strtol(v, &e, 0); 75*60471Sbostic if (v == e || !(v = e)) { 76*60471Sbostic free(rl); 77*60471Sbostic free(ei); 78*60471Sbostic return (EFTYPE); 79*60471Sbostic } 80*60471Sbostic if (sizeof(_EucInfo) <= rl->variable_len) { 81*60471Sbostic memcpy(rl->variable, ei, sizeof(_EucInfo)); 82*60471Sbostic free(ei); 83*60471Sbostic } else { 84*60471Sbostic rl->variable = &ei; 85*60471Sbostic } 86*60471Sbostic rl->variable_len = sizeof(_EucInfo); 87*60471Sbostic _CurrentRuneLocale = rl; 88*60471Sbostic __mb_cur_max = 3; 89*60471Sbostic return (0); 90*60471Sbostic } 91*60471Sbostic 92*60471Sbostic #define CEI ((_EucInfo *)(_CurrentRuneLocale->variable)) 93*60471Sbostic 94*60471Sbostic #define _SS2 0x008e 95*60471Sbostic #define _SS3 0x008f 96*60471Sbostic 97*60471Sbostic static inline int 98*60471Sbostic _euc_set(c) 99*60471Sbostic u_int c; 100*60471Sbostic { 101*60471Sbostic c &= 0xff; 102*60471Sbostic 103*60471Sbostic return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); 104*60471Sbostic } 105*60471Sbostic rune_t 106*60471Sbostic _EUC_sgetrune(string, n, result) 107*60471Sbostic const char *string; 108*60471Sbostic size_t n; 109*60471Sbostic char const **result; 110*60471Sbostic { 111*60471Sbostic rune_t rune = 0; 112*60471Sbostic int len, set; 113*60471Sbostic 114*60471Sbostic if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) { 115*60471Sbostic if (result) 116*60471Sbostic *result = string; 117*60471Sbostic return (_INVALID_RUNE); 118*60471Sbostic } 119*60471Sbostic switch (set) { 120*60471Sbostic case 3: 121*60471Sbostic case 2: 122*60471Sbostic --len; 123*60471Sbostic ++string; 124*60471Sbostic /* FALLTHROUGH */ 125*60471Sbostic case 1: 126*60471Sbostic case 0: 127*60471Sbostic while (len-- > 0) 128*60471Sbostic rune = (rune << 8) | ((u_int)(*string++) & 0xff); 129*60471Sbostic break; 130*60471Sbostic } 131*60471Sbostic if (result) 132*60471Sbostic *result = string; 133*60471Sbostic return ((rune & ~CEI->mask) | CEI->bits[set]); 134*60471Sbostic } 135*60471Sbostic 136*60471Sbostic int 137*60471Sbostic _EUC_sputrune(c, string, n, result) 138*60471Sbostic rune_t c; 139*60471Sbostic char *string, **result; 140*60471Sbostic size_t n; 141*60471Sbostic { 142*60471Sbostic rune_t m = c & CEI->mask; 143*60471Sbostic rune_t nm = c & ~m; 144*60471Sbostic int i, len; 145*60471Sbostic 146*60471Sbostic if (m == CEI->bits[1]) { 147*60471Sbostic CodeSet1: 148*60471Sbostic /* Codeset 1: The first byte must have 0x80 in it. */ 149*60471Sbostic i = len = CEI->count[1]; 150*60471Sbostic if (n >= len) { 151*60471Sbostic if (result) 152*60471Sbostic *result = string + len; 153*60471Sbostic while (i-- > 0) 154*60471Sbostic *string++ = (nm >> (i << 3)) | 0x80; 155*60471Sbostic } else 156*60471Sbostic if (result) 157*60471Sbostic *result = (char *) 0; 158*60471Sbostic } else { 159*60471Sbostic if (m == CEI->bits[0]) { 160*60471Sbostic i = len = CEI->count[0]; 161*60471Sbostic if (n < len) { 162*60471Sbostic if (result) 163*60471Sbostic *result = NULL; 164*60471Sbostic return (len); 165*60471Sbostic } 166*60471Sbostic } else 167*60471Sbostic if (m == CEI->bits[2]) { 168*60471Sbostic i = len = CEI->count[2]; 169*60471Sbostic if (n < len) { 170*60471Sbostic if (result) 171*60471Sbostic *result = NULL; 172*60471Sbostic return (len); 173*60471Sbostic } 174*60471Sbostic *string++ = _SS2; 175*60471Sbostic --i; 176*60471Sbostic } else 177*60471Sbostic if (m == CEI->bits[3]) { 178*60471Sbostic i = len = CEI->count[3]; 179*60471Sbostic if (n < len) { 180*60471Sbostic if (result) 181*60471Sbostic *result = NULL; 182*60471Sbostic return (len); 183*60471Sbostic } 184*60471Sbostic *string++ = _SS3; 185*60471Sbostic --i; 186*60471Sbostic } else 187*60471Sbostic goto CodeSet1; /* Bletch */ 188*60471Sbostic while (i-- > 0) 189*60471Sbostic *string++ = (nm >> (i << 3)) & 0xff; 190*60471Sbostic if (result) 191*60471Sbostic *result = string; 192*60471Sbostic } 193*60471Sbostic return (len); 194*60471Sbostic } 195