1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #include <errno.h>
23: #include <locale.h>
24: #include "../locale/localeinfo.h"
25: #include <stdlib.h>
26: #include <string.h>
27:
28: #include <gconv_int.h>
29:
30:
31: int
32: internal_function
33: __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
34: int flags)
35: {
36: struct __gconv_step *steps;
37: size_t nsteps;
38: __gconv_t result = NULL;
39: size_t cnt = 0;
40: int res;
41: int conv_flags = 0;
42: const char *errhand;
43: const char *ignore;
44: struct trans_struct *trans = NULL;
45:
46:
47: errhand = strchr (toset, '/');
48: if (errhand != NULL)
49: errhand = strchr (errhand + 1, '/');
50: if (__builtin_expect (errhand != NULL, 1))
51: {
52: if (*++errhand == '\0')
53: errhand = NULL;
54: else
55: {
56:
57: char *newtoset = (char *) alloca (errhand - toset + 1);
58: char *tok;
59: char *ptr = NULL ;
60:
61: newtoset[errhand - toset] = '\0';
62: toset = memcpy (newtoset, toset, errhand - toset);
63:
64:
65: tok = strdupa (errhand);
66:
67: tok = __strtok_r (tok, ",", &ptr);
68: while (tok != NULL)
69: {
70: if (__strcasecmp_l (tok, "TRANSLIT", _nl_C_locobj_ptr) == 0)
71: {
72:
73:
74: static const char *const internal_trans_names[1]
75: = { "INTERNAL" };
76: struct trans_struct *lastp = NULL;
77: struct trans_struct *runp;
78:
79: for (runp = trans; runp != NULL; runp = runp->next)
80: if (runp->trans_fct == __gconv_transliterate)
81: break;
82: else
83: lastp = runp;
84:
85: if (runp == NULL)
86: {
87: struct trans_struct *newp;
88:
89: newp = (struct trans_struct *) alloca (sizeof (*newp));
90: memset (newp, '\0', sizeof (*newp));
91:
92:
93:
94: newp->csnames = (const char **) internal_trans_names;
95: newp->ncsnames = 1;
96: newp->trans_fct = __gconv_transliterate;
97:
98: if (lastp == NULL)
99: trans = newp;
100: else
101: lastp->next = newp;
102: }
103: }
104: else if (__strcasecmp_l (tok, "IGNORE", _nl_C_locobj_ptr) == 0)
105:
106: conv_flags |= __GCONV_IGNORE_ERRORS;
107: else
108: {
109:
110:
111:
112: struct trans_struct *lastp = NULL;
113: struct trans_struct *runp;
114:
115: for (runp = trans; runp != NULL; runp = runp->next)
116: if (runp->name != NULL
117: && __strcasecmp_l (tok, runp->name,
118: _nl_C_locobj_ptr) == 0)
119: break;
120: else
121: lastp = runp;
122:
123: if (runp == NULL)
124: {
125: struct trans_struct *newp;
126:
127: newp = (struct trans_struct *) alloca (sizeof (*newp));
128: memset (newp, '\0', sizeof (*newp));
129: newp->name = tok;
130:
131: if (lastp == NULL)
132: trans = newp;
133: else
134: lastp->next = newp;
135: }
136: }
137:
138: tok = __strtok_r (NULL, ",", &ptr);
139: }
140: }
141: }
142:
143:
144:
145: ignore = strchr (fromset, '/');
146: if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL
147: && *++ignore != '\0')
148: {
149: char *newfromset = (char *) alloca (ignore - fromset + 1);
150:
151: newfromset[ignore - fromset] = '\0';
152: fromset = memcpy (newfromset, fromset, ignore - fromset);
153: }
154:
155:
156:
157: if (strcmp (toset, "//") == 0)
158: {
159: const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET);
160: size_t len = strlen (codeset);
161: char *dest;
162: toset = dest = (char *) alloca (len + 3);
163: memcpy (__mempcpy (dest, codeset, len), "//", 3);
164: }
165: if (strcmp (fromset, "//") == 0)
166: {
167: const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET);
168: size_t len = strlen (codeset);
169: char *dest;
170: fromset = dest = (char *) alloca (len + 3);
171: memcpy (__mempcpy (dest, codeset, len), "//", 3);
172: }
173:
174: res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags);
175: if (res == __GCONV_OK)
176: {
177:
178: struct trans_struct *lastp = NULL;
179: struct trans_struct *runp;
180:
181: for (runp = trans; runp != NULL; runp = runp->next)
182: {
183: if (runp->name == NULL
184: || __builtin_expect (__gconv_translit_find (runp), 0) == 0)
185: lastp = runp;
186: else
187: {
188:
189: if (lastp == NULL)
190: trans = runp->next;
191: else
192: lastp->next = runp->next;
193: }
194: }
195:
196:
197: result = (__gconv_t) malloc (sizeof (struct __gconv_info)
198: + (nsteps
199: * sizeof (struct __gconv_step_data)));
200: if (result == NULL)
201: res = __GCONV_NOMEM;
202: else
203: {
204: size_t n;
205:
206:
207: result->__steps = steps;
208: result->__nsteps = nsteps;
209:
210:
211: memset (result->__data, '\0',
212: nsteps * sizeof (struct __gconv_step_data));
213:
214:
215:
216: for (cnt = 0; cnt < nsteps; ++cnt)
217: {
218: size_t size;
219:
220:
221:
222: #if 0
223:
224: result->__data[cnt].__invocation_counter = 0;
225:
226:
227: result->__data[cnt].__internal_use = 0;
228: #endif
229:
230:
231: result->__data[cnt].__statep = &result->__data[cnt].__state;
232:
233:
234:
235: for (runp = trans; runp != NULL; runp = runp->next)
236: for (n = 0; n < runp->ncsnames; ++n)
237: if (__strcasecmp_l (steps[cnt].__from_name,
238: runp->csnames[n], _nl_C_locobj_ptr) == 0)
239: {
240: void *data = NULL;
241:
242:
243: if (runp->trans_init_fct == NULL
244: || (runp->trans_init_fct (&data,
245: steps[cnt].__to_name)
246: == __GCONV_OK))
247: {
248:
249: struct __gconv_trans_data *newp;
250: struct __gconv_trans_data **lastp;
251:
252: newp = (struct __gconv_trans_data *)
253: malloc (sizeof (struct __gconv_trans_data));
254: if (newp == NULL)
255: {
256: res = __GCONV_NOMEM;
257: goto bail;
258: }
259:
260: newp->__trans_fct = runp->trans_fct;
261: newp->__trans_context_fct = runp->trans_context_fct;
262: newp->__trans_end_fct = runp->trans_end_fct;
263: newp->__data = data;
264: newp->__next = NULL;
265:
266: lastp = &result->__data[cnt].__trans;
267: while (*lastp != NULL)
268: lastp = &(*lastp)->__next;
269:
270: *lastp = newp;
271: }
272: break;
273: }
274:
275:
276:
277: if (cnt < nsteps - 1)
278: {
279: result->__data[cnt].__flags = conv_flags;
280:
281:
282: size = (GCONV_NCHAR_GOAL * steps[cnt].__max_needed_to);
283:
284: result->__data[cnt].__outbuf = malloc (size);
285: if (result->__data[cnt].__outbuf == NULL)
286: {
287: res = __GCONV_NOMEM;
288: goto bail;
289: }
290:
291: result->__data[cnt].__outbufend =
292: result->__data[cnt].__outbuf + size;
293: }
294: else
295: {
296:
297: result->__data[cnt].__flags = conv_flags | __GCONV_IS_LAST;
298:
299: break;
300: }
301: }
302: }
303:
304: if (res != __GCONV_OK)
305: {
306:
307: int serrno;
308: bail:
309: serrno = errno;
310:
311: if (result != NULL)
312: {
313: while (cnt-- > 0)
314: {
315: struct __gconv_trans_data *transp;
316:
317: transp = result->__data[cnt].__trans;
318: while (transp != NULL)
319: {
320: struct __gconv_trans_data *curp = transp;
321: transp = transp->__next;
322:
323: if (__builtin_expect (curp->__trans_end_fct != NULL, 0))
324: curp->__trans_end_fct (curp->__data);
325:
326: free (curp);
327: }
328:
329: free (result->__data[cnt].__outbuf);
330: }
331:
332: free (result);
333: result = NULL;
334: }
335:
336: __gconv_close_transform (steps, nsteps);
337:
338: __set_errno (serrno);
339: }
340: }
341:
342: *handle = result;
343: return res;
344: }