1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51: #include <assert.h>
52: #include <endian.h>
53: #include <gconv.h>
54: #include <stdint.h>
55: #include <string.h>
56: #include <wchar.h>
57: #include <sys/param.h>
58: #define __need_size_t
59: #include <stddef.h>
60:
61:
62:
63:
64:
65:
66: #undef FCTNAME2
67: #if defined _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
68:
69: # define get16(addr) *((__const uint16_t *) (addr))
70: # define get32(addr) *((__const uint32_t *) (addr))
71:
72:
73: # define put16(addr, val) *((uint16_t *) (addr)) = (val)
74: # define put32(addr, val) *((uint32_t *) (addr)) = (val)
75:
76: # define FCTNAME2(name) name
77: #else
78:
79: # if __BYTE_ORDER == __LITTLE_ENDIAN
80: # define get16(addr) \
81: (((__const unsigned char *) (addr))[1] << 8 \
82: | ((__const unsigned char *) (addr))[0])
83: # define get32(addr) \
84: (((((__const unsigned char *) (addr))[3] << 8 \
85: | ((__const unsigned char *) (addr))[2]) << 8 \
86: | ((__const unsigned char *) (addr))[1]) << 8 \
87: | ((__const unsigned char *) (addr))[0])
88:
89: # define put16(addr, val) \
90: ({ uint16_t __val = (val); \
91: ((unsigned char *) (addr))[0] = __val; \
92: ((unsigned char *) (addr))[1] = __val >> 8; \
93: (void) 0; })
94: # define put32(addr, val) \
95: ({ uint32_t __val = (val); \
96: ((unsigned char *) (addr))[0] = __val; \
97: __val >>= 8; \
98: ((unsigned char *) (addr))[1] = __val; \
99: __val >>= 8; \
100: ((unsigned char *) (addr))[2] = __val; \
101: __val >>= 8; \
102: ((unsigned char *) (addr))[3] = __val; \
103: (void) 0; })
104: # else
105: # define get16(addr) \
106: (((__const unsigned char *) (addr))[0] << 8 \
107: | ((__const unsigned char *) (addr))[1])
108: # define get32(addr) \
109: (((((__const unsigned char *) (addr))[0] << 8 \
110: | ((__const unsigned char *) (addr))[1]) << 8 \
111: | ((__const unsigned char *) (addr))[2]) << 8 \
112: | ((__const unsigned char *) (addr))[3])
113:
114: # define put16(addr, val) \
115: ({ uint16_t __val = (val); \
116: ((unsigned char *) (addr))[1] = __val; \
117: ((unsigned char *) (addr))[0] = __val >> 8; \
118: (void) 0; })
119: # define put32(addr, val) \
120: ({ uint32_t __val = (val); \
121: ((unsigned char *) (addr))[3] = __val; \
122: __val >>= 8; \
123: ((unsigned char *) (addr))[2] = __val; \
124: __val >>= 8; \
125: ((unsigned char *) (addr))[1] = __val; \
126: __val >>= 8; \
127: ((unsigned char *) (addr))[0] = __val; \
128: (void) 0; })
129: # endif
130:
131: # define FCTNAME2(name) name##_unaligned
132: #endif
133: #define FCTNAME(name) FCTNAME2(name)
134:
135:
136:
137: #ifndef MIN_NEEDED_INPUT
138: # error "MIN_NEEDED_INPUT definition missing"
139: #elif MIN_NEEDED_INPUT < 1
140: # error "MIN_NEEDED_INPUT must be >= 1"
141: #endif
142:
143:
144: #ifndef MAX_NEEDED_INPUT
145: # define MAX_NEEDED_INPUT MIN_NEEDED_INPUT
146: #endif
147:
148:
149: #ifndef MIN_NEEDED_OUTPUT
150: # error "MIN_NEEDED_OUTPUT definition missing"
151: #elif MIN_NEEDED_OUTPUT < 1
152: # error "MIN_NEEDED_OUTPUT must be >= 1"
153: #endif
154:
155:
156: #ifndef MAX_NEEDED_OUTPUT
157: # define MAX_NEEDED_OUTPUT MIN_NEEDED_OUTPUT
158: #endif
159:
160:
161: #ifndef LOOPFCT
162: # define LOOPFCT loop
163: #endif
164:
165:
166: #ifndef BODY
167: # error "Definition of BODY missing for function" LOOPFCT
168: #endif
169:
170:
171:
172:
173: #ifndef EXTRA_LOOP_DECLS
174: # define EXTRA_LOOP_DECLS
175: #endif
176:
177:
178:
179:
180: #define ignore_errors_p() \
181: (irreversible != NULL && (flags & __GCONV_IGNORE_ERRORS))
182:
183:
184:
185:
186:
187: #define STANDARD_FROM_LOOP_ERR_HANDLER(Incr) \
188: { \
189: result = __GCONV_ILLEGAL_INPUT; \
190: \
191: if (! ignore_errors_p ()) \
192: break; \
193: \
194: \
195: inptr += (Incr); \
196: ++*irreversible; \
197:
198: \
199: continue; \
200: }
201:
202:
203:
204:
205:
206: #define STANDARD_TO_LOOP_ERR_HANDLER(Incr) \
207: { \
208: struct __gconv_trans_data *trans; \
209: \
210: result = __GCONV_ILLEGAL_INPUT; \
211: \
212: if (irreversible == NULL) \
213:
214: \
215: break; \
216: \
217: \
218: for (trans = step_data->__trans; trans != NULL; trans = trans->__next) \
219: { \
220: result = DL_CALL_FCT (trans->__trans_fct, \
221: (step, step_data, trans->__data, *inptrp, \
222: &inptr, inend, &outptr, irreversible)); \
223: if (result != __GCONV_ILLEGAL_INPUT) \
224: break; \
225: } \
226: \
227: if (result != __GCONV_ILLEGAL_INPUT) \
228: continue; \
229: \
230: \
231: if (! ignore_errors_p ()) \
232: break; \
233: \
234: \
235: ++*irreversible; \
236: inptr += Incr; \
237:
238: \
239: continue; \
240: }
241:
242:
243:
244:
245:
246:
247: #define UNICODE_TAG_HANDLER(Character, Incr) \
248: { \
249: \
250: if (((Character) >> 7) == (0xe0000 >> 7)) \
251: { \
252: inptr += Incr; \
253: continue; \
254: } \
255: }
256:
257:
258:
259: static inline int
260: __attribute ((always_inline))
261: FCTNAME (LOOPFCT) (struct __gconv_step *step,
262: struct __gconv_step_data *step_data,
263: const unsigned char **inptrp, const unsigned char *inend,
264: unsigned char **outptrp, const unsigned char *outend,
265: size_t *irreversible EXTRA_LOOP_DECLS)
266: {
267: #ifdef LOOP_NEED_STATE
268: mbstate_t *state = step_data->__statep;
269: #endif
270: #ifdef LOOP_NEED_FLAGS
271: int flags = step_data->__flags;
272: #endif
273: #ifdef LOOP_NEED_DATA
274: void *data = step->__data;
275: #endif
276: int result = __GCONV_EMPTY_INPUT;
277: const unsigned char *inptr = *inptrp;
278: unsigned char *outptr = *outptrp;
279:
280: #ifdef INIT_PARAMS
281: INIT_PARAMS;
282: #endif
283:
284: while (inptr != inend)
285: {
286:
287:
288:
289: if (MIN_NEEDED_INPUT > 1
290: && __builtin_expect (inptr + MIN_NEEDED_INPUT > inend, 0))
291: {
292:
293:
294: result = __GCONV_INCOMPLETE_INPUT;
295: break;
296: }
297: if ((MIN_NEEDED_OUTPUT != 1
298: && __builtin_expect (outptr + MIN_NEEDED_OUTPUT > outend, 0))
299: || (MIN_NEEDED_OUTPUT == 1
300: && __builtin_expect (outptr >= outend, 0)))
301: {
302:
303: result = __GCONV_FULL_OUTPUT;
304: break;
305: }
306:
307:
308:
309:
310:
311: BODY
312: }
313:
314:
315: *inptrp = inptr;
316: *outptrp = outptr;
317: #ifdef UPDATE_PARAMS
318: UPDATE_PARAMS;
319: #endif
320:
321: return result;
322: }
323:
324:
325:
326:
327: #if !defined DEFINE_UNALIGNED && !defined _STRING_ARCH_unaligned \
328: && MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
329: && MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
330: # undef get16
331: # undef get32
332: # undef put16
333: # undef put32
334: # undef unaligned
335:
336: # define DEFINE_UNALIGNED
337: # include "loop.c"
338: # undef DEFINE_UNALIGNED
339: #endif
340:
341:
342: #if MAX_NEEDED_INPUT > 1
343: # define SINGLE(fct) SINGLE2 (fct)
344: # define SINGLE2(fct) fct##_single
345: static inline int
346: __attribute ((always_inline))
347: SINGLE(LOOPFCT) (struct __gconv_step *step,
348: struct __gconv_step_data *step_data,
349: const unsigned char **inptrp, const unsigned char *inend,
350: unsigned char **outptrp, unsigned char *outend,
351: size_t *irreversible EXTRA_LOOP_DECLS)
352: {
353: mbstate_t *state = step_data->__statep;
354: #ifdef LOOP_NEED_FLAGS
355: int flags = step_data->__flags;
356: #endif
357: #ifdef LOOP_NEED_DATA
358: void *data = step->__data;
359: #endif
360: int result = __GCONV_OK;
361: unsigned char bytebuf[MAX_NEEDED_INPUT];
362: const unsigned char *inptr = *inptrp;
363: unsigned char *outptr = *outptrp;
364: size_t inlen;
365:
366: #ifdef INIT_PARAMS
367: INIT_PARAMS;
368: #endif
369:
370: #ifdef UNPACK_BYTES
371: UNPACK_BYTES
372: #else
373:
374: for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
375: bytebuf[inlen] = state->__value.__wchb[inlen];
376: #endif
377:
378:
379: if (__builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
380: {
381: *inptrp = inend;
382: #ifdef STORE_REST
383: inptr = bytebuf;
384: inptrp = &inptr;
385: inend = &bytebuf[inlen];
386:
387: STORE_REST
388: #else
389:
390:
391: while (inptr < inend)
392: state->__value.__wchb[inlen++] = *inptr++;
393: #endif
394:
395: return __GCONV_INCOMPLETE_INPUT;
396: }
397:
398:
399: if ((MIN_NEEDED_OUTPUT != 1 && outptr + MIN_NEEDED_OUTPUT > outend)
400: || (MIN_NEEDED_OUTPUT == 1 && outptr >= outend))
401:
402: return __GCONV_FULL_OUTPUT;
403:
404:
405: do
406: bytebuf[inlen++] = *inptr++;
407: while (inlen < MAX_NEEDED_INPUT && inptr < inend);
408:
409: inptr = bytebuf;
410: inend = &bytebuf[inlen];
411:
412: do
413: {
414: BODY
415: }
416: while (0);
417:
418:
419:
420:
421:
422: if (__builtin_expect (inptr != bytebuf, 1))
423: {
424:
425: assert (inptr - bytebuf > (state->__count & 7));
426:
427: *inptrp += inptr - bytebuf - (state->__count & 7);
428: *outptrp = outptr;
429:
430: result = __GCONV_OK;
431:
432:
433: #ifdef CLEAR_STATE
434: CLEAR_STATE;
435: #else
436: state->__count &= ~7;
437: #endif
438: }
439: else if (result == __GCONV_INCOMPLETE_INPUT)
440: {
441:
442:
443: assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
444:
445: *inptrp += inend - bytebuf - (state->__count & 7);
446: #ifdef STORE_REST
447: inptrp = &inptr;
448:
449: STORE_REST
450: #else
451:
452:
453: assert (inend - inptr > (state->__count & ~7));
454: assert (inend - inptr <= 7);
455: state->__count = (state->__count & ~7) | (inend - inptr);
456: inlen = 0;
457: while (inptr < inend)
458: state->__value.__wchb[inlen++] = *inptr++;
459: #endif
460: }
461:
462: return result;
463: }
464: # undef SINGLE
465: # undef SINGLE2
466: #endif
467:
468:
469: #ifdef ONEBYTE_BODY
470:
471: static wint_t
472: gconv_btowc (struct __gconv_step *step, unsigned char c)
473: ONEBYTE_BODY
474: # define FROM_ONEBYTE gconv_btowc
475: #endif
476:
477:
478:
479:
480: #undef MIN_NEEDED_INPUT
481: #undef MAX_NEEDED_INPUT
482: #undef MIN_NEEDED_OUTPUT
483: #undef MAX_NEEDED_OUTPUT
484: #undef LOOPFCT
485: #undef BODY
486: #undef LOOPFCT
487: #undef EXTRA_LOOP_DECLS
488: #undef INIT_PARAMS
489: #undef UPDATE_PARAMS
490: #undef ONEBYTE_BODY
491: #undef UNPACK_BYTES
492: #undef CLEAR_STATE
493: #undef LOOP_NEED_STATE
494: #undef LOOP_NEED_FLAGS
495: #undef LOOP_NEED_DATA
496: #undef get16
497: #undef get32
498: #undef put16
499: #undef put32
500: #undef unaligned