Update.
[platform/upstream/glibc.git] / iconvdata / 8bit-gap.c
1 /* Generic conversion to and from 8bit charsets,
2    converting from UCS using gaps.
3    Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public
18    License along with the GNU C Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include <dlfcn.h>
23 #include <stdint.h>
24
25 struct gap
26 {
27   uint16_t start;
28   uint16_t end;
29   int32_t idx;
30 };
31
32 /* Now we can include the tables.  */
33 #include TABLES
34
35
36 #define FROM_LOOP               from_gap
37 #define TO_LOOP                 to_gap
38 #define DEFINE_INIT             1
39 #define DEFINE_FINI             1
40 #define MIN_NEEDED_FROM         1
41 #define MIN_NEEDED_TO           4
42
43
44 /* First define the conversion function from the 8bit charset to UCS4.  */
45 #define MIN_NEEDED_INPUT        MIN_NEEDED_FROM
46 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_TO
47 #define LOOPFCT                 FROM_LOOP
48 #define BODY \
49   {                                                                           \
50     uint32_t ch = to_ucs4[*inptr];                                            \
51                                                                               \
52     if (HAS_HOLES && __builtin_expect (ch, L'\1') == L'\0' && *inptr != '\0') \
53       {                                                                       \
54         /* This is an illegal character.  */                                  \
55         if (! ignore_errors_p ())                                             \
56           {                                                                   \
57             result = __GCONV_ILLEGAL_INPUT;                                   \
58             break;                                                            \
59           }                                                                   \
60                                                                               \
61         ++*irreversible;                                                      \
62       }                                                                       \
63     else                                                                      \
64       {                                                                       \
65         put32 (outptr, ch);                                                   \
66         outptr += 4;                                                          \
67       }                                                                       \
68                                                                               \
69     ++inptr;                                                                  \
70   }
71 #define LOOP_NEED_FLAGS
72 #include <iconv/loop.c>
73
74
75 /* Next, define the other direction.  */
76 #define MIN_NEEDED_INPUT        MIN_NEEDED_TO
77 #define MIN_NEEDED_OUTPUT       MIN_NEEDED_FROM
78 #define LOOPFCT                 TO_LOOP
79 #define BODY \
80   {                                                                           \
81     const struct gap *rp = from_idx;                                          \
82     uint32_t ch = get32 (inptr);                                              \
83     unsigned char res;                                                        \
84                                                                               \
85     if (__builtin_expect (ch, 0) >= 0xffff)                                   \
86       {                                                                       \
87         /* This is an illegal character.  */                                  \
88         if (step_data->__trans.__trans_fct != NULL)                           \
89           {                                                                   \
90             result = DL_CALL_FCT (step_data->__trans.__trans_fct,             \
91                                   (step, step_data, *inptrp, &inptr, inend,   \
92                                    *outptrp, &outptr, outend, irreversible)); \
93             if (result != __GCONV_OK)                                         \
94               break;                                                          \
95           }                                                                   \
96         else if (! ignore_errors_p ())                                        \
97           {                                                                   \
98             result = __GCONV_ILLEGAL_INPUT;                                   \
99             break;                                                            \
100           }                                                                   \
101                                                                               \
102         ++*irreversible;                                                      \
103         inptr += 4;                                                           \
104         continue;                                                             \
105       }                                                                       \
106     while (ch > rp->end)                                                      \
107       ++rp;                                                                   \
108     if (__builtin_expect (ch < rp->start, 0))                                 \
109       {                                                                       \
110         /* This is an illegal character.  */                                  \
111         if (step_data->__trans.__trans_fct != NULL)                           \
112           {                                                                   \
113             result = DL_CALL_FCT (step_data->__trans.__trans_fct,             \
114                                   (step, step_data, *inptrp, &inptr, inend,   \
115                                    *outptrp, &outptr, outend, irreversible)); \
116             if (result != __GCONV_OK)                                         \
117               break;                                                          \
118           }                                                                   \
119         else if (! ignore_errors_p ())                                        \
120           {                                                                   \
121             result = __GCONV_ILLEGAL_INPUT;                                   \
122             break;                                                            \
123           }                                                                   \
124         else                                                                  \
125           {                                                                   \
126             ++*irreversible;                                                  \
127             inptr += 4;                                                       \
128           }                                                                   \
129         continue;                                                             \
130       }                                                                       \
131                                                                               \
132     res = from_ucs4[ch + rp->idx];                                            \
133     if (__builtin_expect (res, '\1') == '\0' && ch != 0)                      \
134       {                                                                       \
135         /* This is an illegal character.  */                                  \
136         if (step_data->__trans.__trans_fct != NULL)                           \
137           {                                                                   \
138             result = DL_CALL_FCT (step_data->__trans.__trans_fct,             \
139                                   (step, step_data, *inptrp, &inptr, inend,   \
140                                    *outptrp, &outptr, outend, irreversible)); \
141             if (result != __GCONV_OK)                                         \
142               break;                                                          \
143           }                                                                   \
144         else if (! ignore_errors_p ())                                        \
145           {                                                                   \
146             result = __GCONV_ILLEGAL_INPUT;                                   \
147             break;                                                            \
148           }                                                                   \
149         else                                                                  \
150           {                                                                   \
151             ++*irreversible;                                                  \
152             inptr += 4;                                                       \
153           }                                                                   \
154         continue;                                                             \
155       }                                                                       \
156                                                                               \
157     *outptr++ = res;                                                          \
158     inptr += 4;                                                               \
159   }
160 #define LOOP_NEED_FLAGS
161 #include <iconv/loop.c>
162
163
164 /* Now define the toplevel functions.  */
165 #include <iconv/skeleton.c>