]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/locale/euc.c
This commit was generated by cvs2svn to compensate for changes in r53660,
[FreeBSD/FreeBSD.git] / lib / libc / locale / euc.c
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  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36
37 #ifdef XPG4
38 #if defined(LIBC_SCCS) && !defined(lint)
39 static char sccsid[] = "@(#)euc.c       8.1 (Berkeley) 6/4/93";
40 #endif /* LIBC_SCCS and not lint */
41
42 #include <sys/types.h>
43
44 #include <errno.h>
45 #include <rune.h>
46 #include <stddef.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 rune_t  _EUC_sgetrune __P((const char *, size_t, char const **));
52 int     _EUC_sputrune __P((rune_t, char *, size_t, char **));
53
54 typedef struct {
55         int     count[4];
56         rune_t  bits[4];
57         rune_t  mask;
58 } _EucInfo;
59
60 int
61 _EUC_init(rl)
62         _RuneLocale *rl;
63 {
64         _EucInfo *ei;
65         int x;
66         char *v, *e;
67
68         rl->sgetrune = _EUC_sgetrune;
69         rl->sputrune = _EUC_sputrune;
70
71         if (!rl->variable) {
72                 free(rl);
73                 return (EFTYPE);
74         }
75         v = (char *) rl->variable;
76
77         while (*v == ' ' || *v == '\t')
78                 ++v;
79
80         if ((ei = malloc(sizeof(_EucInfo))) == NULL) {
81                 free(rl);
82                 return (ENOMEM);
83         }
84         for (x = 0; x < 4; ++x) {
85                 ei->count[x] = (int) strtol(v, &e, 0);
86                 if (v == e || !(v = e)) {
87                         free(rl);
88                         free(ei);
89                         return (EFTYPE);
90                 }
91                 while (*v == ' ' || *v == '\t')
92                         ++v;
93                 ei->bits[x] = (int) strtol(v, &e, 0);
94                 if (v == e || !(v = e)) {
95                         free(rl);
96                         free(ei);
97                         return (EFTYPE);
98                 }
99                 while (*v == ' ' || *v == '\t')
100                         ++v;
101         }
102         ei->mask = (int)strtol(v, &e, 0);
103         if (v == e || !(v = e)) {
104                 free(rl);
105                 free(ei);
106                 return (EFTYPE);
107         }
108         if (sizeof(_EucInfo) <= rl->variable_len) {
109                 memcpy(rl->variable, ei, sizeof(_EucInfo));
110                 free(ei);
111         } else {
112                 rl->variable = &ei;
113         }
114         rl->variable_len = sizeof(_EucInfo);
115         _CurrentRuneLocale = rl;
116         __mb_cur_max = 3;
117         return (0);
118 }
119
120 #define CEI     ((_EucInfo *)(_CurrentRuneLocale->variable))
121
122 #define _SS2    0x008e
123 #define _SS3    0x008f
124
125 static inline int
126 _euc_set(c)
127         u_int c;
128 {
129         c &= 0xff;
130
131         return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
132 }
133 rune_t
134 _EUC_sgetrune(string, n, result)
135         const char *string;
136         size_t n;
137         char const **result;
138 {
139         rune_t rune = 0;
140         int len, set;
141
142         if (n < 1 || (len = CEI->count[set = _euc_set(*string)]) > n) {
143                 if (result)
144                         *result = string;
145                 return (_INVALID_RUNE);
146         }
147         switch (set) {
148         case 3:
149         case 2:
150                 --len;
151                 ++string;
152                 /* FALLTHROUGH */
153         case 1:
154         case 0:
155                 while (len-- > 0)
156                         rune = (rune << 8) | ((u_int)(*string++) & 0xff);
157                 break;
158         }
159         if (result)
160                 *result = string;
161         return ((rune & ~CEI->mask) | CEI->bits[set]);
162 }
163
164 int
165 _EUC_sputrune(c, string, n, result)
166         rune_t c;
167         char *string, **result;
168         size_t n;
169 {
170         rune_t m = c & CEI->mask;
171         rune_t nm = c & ~m;
172         int i, len;
173
174         if (m == CEI->bits[1]) {
175 CodeSet1:
176                 /* Codeset 1: The first byte must have 0x80 in it. */
177                 i = len = CEI->count[1];
178                 if (n >= len) {
179                         if (result)
180                                 *result = string + len;
181                         while (i-- > 0)
182                                 *string++ = (nm >> (i << 3)) | 0x80;
183                 } else
184                         if (result)
185                                 *result = (char *) 0;
186         } else {
187                 if (m == CEI->bits[0]) {
188                         i = len = CEI->count[0];
189                         if (n < len) {
190                                 if (result)
191                                         *result = NULL;
192                                 return (len);
193                         }
194                 } else
195                         if (m == CEI->bits[2]) {
196                                 i = len = CEI->count[2];
197                                 if (n < len) {
198                                         if (result)
199                                                 *result = NULL;
200                                         return (len);
201                                 }
202                                 *string++ = _SS2;
203                                 --i;
204                         } else
205                                 if (m == CEI->bits[3]) {
206                                         i = len = CEI->count[3];
207                                         if (n < len) {
208                                                 if (result)
209                                                         *result = NULL;
210                                                 return (len);
211                                         }
212                                         *string++ = _SS3;
213                                         --i;
214                                 } else
215                                         goto CodeSet1;  /* Bletch */
216                 while (i-- > 0)
217                         *string++ = (nm >> (i << 3)) & 0xff;
218                 if (result)
219                         *result = string;
220         }
221         return (len);
222 }
223 #endif  /* XPG4 */