Initialize Tizen 2.3
[framework/base/tizen-locale.git] / iconvdata / ibm1364.c
1 /* Conversion from and to IBM1364.
2    Copyright (C) 2005, 2008 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Masahide Washizawa <washi@jp.ibm.com>, 2005.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <dlfcn.h>
22 #include <stdint.h>
23 #include <wchar.h>
24 #include <byteswap.h>
25
26 #ifndef CHARSET_NAME
27 /* This is really the IBM1364 converter, not another module sharing
28    the code.  */
29 # define DATA_HEADER    "ibm1364.h"
30 # define CHARSET_NAME   "IBM1364//"
31 # define FROM_LOOP      from_ibm1364
32 # define TO_LOOP        to_ibm1364
33 # define SB_TO_UCS4     __ibm1364sb_to_ucs4
34 # define DB_TO_UCS4_IDX __ibm1364db_to_ucs4_idx
35 # define DB_TO_UCS4     __ibm1364db_to_ucs4
36 # define UCS4_TO_SB_IDX __ucs4_to_ibm1364sb_idx
37 # define UCS4_TO_SB     __ucs4_to_ibm1364sb
38 # define UCS4_TO_DB_IDX __ucs4_to_ibm1364db_idx
39 # define UCS4_TO_DB     __ucs4_to_ibm1364db
40 # define UCS_LIMIT      0xffff
41 #endif
42
43
44 #include DATA_HEADER
45
46 /* The shift sequences for this charset (it does not use ESC).  */
47 #define SI              0x0F  /* Shift In, host code to turn DBCS off.  */
48 #define SO              0x0E  /* Shift Out, host code to turn DBCS on.  */
49
50 /* Definitions used in the body of the `gconv' function.  */
51 #define MIN_NEEDED_FROM 1
52 #define MAX_NEEDED_FROM 2
53 #define MIN_NEEDED_TO   4
54 #ifdef HAS_COMBINED
55 # define MAX_NEEDED_TO  8
56 #else
57 # define MAX_NEEDED_TO  4
58 #endif
59 #define PREPARE_LOOP \
60   int save_curcs;                                                             \
61   int *curcsp = &data->__statep->__count;
62 #define EXTRA_LOOP_ARGS         , curcsp
63
64 /* Definitions of initialization and destructor function.  */
65 #define DEFINE_INIT     1
66 #define DEFINE_FINI     1
67
68
69 /* Since this is a stateful encoding we have to provide code which resets
70    the output state to the initial state.  This has to be done during the
71    flushing.  */
72 #define EMIT_SHIFT_TO_INIT \
73   if ((data->__statep->__count & ~7) != sb)                                   \
74     {                                                                         \
75       if (FROM_DIRECTION)                                                     \
76         data->__statep->__count &= 7;                                         \
77       else                                                                    \
78         {                                                                     \
79           /* We are not in the initial state.  To switch back we have         \
80              to emit `SI'.  */                                                \
81           if (__builtin_expect (outbuf >= outend, 0))                         \
82             /* We don't have enough room in the output buffer.  */            \
83             status = __GCONV_FULL_OUTPUT;                                     \
84           else                                                                \
85             {                                                                 \
86               /* Write out the shift sequence.  */                            \
87               *outbuf++ = SI;                                                 \
88               data->__statep->__count &= 7;                                   \
89             }                                                                 \
90         }                                                                     \
91     }
92
93
94 /* Since we might have to reset input pointer we must be able to save
95    and retore the state.  */
96 #define SAVE_RESET_STATE(Save) \
97   if (Save)                                                                   \
98     save_curcs = *curcsp;                                                     \
99   else                                                                        \
100     *curcsp = save_curcs
101
102
103 /* Current codeset type.  */
104 enum
105 {
106   sb = 0,
107   db = 64
108 };
109
110
111 /* Subroutine to write out converted UCS4 from IBM-13XX.  */
112 #ifdef HAS_COMBINED
113 # define SUB_COMBINED_UCS_FROM_IBM13XX \
114   {                                                                           \
115     if (res != UCS_LIMIT || ch < __TO_UCS4_COMBINED_MIN                       \
116         || ch > __TO_UCS4_COMBINED_MAX)                                       \
117       {                                                                       \
118         put32 (outptr, res);                                                  \
119         outptr += 4;                                                          \
120       }                                                                       \
121     else                                                                      \
122       {                                                                       \
123         /* This is a combined character.  Make sure we have room.  */         \
124         if (__builtin_expect (outptr + 8 > outend, 0))                        \
125           {                                                                   \
126             result = __GCONV_FULL_OUTPUT;                                     \
127             break;                                                            \
128           }                                                                   \
129                                                                               \
130         const struct divide *cmbp                                             \
131           = &DB_TO_UCS4_COMB[ch - __TO_UCS4_COMBINED_MIN];                    \
132         assert (cmbp->res1 != 0 && cmbp->res2 != 0);                          \
133                                                                               \
134         put32 (outptr, cmbp->res1);                                           \
135         outptr += 4;                                                          \
136         put32 (outptr, cmbp->res2);                                           \
137         outptr += 4;                                                          \
138       }                                                                       \
139   }
140 #else
141 # define SUB_COMBINED_UCS_FROM_IBM13XX \
142   {                                                                           \
143     put32 (outptr, res);                                                      \
144     outptr += 4;                                                              \
145   }
146 #endif /* HAS_COMBINED */
147
148
149 /* First, define the conversion function from IBM-13XX to UCS4.  */
150 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
151 #define MAX_NEEDED_INPUT        MAX_NEEDED_FROM
152 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
153 #define LOOPFCT                 FROM_LOOP
154 #define BODY \
155   {                                                                           \
156     uint32_t ch = *inptr;                                                     \
157                                                                               \
158     if (__builtin_expect (ch, 0) == SO)                                       \
159       {                                                                       \
160         /* Shift OUT, change to DBCS converter.  */                           \
161         if (curcs == db)                                                      \
162           {                                                                   \
163             result = __GCONV_ILLEGAL_INPUT;                                   \
164             break;                                                            \
165           }                                                                   \
166         curcs = db;                                                           \
167         ++inptr;                                                              \
168         continue;                                                             \
169       }                                                                       \
170     if (__builtin_expect (ch, 0) == SI)                                       \
171       {                                                                       \
172         /* Shift IN, change to SBCS converter.  */                            \
173         if (curcs == sb)                                                      \
174           {                                                                   \
175             result = __GCONV_ILLEGAL_INPUT;                                   \
176             break;                                                            \
177           }                                                                   \
178         curcs = sb;                                                           \
179         ++inptr;                                                              \
180         continue;                                                             \
181       }                                                                       \
182                                                                               \
183     if (curcs == sb)                                                          \
184       {                                                                       \
185         /* Use the IBM13XX table for single byte.  */                         \
186         uint32_t res = SB_TO_UCS4[ch];                                \
187         if (__builtin_expect (res, L'\1') == L'\0' && ch != '\0')             \
188           {                                                                   \
189             /* This is an illegal character.  */                              \
190             if (! ignore_errors_p ())                                         \
191               {                                                               \
192                 result = __GCONV_ILLEGAL_INPUT;                               \
193                 break;                                                        \
194               }                                                               \
195             ++*irreversible;                                                  \
196           }                                                                   \
197         else                                                                  \
198           {                                                                   \
199             put32 (outptr, res);                                              \
200             outptr += 4;                                                      \
201           }                                                                   \
202         ++inptr;                                                              \
203       }                                                                       \
204     else                                                                      \
205       {                                                                       \
206         assert (curcs == db);                                                 \
207                                                                               \
208         if (__builtin_expect (inptr + 1 >= inend, 0))                         \
209           {                                                                   \
210             /* The second character is not available.  Store the              \
211                intermediate result.  */                                       \
212             result = __GCONV_INCOMPLETE_INPUT;                                \
213             break;                                                            \
214           }                                                                   \
215                                                                               \
216         ch = (ch * 0x100) + inptr[1];                                         \
217                                                                               \
218         /* Use the IBM1364 table for double byte.  */                         \
219         const struct gap *rp2 = DB_TO_UCS4_IDX;                               \
220         while (ch > rp2->end)                                                 \
221           ++rp2;                                                              \
222                                                                               \
223         uint32_t res;                                                         \
224         if (__builtin_expect (ch < rp2->start, 0)                             \
225             || (res = DB_TO_UCS4[ch + rp2->idx],                              \
226                 __builtin_expect (res, L'\1') == L'\0' && ch != '\0'))        \
227           {                                                                   \
228             /* This is an illegal character.  */                              \
229             if (! ignore_errors_p ())                                         \
230               {                                                               \
231                 result = __GCONV_ILLEGAL_INPUT;                               \
232                 break;                                                        \
233               }                                                               \
234             ++*irreversible;                                                  \
235           }                                                                   \
236         else                                                                  \
237           {                                                                   \
238             SUB_COMBINED_UCS_FROM_IBM13XX;                                    \
239           }                                                                   \
240         inptr += 2;                                                           \
241       }                                                                       \
242   }
243 #define LOOP_NEED_FLAGS
244 #define EXTRA_LOOP_DECLS        , int *curcsp
245 #define INIT_PARAMS             int curcs = *curcsp & ~7
246 #define UPDATE_PARAMS           *curcsp = curcs
247 #include <iconv/loop.c>
248
249
250 /* Subroutine to convert two UCS4 codes to IBM-13XX.  */
251 #ifdef HAS_COMBINED
252 # define SUB_COMBINED_UCS_TO_IBM13XX \
253   {                                                                           \
254     const struct combine *cmbp = UCS4_COMB_TO_DB;                             \
255     while (cmbp->res1 < ch)                                                   \
256       ++cmbp;                                                                 \
257     /* XXX if last char is beginning of combining store in state */           \
258     if (cmbp->res1 == ch && inptr + 4 < inend)                                \
259       {                                                                       \
260         /* See if input is part of a combined character.  */                  \
261         uint32_t ch_next = get32 (inptr + 4);                                 \
262         while (cmbp->res2 != ch_next)                                         \
263           {                                                                   \
264             ++cmbp;                                                           \
265             if (cmbp->res1 != ch)                                             \
266               goto not_combined;                                              \
267           }                                                                   \
268                                                                               \
269         /* It is a combined character.  First make sure we are in             \
270            double byte mode.  */                                              \
271         if (curcs == sb)                                                      \
272           {                                                                   \
273             /* We know there is room for at least one byte.  */               \
274             *outptr++ = SO;                                                   \
275             curcs = db;                                                       \
276           }                                                                   \
277                                                                               \
278         if (__builtin_expect (outptr + 2 > outend, 0))                        \
279           {                                                                   \
280             result = __GCONV_FULL_OUTPUT;                                     \
281             break;                                                            \
282           }                                                                   \
283         *outptr++ = cmbp->ch[0];                                              \
284         *outptr++ = cmbp->ch[1];                                              \
285         inptr += 8;                                                           \
286         continue;                                                             \
287                                                                               \
288       not_combined:;                                                          \
289       }                                                                       \
290   }
291 #else
292 # define SUB_COMBINED_UCS_TO_IBM13XX
293 #endif /* HAS_COMBINED */
294
295
296 /* Next, define the other direction.  */
297 #define MIN_NEEDED_INPUT        MIN_NEEDED_TO
298 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_FROM
299 #define MAX_NEEDED_OUTPUT       MAX_NEEDED_FROM
300 #define LOOPFCT                 TO_LOOP
301 #define BODY \
302   {                                                                           \
303     uint32_t ch = get32 (inptr);                                              \
304                                                                               \
305     if (__builtin_expect (ch >= UCS_LIMIT, 0))                                \
306       {                                                                       \
307         UNICODE_TAG_HANDLER (ch, 4);                                          \
308                                                                               \
309         if (! ignore_errors_p ())                                             \
310           {                                                                   \
311             result = __GCONV_ILLEGAL_INPUT;                                   \
312             break;                                                            \
313           }                                                                   \
314         ++*irreversible;                                                      \
315         inptr += 4;                                                           \
316         continue;                                                             \
317       }                                                                       \
318                                                                               \
319     SUB_COMBINED_UCS_TO_IBM13XX;                                              \
320                                                                               \
321     const struct gap *rp1 = UCS4_TO_SB_IDX;                                   \
322     while (ch > rp1->end)                                                     \
323       ++rp1;                                                                  \
324                                                                               \
325     /* Use the UCS4 table for single byte.  */                                \
326     const char *cp;                                                           \
327     if (__builtin_expect (ch < rp1->start, 0)                                 \
328         || (cp = UCS4_TO_SB[ch + rp1->idx],                                   \
329             __builtin_expect (cp[0], L'\1') == L'\0' && ch != '\0'))          \
330       {                                                                       \
331         /* Use the UCS4 table for double byte.  */                            \
332         const struct gap *rp2 = UCS4_TO_DB_IDX;                               \
333         while (ch > rp2->end)                                                 \
334           ++rp2;                                                              \
335                                                                               \
336         if (__builtin_expect (ch < rp2->start, 0)                             \
337             || (cp = UCS4_TO_DB[ch + rp2->idx],                               \
338                 __builtin_expect (cp[0], L'\1') == L'\0' && ch != '\0'))      \
339           {                                                                   \
340             /* This is an illegal character.  */                              \
341             if (! ignore_errors_p ())                                         \
342               {                                                               \
343                 result = __GCONV_ILLEGAL_INPUT;                               \
344                 break;                                                        \
345               }                                                               \
346             ++*irreversible;                                                  \
347           }                                                                   \
348         else                                                                  \
349           {                                                                   \
350             if (curcs == sb)                                                  \
351               {                                                               \
352                 /* We know there is room for at least one byte.  */           \
353                 *outptr++ = SO;                                               \
354                 curcs = db;                                                   \
355               }                                                               \
356                                                                               \
357             if (__builtin_expect (outptr + 2 > outend, 0))                    \
358               {                                                               \
359                 result = __GCONV_FULL_OUTPUT;                                 \
360                 break;                                                        \
361               }                                                               \
362             *outptr++ = cp[0];                                                \
363             *outptr++ = cp[1];                                                \
364           }                                                                   \
365       }                                                                       \
366     else                                                                      \
367       {                                                                       \
368         if (__builtin_expect (curcs == db, 0))                                \
369           {                                                                   \
370             /* We know there is room for at least one byte.  */               \
371             *outptr++ = SI;                                                   \
372             curcs = sb;                                                       \
373                                                                               \
374             if (__builtin_expect (outptr >= outend, 0))                       \
375               {                                                               \
376                 result = __GCONV_FULL_OUTPUT;                                 \
377                 break;                                                        \
378               }                                                               \
379           }                                                                   \
380                                                                               \
381         *outptr++ = cp[0];                                                    \
382       }                                                                       \
383                                                                               \
384     /* Now that we wrote the output increment the input pointer.  */          \
385     inptr += 4;                                                               \
386   }
387 #define LOOP_NEED_FLAGS
388 #define EXTRA_LOOP_DECLS        , int *curcsp
389 #define INIT_PARAMS             int curcs = *curcsp & ~7
390 #define REINIT_PARAMS           curcs = *curcsp & ~7
391 #define UPDATE_PARAMS           *curcsp = curcs
392 #include <iconv/loop.c>
393
394 /* Now define the toplevel functions.  */
395 #include <iconv/skeleton.c>