158f0484fSRodney W. Grimes /*- 258f0484fSRodney W. Grimes * Copyright (c) 1993 358f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 458f0484fSRodney W. Grimes * 558f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by 658f0484fSRodney W. Grimes * Paul Borman at Krystal Technologies. 758f0484fSRodney W. Grimes * 858f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 958f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1058f0484fSRodney W. Grimes * are met: 1158f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1258f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1358f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1458f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1558f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1658f0484fSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 1758f0484fSRodney W. Grimes * must display the following acknowledgement: 1858f0484fSRodney W. Grimes * This product includes software developed by the University of 1958f0484fSRodney W. Grimes * California, Berkeley and its contributors. 2058f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 2158f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2258f0484fSRodney W. Grimes * without specific prior written permission. 2358f0484fSRodney W. Grimes * 2458f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2558f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2658f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2758f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2858f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2958f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3058f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3158f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3258f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3358f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3458f0484fSRodney W. Grimes * SUCH DAMAGE. 3558f0484fSRodney W. Grimes */ 3658f0484fSRodney W. Grimes 3758f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 3858f0484fSRodney W. Grimes static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93"; 3958f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 40333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 41333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4258f0484fSRodney W. Grimes 4358f0484fSRodney W. Grimes #include <sys/types.h> 4458f0484fSRodney W. Grimes 4558f0484fSRodney W. Grimes #include <errno.h> 4658f0484fSRodney W. Grimes #include <rune.h> 4758f0484fSRodney W. Grimes #include <stddef.h> 4858f0484fSRodney W. Grimes #include <stdio.h> 4958f0484fSRodney W. Grimes #include <stdlib.h> 50da8a9b61SJohn Birrell #include <string.h> 5158f0484fSRodney W. Grimes 52c05ac53bSDavid E. O'Brien rune_t _EUC_sgetrune(const char *, size_t, char const **); 53c05ac53bSDavid E. O'Brien int _EUC_sputrune(rune_t, char *, size_t, char **); 5458f0484fSRodney W. Grimes 5558f0484fSRodney W. Grimes typedef struct { 5658f0484fSRodney W. Grimes int count[4]; 5758f0484fSRodney W. Grimes rune_t bits[4]; 5858f0484fSRodney W. Grimes rune_t mask; 5958f0484fSRodney W. Grimes } _EucInfo; 6058f0484fSRodney W. Grimes 6158f0484fSRodney W. Grimes int 6258f0484fSRodney W. Grimes _EUC_init(rl) 6358f0484fSRodney W. Grimes _RuneLocale *rl; 6458f0484fSRodney W. Grimes { 6558f0484fSRodney W. Grimes _EucInfo *ei; 6658f0484fSRodney W. Grimes int x; 6758f0484fSRodney W. Grimes char *v, *e; 6858f0484fSRodney W. Grimes 6958f0484fSRodney W. Grimes rl->sgetrune = _EUC_sgetrune; 7058f0484fSRodney W. Grimes rl->sputrune = _EUC_sputrune; 7158f0484fSRodney W. Grimes 7258f0484fSRodney W. Grimes if (!rl->variable) { 7358f0484fSRodney W. Grimes free(rl); 7458f0484fSRodney W. Grimes return (EFTYPE); 7558f0484fSRodney W. Grimes } 7658f0484fSRodney W. Grimes v = (char *) rl->variable; 7758f0484fSRodney W. Grimes 7858f0484fSRodney W. Grimes while (*v == ' ' || *v == '\t') 7958f0484fSRodney W. Grimes ++v; 8058f0484fSRodney W. Grimes 8158f0484fSRodney W. Grimes if ((ei = malloc(sizeof(_EucInfo))) == NULL) { 8258f0484fSRodney W. Grimes free(rl); 8358f0484fSRodney W. Grimes return (ENOMEM); 8458f0484fSRodney W. Grimes } 85eb12e52aSJeroen Ruigrok van der Werven __mb_cur_max = 0; 8658f0484fSRodney W. Grimes for (x = 0; x < 4; ++x) { 8758f0484fSRodney W. Grimes ei->count[x] = (int) strtol(v, &e, 0); 8858f0484fSRodney W. Grimes if (v == e || !(v = e)) { 8958f0484fSRodney W. Grimes free(rl); 9058f0484fSRodney W. Grimes free(ei); 9158f0484fSRodney W. Grimes return (EFTYPE); 9258f0484fSRodney W. Grimes } 93eb12e52aSJeroen Ruigrok van der Werven if (__mb_cur_max < ei->count[x]) 94eb12e52aSJeroen Ruigrok van der Werven __mb_cur_max = ei->count[x]; 9558f0484fSRodney W. Grimes while (*v == ' ' || *v == '\t') 9658f0484fSRodney W. Grimes ++v; 9758f0484fSRodney W. Grimes ei->bits[x] = (int) strtol(v, &e, 0); 9858f0484fSRodney W. Grimes if (v == e || !(v = e)) { 9958f0484fSRodney W. Grimes free(rl); 10058f0484fSRodney W. Grimes free(ei); 10158f0484fSRodney W. Grimes return (EFTYPE); 10258f0484fSRodney W. Grimes } 10358f0484fSRodney W. Grimes while (*v == ' ' || *v == '\t') 10458f0484fSRodney W. Grimes ++v; 10558f0484fSRodney W. Grimes } 10658f0484fSRodney W. Grimes ei->mask = (int)strtol(v, &e, 0); 10758f0484fSRodney W. Grimes if (v == e || !(v = e)) { 10858f0484fSRodney W. Grimes free(rl); 10958f0484fSRodney W. Grimes free(ei); 11058f0484fSRodney W. Grimes return (EFTYPE); 11158f0484fSRodney W. Grimes } 11258f0484fSRodney W. Grimes if (sizeof(_EucInfo) <= rl->variable_len) { 11358f0484fSRodney W. Grimes memcpy(rl->variable, ei, sizeof(_EucInfo)); 11458f0484fSRodney W. Grimes free(ei); 11558f0484fSRodney W. Grimes } else { 11645206d5cSAndrey A. Chernov rl->variable = ei; 11758f0484fSRodney W. Grimes } 11858f0484fSRodney W. Grimes rl->variable_len = sizeof(_EucInfo); 11958f0484fSRodney W. Grimes _CurrentRuneLocale = rl; 12058f0484fSRodney W. Grimes return (0); 12158f0484fSRodney W. Grimes } 12258f0484fSRodney W. Grimes 12358f0484fSRodney W. Grimes #define CEI ((_EucInfo *)(_CurrentRuneLocale->variable)) 12458f0484fSRodney W. Grimes 12558f0484fSRodney W. Grimes #define _SS2 0x008e 12658f0484fSRodney W. Grimes #define _SS3 0x008f 12758f0484fSRodney W. Grimes 128a243e676SJeroen Ruigrok van der Werven #define GR_BITS 0x80808080 /* XXX: to be fixed */ 129a243e676SJeroen Ruigrok van der Werven 13058f0484fSRodney W. Grimes static inline int 13158f0484fSRodney W. Grimes _euc_set(c) 13258f0484fSRodney W. Grimes u_int c; 13358f0484fSRodney W. Grimes { 13458f0484fSRodney W. Grimes c &= 0xff; 13558f0484fSRodney W. Grimes 13658f0484fSRodney W. Grimes return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0); 13758f0484fSRodney W. Grimes } 13858f0484fSRodney W. Grimes rune_t 13958f0484fSRodney W. Grimes _EUC_sgetrune(string, n, result) 14058f0484fSRodney W. Grimes const char *string; 14158f0484fSRodney W. Grimes size_t n; 14258f0484fSRodney W. Grimes char const **result; 14358f0484fSRodney W. Grimes { 14458f0484fSRodney W. Grimes rune_t rune = 0; 14558f0484fSRodney W. Grimes int len, set; 14658f0484fSRodney W. Grimes 14758f0484fSRodney W. Grimes if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) { 14858f0484fSRodney W. Grimes if (result) 14958f0484fSRodney W. Grimes *result = string; 15058f0484fSRodney W. Grimes return (_INVALID_RUNE); 15158f0484fSRodney W. Grimes } 15258f0484fSRodney W. Grimes switch (set) { 15358f0484fSRodney W. Grimes case 3: 15458f0484fSRodney W. Grimes case 2: 15558f0484fSRodney W. Grimes --len; 15658f0484fSRodney W. Grimes ++string; 15758f0484fSRodney W. Grimes /* FALLTHROUGH */ 15858f0484fSRodney W. Grimes case 1: 15958f0484fSRodney W. Grimes case 0: 16058f0484fSRodney W. Grimes while (len-- > 0) 16158f0484fSRodney W. Grimes rune = (rune << 8) | ((u_int)(*string++) & 0xff); 16258f0484fSRodney W. Grimes break; 16358f0484fSRodney W. Grimes } 16458f0484fSRodney W. Grimes if (result) 16558f0484fSRodney W. Grimes *result = string; 16658f0484fSRodney W. Grimes return ((rune & ~CEI->mask) | CEI->bits[set]); 16758f0484fSRodney W. Grimes } 16858f0484fSRodney W. Grimes 16958f0484fSRodney W. Grimes int 17058f0484fSRodney W. Grimes _EUC_sputrune(c, string, n, result) 17158f0484fSRodney W. Grimes rune_t c; 17258f0484fSRodney W. Grimes char *string, **result; 17358f0484fSRodney W. Grimes size_t n; 17458f0484fSRodney W. Grimes { 17558f0484fSRodney W. Grimes rune_t m = c & CEI->mask; 17658f0484fSRodney W. Grimes rune_t nm = c & ~m; 17758f0484fSRodney W. Grimes int i, len; 17858f0484fSRodney W. Grimes 17958f0484fSRodney W. Grimes if (m == CEI->bits[1]) { 18058f0484fSRodney W. Grimes CodeSet1: 18158f0484fSRodney W. Grimes /* Codeset 1: The first byte must have 0x80 in it. */ 18258f0484fSRodney W. Grimes i = len = CEI->count[1]; 18358f0484fSRodney W. Grimes if (n >= len) { 18458f0484fSRodney W. Grimes if (result) 18558f0484fSRodney W. Grimes *result = string + len; 18658f0484fSRodney W. Grimes while (i-- > 0) 18758f0484fSRodney W. Grimes *string++ = (nm >> (i << 3)) | 0x80; 18858f0484fSRodney W. Grimes } else 18958f0484fSRodney W. Grimes if (result) 19058f0484fSRodney W. Grimes *result = (char *) 0; 19158f0484fSRodney W. Grimes } else { 19258f0484fSRodney W. Grimes if (m == CEI->bits[0]) { 19358f0484fSRodney W. Grimes i = len = CEI->count[0]; 19458f0484fSRodney W. Grimes if (n < len) { 19558f0484fSRodney W. Grimes if (result) 19658f0484fSRodney W. Grimes *result = NULL; 19758f0484fSRodney W. Grimes return (len); 19858f0484fSRodney W. Grimes } 19958f0484fSRodney W. Grimes } else 20058f0484fSRodney W. Grimes if (m == CEI->bits[2]) { 20158f0484fSRodney W. Grimes i = len = CEI->count[2]; 20258f0484fSRodney W. Grimes if (n < len) { 20358f0484fSRodney W. Grimes if (result) 20458f0484fSRodney W. Grimes *result = NULL; 20558f0484fSRodney W. Grimes return (len); 20658f0484fSRodney W. Grimes } 20758f0484fSRodney W. Grimes *string++ = _SS2; 20858f0484fSRodney W. Grimes --i; 209a243e676SJeroen Ruigrok van der Werven /* SS2 designates G2 into GR */ 210a243e676SJeroen Ruigrok van der Werven nm |= GR_BITS; 21158f0484fSRodney W. Grimes } else 21258f0484fSRodney W. Grimes if (m == CEI->bits[3]) { 21358f0484fSRodney W. Grimes i = len = CEI->count[3]; 21458f0484fSRodney W. Grimes if (n < len) { 21558f0484fSRodney W. Grimes if (result) 21658f0484fSRodney W. Grimes *result = NULL; 21758f0484fSRodney W. Grimes return (len); 21858f0484fSRodney W. Grimes } 21958f0484fSRodney W. Grimes *string++ = _SS3; 22058f0484fSRodney W. Grimes --i; 221a243e676SJeroen Ruigrok van der Werven /* SS3 designates G3 into GR */ 222a243e676SJeroen Ruigrok van der Werven nm |= GR_BITS; 22358f0484fSRodney W. Grimes } else 22458f0484fSRodney W. Grimes goto CodeSet1; /* Bletch */ 22558f0484fSRodney W. Grimes while (i-- > 0) 22658f0484fSRodney W. Grimes *string++ = (nm >> (i << 3)) & 0xff; 22758f0484fSRodney W. Grimes if (result) 22858f0484fSRodney W. Grimes *result = string; 22958f0484fSRodney W. Grimes } 23058f0484fSRodney W. Grimes return (len); 23158f0484fSRodney W. Grimes } 232