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