160471Sbostic /*-
2*61136Sbostic * Copyright (c) 1993
3*61136Sbostic * The Regents of the University of California. All rights reserved.
460471Sbostic *
560471Sbostic * This code is derived from software contributed to Berkeley by
660471Sbostic * Paul Borman at Krystal Technologies.
760471Sbostic *
860471Sbostic * %sccs.include.redist.c%
960471Sbostic */
1060471Sbostic
1160471Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*61136Sbostic static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 06/04/93";
1360471Sbostic #endif /* LIBC_SCCS and not lint */
1460471Sbostic
1560471Sbostic #include <sys/types.h>
1660471Sbostic
1760471Sbostic #include <errno.h>
1860471Sbostic #include <rune.h>
1960471Sbostic #include <stddef.h>
2060471Sbostic #include <stdio.h>
2160471Sbostic #include <stdlib.h>
2260471Sbostic
2360471Sbostic rune_t _EUC_sgetrune __P((const char *, size_t, char const **));
2460471Sbostic int _EUC_sputrune __P((rune_t, char *, size_t, char **));
2560471Sbostic
2660471Sbostic typedef struct {
2760471Sbostic int count[4];
2860471Sbostic rune_t bits[4];
2960471Sbostic rune_t mask;
3060471Sbostic } _EucInfo;
3160471Sbostic
3260471Sbostic int
_EUC_init(rl)3360471Sbostic _EUC_init(rl)
3460471Sbostic _RuneLocale *rl;
3560471Sbostic {
3660471Sbostic _EucInfo *ei;
3760471Sbostic int x;
3860471Sbostic char *v, *e;
3960471Sbostic
4060471Sbostic rl->sgetrune = _EUC_sgetrune;
4160471Sbostic rl->sputrune = _EUC_sputrune;
4260471Sbostic
4360471Sbostic if (!rl->variable) {
4460471Sbostic free(rl);
4560471Sbostic return (EFTYPE);
4660471Sbostic }
4760471Sbostic v = (char *) rl->variable;
4860471Sbostic
4960471Sbostic while (*v == ' ' || *v == '\t')
5060471Sbostic ++v;
5160471Sbostic
5260471Sbostic if ((ei = malloc(sizeof(_EucInfo))) == NULL) {
5360471Sbostic free(rl);
5460471Sbostic return (ENOMEM);
5560471Sbostic }
5660471Sbostic for (x = 0; x < 4; ++x) {
5760471Sbostic ei->count[x] = (int) strtol(v, &e, 0);
5860471Sbostic if (v == e || !(v = e)) {
5960471Sbostic free(rl);
6060471Sbostic free(ei);
6160471Sbostic return (EFTYPE);
6260471Sbostic }
6360471Sbostic while (*v == ' ' || *v == '\t')
6460471Sbostic ++v;
6560471Sbostic ei->bits[x] = (int) strtol(v, &e, 0);
6660471Sbostic if (v == e || !(v = e)) {
6760471Sbostic free(rl);
6860471Sbostic free(ei);
6960471Sbostic return (EFTYPE);
7060471Sbostic }
7160471Sbostic while (*v == ' ' || *v == '\t')
7260471Sbostic ++v;
7360471Sbostic }
7460471Sbostic ei->mask = (int)strtol(v, &e, 0);
7560471Sbostic if (v == e || !(v = e)) {
7660471Sbostic free(rl);
7760471Sbostic free(ei);
7860471Sbostic return (EFTYPE);
7960471Sbostic }
8060471Sbostic if (sizeof(_EucInfo) <= rl->variable_len) {
8160471Sbostic memcpy(rl->variable, ei, sizeof(_EucInfo));
8260471Sbostic free(ei);
8360471Sbostic } else {
8460471Sbostic rl->variable = &ei;
8560471Sbostic }
8660471Sbostic rl->variable_len = sizeof(_EucInfo);
8760471Sbostic _CurrentRuneLocale = rl;
8860471Sbostic __mb_cur_max = 3;
8960471Sbostic return (0);
9060471Sbostic }
9160471Sbostic
9260471Sbostic #define CEI ((_EucInfo *)(_CurrentRuneLocale->variable))
9360471Sbostic
9460471Sbostic #define _SS2 0x008e
9560471Sbostic #define _SS3 0x008f
9660471Sbostic
9760471Sbostic static inline int
_euc_set(c)9860471Sbostic _euc_set(c)
9960471Sbostic u_int c;
10060471Sbostic {
10160471Sbostic c &= 0xff;
10260471Sbostic
10360471Sbostic return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
10460471Sbostic }
10560471Sbostic rune_t
_EUC_sgetrune(string,n,result)10660471Sbostic _EUC_sgetrune(string, n, result)
10760471Sbostic const char *string;
10860471Sbostic size_t n;
10960471Sbostic char const **result;
11060471Sbostic {
11160471Sbostic rune_t rune = 0;
11260471Sbostic int len, set;
11360471Sbostic
11460471Sbostic if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) {
11560471Sbostic if (result)
11660471Sbostic *result = string;
11760471Sbostic return (_INVALID_RUNE);
11860471Sbostic }
11960471Sbostic switch (set) {
12060471Sbostic case 3:
12160471Sbostic case 2:
12260471Sbostic --len;
12360471Sbostic ++string;
12460471Sbostic /* FALLTHROUGH */
12560471Sbostic case 1:
12660471Sbostic case 0:
12760471Sbostic while (len-- > 0)
12860471Sbostic rune = (rune << 8) | ((u_int)(*string++) & 0xff);
12960471Sbostic break;
13060471Sbostic }
13160471Sbostic if (result)
13260471Sbostic *result = string;
13360471Sbostic return ((rune & ~CEI->mask) | CEI->bits[set]);
13460471Sbostic }
13560471Sbostic
13660471Sbostic int
_EUC_sputrune(c,string,n,result)13760471Sbostic _EUC_sputrune(c, string, n, result)
13860471Sbostic rune_t c;
13960471Sbostic char *string, **result;
14060471Sbostic size_t n;
14160471Sbostic {
14260471Sbostic rune_t m = c & CEI->mask;
14360471Sbostic rune_t nm = c & ~m;
14460471Sbostic int i, len;
14560471Sbostic
14660471Sbostic if (m == CEI->bits[1]) {
14760471Sbostic CodeSet1:
14860471Sbostic /* Codeset 1: The first byte must have 0x80 in it. */
14960471Sbostic i = len = CEI->count[1];
15060471Sbostic if (n >= len) {
15160471Sbostic if (result)
15260471Sbostic *result = string + len;
15360471Sbostic while (i-- > 0)
15460471Sbostic *string++ = (nm >> (i << 3)) | 0x80;
15560471Sbostic } else
15660471Sbostic if (result)
15760471Sbostic *result = (char *) 0;
15860471Sbostic } else {
15960471Sbostic if (m == CEI->bits[0]) {
16060471Sbostic i = len = CEI->count[0];
16160471Sbostic if (n < len) {
16260471Sbostic if (result)
16360471Sbostic *result = NULL;
16460471Sbostic return (len);
16560471Sbostic }
16660471Sbostic } else
16760471Sbostic if (m == CEI->bits[2]) {
16860471Sbostic i = len = CEI->count[2];
16960471Sbostic if (n < len) {
17060471Sbostic if (result)
17160471Sbostic *result = NULL;
17260471Sbostic return (len);
17360471Sbostic }
17460471Sbostic *string++ = _SS2;
17560471Sbostic --i;
17660471Sbostic } else
17760471Sbostic if (m == CEI->bits[3]) {
17860471Sbostic i = len = CEI->count[3];
17960471Sbostic if (n < len) {
18060471Sbostic if (result)
18160471Sbostic *result = NULL;
18260471Sbostic return (len);
18360471Sbostic }
18460471Sbostic *string++ = _SS3;
18560471Sbostic --i;
18660471Sbostic } else
18760471Sbostic goto CodeSet1; /* Bletch */
18860471Sbostic while (i-- > 0)
18960471Sbostic *string++ = (nm >> (i << 3)) & 0xff;
19060471Sbostic if (result)
19160471Sbostic *result = string;
19260471Sbostic }
19360471Sbostic return (len);
19460471Sbostic }
195