euc.c revision 94122
133965Sjdp/*- 2218822Sdim * Copyright (c) 1993 3218822Sdim * The Regents of the University of California. All rights reserved. 433965Sjdp * 533965Sjdp * This code is derived from software contributed to Berkeley by 6130561Sobrien * Paul Borman at Krystal Technologies. 733965Sjdp * 8130561Sobrien * Redistribution and use in source and binary forms, with or without 9130561Sobrien * modification, are permitted provided that the following conditions 10130561Sobrien * are met: 11130561Sobrien * 1. Redistributions of source code must retain the above copyright 1233965Sjdp * notice, this list of conditions and the following disclaimer. 13130561Sobrien * 2. Redistributions in binary form must reproduce the above copyright 14130561Sobrien * notice, this list of conditions and the following disclaimer in the 15130561Sobrien * documentation and/or other materials provided with the distribution. 16130561Sobrien * 3. All advertising materials mentioning features or use of this software 1733965Sjdp * must display the following acknowledgement: 18130561Sobrien * This product includes software developed by the University of 19130561Sobrien * California, Berkeley and its contributors. 20218822Sdim * 4. Neither the name of the University nor the names of its contributors 2133965Sjdp * may be used to endorse or promote products derived from this software 22218822Sdim * without specific prior written permission. 2333965Sjdp * 2433965Sjdp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2533965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2633965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2733965Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2833965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2933965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3033965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3133965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3233965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3333965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3433965Sjdp * SUCH DAMAGE. 35130561Sobrien */ 36130561Sobrien 3733965Sjdp#if defined(LIBC_SCCS) && !defined(lint) 3833965Sjdpstatic char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93"; 3933965Sjdp#endif /* LIBC_SCCS and not lint */ 40130561Sobrien#include <sys/cdefs.h> 41130561Sobrien__FBSDID("$FreeBSD: head/lib/libc/locale/euc.c 94122 2002-04-07 16:37:15Z asmodai $"); 42130561Sobrien 43130561Sobrien#include <sys/types.h> 44130561Sobrien 45130561Sobrien#include <errno.h> 46130561Sobrien#include <rune.h> 47130561Sobrien#include <stddef.h> 48130561Sobrien#include <stdio.h> 4933965Sjdp#include <stdlib.h> 5033965Sjdp#include <string.h> 51130561Sobrien 52130561Sobrienrune_t _EUC_sgetrune(const char *, size_t, char const **); 53130561Sobrienint _EUC_sputrune(rune_t, char *, size_t, char **); 54130561Sobrien 55130561Sobrientypedef struct { 5633965Sjdp int count[4]; 5733965Sjdp rune_t bits[4]; 5833965Sjdp rune_t mask; 5933965Sjdp} _EucInfo; 6033965Sjdp 6133965Sjdpint 6233965Sjdp_EUC_init(rl) 6333965Sjdp _RuneLocale *rl; 6433965Sjdp{ 6533965Sjdp _EucInfo *ei; 6633965Sjdp int x; 6733965Sjdp char *v, *e; 6833965Sjdp 6933965Sjdp rl->sgetrune = _EUC_sgetrune; 7033965Sjdp rl->sputrune = _EUC_sputrune; 7133965Sjdp 7233965Sjdp if (!rl->variable) { 7333965Sjdp free(rl); 7477298Sobrien return (EFTYPE); 7577298Sobrien } 7633965Sjdp v = (char *) rl->variable; 7733965Sjdp 7833965Sjdp while (*v == ' ' || *v == '\t') 7933965Sjdp ++v; 8033965Sjdp 8133965Sjdp if ((ei = malloc(sizeof(_EucInfo))) == NULL) { 8233965Sjdp free(rl); 8333965Sjdp return (ENOMEM); 8433965Sjdp } 8533965Sjdp for (x = 0; x < 4; ++x) { 8633965Sjdp ei->count[x] = (int) strtol(v, &e, 0); 8733965Sjdp if (v == e || !(v = e)) { 8833965Sjdp free(rl); 8933965Sjdp free(ei); 9033965Sjdp return (EFTYPE); 9133965Sjdp } 9233965Sjdp while (*v == ' ' || *v == '\t') 9333965Sjdp ++v; 9433965Sjdp ei->bits[x] = (int) strtol(v, &e, 0); 9533965Sjdp if (v == e || !(v = e)) { 9633965Sjdp free(rl); 9733965Sjdp free(ei); 9833965Sjdp return (EFTYPE); 9933965Sjdp } 10033965Sjdp while (*v == ' ' || *v == '\t') 10133965Sjdp ++v; 10233965Sjdp } 10333965Sjdp ei->mask = (int)strtol(v, &e, 0); 10433965Sjdp if (v == e || !(v = e)) { 10533965Sjdp free(rl); 10633965Sjdp free(ei); 10733965Sjdp return (EFTYPE); 10833965Sjdp } 10933965Sjdp if (sizeof(_EucInfo) <= rl->variable_len) { 11033965Sjdp memcpy(rl->variable, ei, sizeof(_EucInfo)); 11133965Sjdp free(ei); 11233965Sjdp } else { 11333965Sjdp rl->variable = &ei; 11477298Sobrien } 11533965Sjdp rl->variable_len = sizeof(_EucInfo); 11633965Sjdp _CurrentRuneLocale = rl; 11733965Sjdp __mb_cur_max = 3; 11833965Sjdp return (0); 11933965Sjdp} 12033965Sjdp 12133965Sjdp#define CEI ((_EucInfo *)(_CurrentRuneLocale->variable)) 12233965Sjdp 12333965Sjdp#define _SS2 0x008e 12433965Sjdp#define _SS3 0x008f 12533965Sjdp 12633965Sjdp#define GR_BITS 0x80808080 /* XXX: to be fixed */ 12733965Sjdp 12833965Sjdpstatic inline int 12933965Sjdp_euc_set(c) 13033965Sjdp u_int c; 13177298Sobrien{ 13277298Sobrien c &= 0xff; 13333965Sjdp 13433965Sjdp return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); 13533965Sjdp} 13633965Sjdprune_t 13733965Sjdp_EUC_sgetrune(string, n, result) 13833965Sjdp const char *string; 13933965Sjdp size_t n; 14033965Sjdp char const **result; 14133965Sjdp{ 14233965Sjdp rune_t rune = 0; 14333965Sjdp int len, set; 14433965Sjdp 14533965Sjdp if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) { 14633965Sjdp if (result) 14733965Sjdp *result = string; 14833965Sjdp return (_INVALID_RUNE); 14933965Sjdp } 15033965Sjdp switch (set) { 15133965Sjdp case 3: 15233965Sjdp case 2: 15333965Sjdp --len; 15433965Sjdp ++string; 15533965Sjdp /* FALLTHROUGH */ 15633965Sjdp case 1: 15733965Sjdp case 0: 15833965Sjdp while (len-- > 0) 15933965Sjdp rune = (rune << 8) | ((u_int)(*string++) & 0xff); 16033965Sjdp break; 16133965Sjdp } 16233965Sjdp if (result) 16333965Sjdp *result = string; 16433965Sjdp return ((rune & ~CEI->mask) | CEI->bits[set]); 16533965Sjdp} 16633965Sjdp 16733965Sjdpint 16833965Sjdp_EUC_sputrune(c, string, n, result) 16933965Sjdp rune_t c; 17033965Sjdp char *string, **result; 17177298Sobrien size_t n; 17233965Sjdp{ 17333965Sjdp rune_t m = c & CEI->mask; 17433965Sjdp rune_t nm = c & ~m; 17533965Sjdp int i, len; 17633965Sjdp 17733965Sjdp if (m == CEI->bits[1]) { 17833965SjdpCodeSet1: 17933965Sjdp /* Codeset 1: The first byte must have 0x80 in it. */ 18033965Sjdp i = len = CEI->count[1]; 18133965Sjdp if (n >= len) { 18233965Sjdp if (result) 18333965Sjdp *result = string + len; 18433965Sjdp while (i-- > 0) 18533965Sjdp *string++ = (nm >> (i << 3)) | 0x80; 18633965Sjdp } else 18777298Sobrien if (result) 18877298Sobrien *result = (char *) 0; 18933965Sjdp } else { 19033965Sjdp if (m == CEI->bits[0]) { 19133965Sjdp i = len = CEI->count[0]; 19233965Sjdp if (n < len) { 19333965Sjdp if (result) 19433965Sjdp *result = NULL; 19533965Sjdp return (len); 19633965Sjdp } 19733965Sjdp } else 19833965Sjdp if (m == CEI->bits[2]) { 19933965Sjdp i = len = CEI->count[2]; 20033965Sjdp if (n < len) { 20133965Sjdp if (result) 20233965Sjdp *result = NULL; 20333965Sjdp return (len); 20433965Sjdp } 20533965Sjdp *string++ = _SS2; 20633965Sjdp --i; 20733965Sjdp /* SS2 designates G2 into GR */ 20833965Sjdp nm |= GR_BITS; 20933965Sjdp } else 21077298Sobrien if (m == CEI->bits[3]) { 21133965Sjdp i = len = CEI->count[3]; 21233965Sjdp if (n < len) { 21333965Sjdp if (result) 21433965Sjdp *result = NULL; 21533965Sjdp return (len); 21633965Sjdp } 21733965Sjdp *string++ = _SS3; 21833965Sjdp --i; 21933965Sjdp /* SS3 designates G3 into GR */ 22033965Sjdp nm |= GR_BITS; 22133965Sjdp } else 22233965Sjdp goto CodeSet1; /* Bletch */ 22333965Sjdp while (i-- > 0) 22433965Sjdp *string++ = (nm >> (i << 3)) & 0xff; 22533965Sjdp if (result) 22677298Sobrien *result = string; 22777298Sobrien } 22833965Sjdp return (len); 22933965Sjdp} 23033965Sjdp