5f607871814cc78c728d197342dd5a670f5b9dd5
[dragonfly.git] / lib / libc / citrus / citrus_ctype.c
1 /* $NetBSD: src/lib/libc/citrus/citrus_ctype.c,v 1.4 2003/03/05 20:18:15 tshiozak Exp $ */
2 /* $DragonFly: src/lib/libc/citrus/citrus_ctype.c,v 1.2 2008/04/10 10:21:01 hasso Exp $ */
3
4 /*-
5  * Copyright (c)1999, 2000, 2001, 2002 Citrus Project,
6  * All rights reserved.
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  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <sys/types.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <locale.h>
39 #include <stddef.h>
40 #include <wchar.h>
41 #include "citrus_module.h"
42 #include "citrus_ctype.h"
43 #include "citrus_ctype_fallback.h"
44 #include "citrus_none.h"
45 #include _CITRUS_DEFAULT_CTYPE_HEADER
46
47 _citrus_ctype_rec_t _citrus_ctype_default = {
48         &_CITRUS_DEFAULT_CTYPE_OPS,     /* cc_ops */
49         NULL,                           /* cc_closure */
50         NULL                            /* cc_module */
51 };
52
53 #ifdef _I18N_DYNAMIC
54
55 static int _initctypemodule(_citrus_ctype_t, char const *, _citrus_module_t,
56                             void *, size_t, size_t);
57
58 static int
59 _initctypemodule(_citrus_ctype_t cc, char const *modname,
60                  _citrus_module_t handle, void *variable, size_t lenvar,
61                  size_t szpriv)
62 {
63         int ret;
64         _citrus_ctype_getops_t getops;
65
66         _DIAGASSERT(cc != NULL);
67
68         cc->cc_module = handle;
69
70         getops = (_citrus_ctype_getops_t)_citrus_find_getops(cc->cc_module,
71                                                              modname,
72                                                              "ctype");
73         if (getops == NULL)
74                 return (EINVAL);
75
76         cc->cc_ops = malloc(sizeof(*cc->cc_ops));
77         if (cc->cc_ops == NULL)
78                 return (ENOMEM);
79
80         ret = (*getops)(cc->cc_ops, sizeof(*cc->cc_ops),
81                         _CITRUS_CTYPE_ABI_VERSION);
82         if (ret)
83                 goto bad;
84
85         /* If return ABI version is not expected, fixup it here*/
86         switch (cc->cc_ops->co_abi_version) {
87         case 0x00000001:
88                 cc->cc_ops->co_btowc = &_citrus_ctype_btowc_fallback;
89                 cc->cc_ops->co_wctob = &_citrus_ctype_wctob_fallback;
90                 /* FALLTHROUGH */
91         case 0x00000002:
92                 /* FALLTHROUGH */
93         default:
94                 break;
95         }
96
97         /* validation check */
98         if (cc->cc_ops->co_init == NULL ||
99             cc->cc_ops->co_uninit == NULL ||
100             cc->cc_ops->co_get_mb_cur_max == NULL ||
101             cc->cc_ops->co_mblen == NULL ||
102             cc->cc_ops->co_mbrlen == NULL ||
103             cc->cc_ops->co_mbrtowc == NULL ||
104             cc->cc_ops->co_mbsinit == NULL ||
105             cc->cc_ops->co_mbsrtowcs == NULL ||
106             cc->cc_ops->co_mbstowcs == NULL ||
107             cc->cc_ops->co_mbtowc == NULL ||
108             cc->cc_ops->co_wcrtomb == NULL ||
109             cc->cc_ops->co_wcsrtombs == NULL ||
110             cc->cc_ops->co_wcstombs == NULL ||
111             cc->cc_ops->co_wctomb == NULL ||
112             cc->cc_ops->co_btowc == NULL ||
113             cc->cc_ops->co_wctob == NULL)
114                 goto bad;
115
116         /* init and get closure */
117         ret = (*cc->cc_ops->co_init)(
118                 &cc->cc_closure, variable, lenvar, szpriv);
119         if (ret)
120                 goto bad;
121
122         return (0);
123
124 bad:
125         if (cc->cc_ops)
126                 free(cc->cc_ops);
127         cc->cc_ops = NULL;
128
129         return (ret);
130 }
131
132 int
133 _citrus_ctype_open(_citrus_ctype_t *rcc,
134                    char const *encname, void *variable, size_t lenvar,
135                    size_t szpriv)
136 {
137         int ret;
138         _citrus_module_t handle;
139         _citrus_ctype_t cc;
140
141         _DIAGASSERT(encname != NULL);
142         _DIAGASSERT(!lenvar || variable!=NULL);
143         _DIAGASSERT(rcc != NULL);
144
145         if (!strcmp(encname, _CITRUS_DEFAULT_CTYPE_NAME)) {
146                 *rcc = &_citrus_ctype_default;
147                 return (0);
148         }
149         ret = _citrus_load_module(&handle, encname);
150         if (ret)
151                 return (ret);
152
153         cc = calloc(1, sizeof(*cc));
154         if (!cc) {
155                 _citrus_unload_module(handle);
156                 return (errno);
157         }
158
159         ret = _initctypemodule(cc, encname, handle, variable, lenvar, szpriv);
160         if (ret) {
161                 _citrus_unload_module(cc->cc_module);
162                 free(cc);
163                 return (ret);
164         }
165
166         *rcc = cc;
167
168         return (0);
169 }
170
171 void
172 _citrus_ctype_close(_citrus_ctype_t cc)
173 {
174
175         _DIAGASSERT(cc != NULL);
176
177         if (cc == &_citrus_ctype_default)
178                 return;
179         (*cc->cc_ops->co_uninit)(cc->cc_closure);
180         free(cc->cc_ops);
181         _citrus_unload_module(cc->cc_module);
182         free(cc);
183 }
184
185 #else
186 /* !_I18N_DYNAMIC */
187
188 int
189 /*ARGSUSED*/
190 _citrus_ctype_open(_citrus_ctype_t *rcc,
191                    char const *encname, void *variable, size_t lenvar,
192                    size_t szpriv)
193 {
194         if (!strcmp(encname, _CITRUS_DEFAULT_CTYPE_NAME)) {
195                 *rcc = &_citrus_ctype_default;
196                 return (0);
197         }
198         return (EINVAL);
199 }
200
201 void
202 /*ARGSUSED*/
203 _citrus_ctype_close(_citrus_ctype_t cc)
204 {
205 }
206
207 #endif