1/* Conversion to and from ARMSCII-8
2 Copyright (C) 1997-2016 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
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, see
18 <http://www.gnu.org/licenses/>. */
19
20#include <dlfcn.h>
21#include <stdint.h>
22
23/* Definitions used in the body of the `gconv' function. */
24#define CHARSET_NAME "ARMSCII-8//"
25#define FROM_LOOP from_armscii_8
26#define TO_LOOP to_armscii_8
27#define DEFINE_INIT 1
28#define DEFINE_FINI 1
29#define MIN_NEEDED_FROM 1
30#define MIN_NEEDED_TO 4
31#define ONE_DIRECTION 0
32
33
34static const uint16_t map_from_armscii_8[0xfe - 0xa2 + 1] =
35 {
36 0x0587, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, 0x2014, 0x002e,
37 0x055d, 0x002c, 0x002d, 0x058a, 0x2026, 0x055c, 0x055b, 0x055e,
38 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, 0x0534, 0x0564,
39 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, 0x0538, 0x0568,
40 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, 0x053c, 0x056c,
41 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, 0x0540, 0x0570,
42 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, 0x0544, 0x0574,
43 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, 0x0548, 0x0578,
44 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, 0x054c, 0x057c,
45 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, 0x0550, 0x0580,
46 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, 0x0554, 0x0584,
47 0x0555, 0x0585, 0x0556, 0x0586, 0x055a
48 };
49
50
51/* First define the conversion function from ARMSCII-8 to UCS4. */
52#define MIN_NEEDED_INPUT MIN_NEEDED_FROM
53#define MIN_NEEDED_OUTPUT MIN_NEEDED_TO
54#define LOOPFCT FROM_LOOP
55#define BODY \
56 { \
57 uint_fast8_t ch = *inptr; \
58 \
59 if (ch <= 0xa0) \
60 { \
61 /* Upto and including 0xa0 the ARMSCII-8 corresponds to Unicode. */ \
62 *((uint32_t *) outptr) = ch; \
63 outptr += sizeof (uint32_t); \
64 } \
65 else if (ch >= 0xa2 && ch <= 0xfe) \
66 { \
67 /* Use the table. */ \
68 *((uint32_t *) outptr) = map_from_armscii_8[ch - 0xa2]; \
69 outptr += sizeof (uint32_t); \
70 } \
71 else \
72 { \
73 /* This is an illegal character. */ \
74 STANDARD_FROM_LOOP_ERR_HANDLER (1); \
75 } \
76 \
77 ++inptr; \
78 }
79#define LOOP_NEED_FLAGS
80#define ONEBYTE_BODY \
81 { \
82 if (c <= 0xa0) \
83 /* Upto and including 0xa0 the ARMSCII-8 corresponds to Unicode. */ \
84 return c; \
85 else if (c >= 0xa2 && c <= 0xfe) \
86 /* Use the table. */ \
87 return map_from_armscii_8[c - 0xa2]; \
88 else \
89 return WEOF; \
90 }
91#include <iconv/loop.c>
92
93
94static const unsigned char map_to_armscii_8[0x58a - 0x531 + 1] =
95 {
96 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 0xc0,
97 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0,
98 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, 0xe0,
99 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0,
100 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0x00, 0x00,
101 0x00, 0xfe, 0xb0, 0xaf, 0xaa, 0xb1, 0x00, 0x00,
102 0xb3, 0xb5, 0xb7, 0xb9, 0xbb, 0xbd, 0xbf, 0xc1,
103 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf, 0xd1,
104 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf, 0xe1,
105 0xe3, 0xe5, 0xe7, 0xe9, 0xeb, 0xed, 0xef, 0xf1,
106 0xf3, 0xf5, 0xf7, 0xf9, 0xfb, 0xfd, 0xa2, 0x00,
107 0xa3, 0xad
108 };
109
110
111/* Next, define the other direction. */
112#define MIN_NEEDED_INPUT MIN_NEEDED_TO
113#define MIN_NEEDED_OUTPUT MIN_NEEDED_FROM
114#define LOOPFCT TO_LOOP
115#define BODY \
116 { \
117 uint32_t ch = *((const uint32_t *) inptr); \
118 \
119 if (ch <= 0xa0) \
120 /* Upto and including 0xa0 the ARMSCII-8 corresponds to Unicode. */ \
121 *outptr = (unsigned char) ch; \
122 else if (ch == 0xab) \
123 *outptr = 0xa7; \
124 else if (ch == 0xbb) \
125 *outptr = 0xa6; \
126 else if (ch >= 0x531 && ch <= 0x58a) \
127 { \
128 unsigned char oc = map_to_armscii_8[ch - 0x531]; \
129 \
130 if (oc == 0) \
131 /* No valid mapping. */ \
132 goto err; \
133 \
134 *outptr = oc; \
135 } \
136 else if (ch == 0x2014) \
137 *outptr = 0xa8; \
138 else if (ch == 0x2026) \
139 *outptr = 0xae; \
140 else \
141 { \
142 UNICODE_TAG_HANDLER (ch, 4); \
143 \
144 /* We have an illegal character. */ \
145 err: \
146 STANDARD_TO_LOOP_ERR_HANDLER (4); \
147 } \
148 ++outptr; \
149 inptr += 4; \
150 }
151#define LOOP_NEED_FLAGS
152#include <iconv/loop.c>
153
154
155/* Now define the toplevel functions. */
156#include <iconv/skeleton.c>
157