Update.
[glibc.git] / iconvdata / tst-table-from.c
blobb24632e1b96ab3da9bd760b7258b348bdec23d18
1 /* Copyright (C) 2000-2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 /* Create a table from CHARSET to Unicode.
21 This is a good test for CHARSET's iconv() module, in particular the
22 FROM_LOOP BODY macro. */
24 #include <stddef.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <iconv.h>
29 #include <errno.h>
31 /* Converts a byte buffer to a hexadecimal string. */
32 static const char*
33 hexbuf (unsigned char buf[], unsigned int buflen)
35 static char msg[50];
37 switch (buflen)
39 case 1:
40 sprintf (msg, "0x%02X", buf[0]);
41 break;
42 case 2:
43 sprintf (msg, "0x%02X%02X", buf[0], buf[1]);
44 break;
45 case 3:
46 sprintf (msg, "0x%02X%02X%02X", buf[0], buf[1], buf[2]);
47 break;
48 case 4:
49 sprintf (msg, "0x%02X%02X%02X%02X", buf[0], buf[1], buf[2], buf[3]);
50 break;
51 default:
52 abort ();
54 return msg;
57 /* Attempts to convert a byte buffer BUF (BUFLEN bytes) to OUT (6 bytes)
58 using the conversion descriptor CD. Returns the number of written bytes,
59 or 0 if ambiguous, or -1 if invalid. */
60 static int
61 try (iconv_t cd, unsigned char buf[], unsigned int buflen, unsigned char *out)
63 const char *inbuf = (const char *) buf;
64 size_t inbytesleft = buflen;
65 char *outbuf = (char *) out;
66 size_t outbytesleft = 6;
67 size_t result;
69 iconv (cd, NULL, NULL, NULL, NULL);
70 result = iconv (cd, (char **) &inbuf, &inbytesleft, &outbuf, &outbytesleft);
71 if (result != (size_t)(-1))
72 result = iconv (cd, NULL, NULL, &outbuf, &outbytesleft);
74 if (result == (size_t)(-1))
76 if (errno == EILSEQ)
78 return -1;
80 else if (errno == EINVAL)
82 return 0;
84 else
86 int saved_errno = errno;
87 fprintf (stderr, "%s: iconv error: ", hexbuf (buf, buflen));
88 errno = saved_errno;
89 perror ("");
90 exit (1);
93 else
95 if (inbytesleft != 0)
97 fprintf (stderr, "%s: inbytes = %ld, outbytes = %ld\n",
98 hexbuf (buf, buflen),
99 (long) (buflen - inbytesleft),
100 (long) (6 - outbytesleft));
101 exit (1);
103 return 6 - outbytesleft;
107 /* Returns the out[] buffer as a Unicode value, formatted as 0x%04X. */
108 static const char *
109 utf8_decode (const unsigned char *out, unsigned int outlen)
111 static char hexbuf[42];
112 char *p = hexbuf;
114 while (outlen > 0)
116 if (p > hexbuf)
117 *p++ = ' ';
119 if (out[0] < 0x80)
121 sprintf (p, "0x%04X", out[0]);
122 out += 1; outlen -= 1;
124 else if (out[0] >= 0xc0 && out[0] < 0xe0 && outlen >= 2)
126 sprintf (p, "0x%04X", ((out[0] & 0x1f) << 6) + (out[1] & 0x3f));
127 out += 2; outlen -= 2;
129 else if (out[0] >= 0xe0 && out[0] < 0xf0 && outlen >= 3)
131 sprintf (p, "0x%04X", ((out[0] & 0x0f) << 12)
132 + ((out[1] & 0x3f) << 6) + (out[2] & 0x3f));
133 out += 3; outlen -= 3;
135 else if (out[0] >= 0xf0 && out[0] < 0xf8 && outlen >= 4)
137 sprintf (p, "0x%04X", ((out[0] & 0x07) << 18)
138 + ((out[1] & 0x3f) << 12)
139 + ((out[2] & 0x3f) << 6) + (out[3] & 0x3f));
140 out += 4; outlen -= 4;
142 else if (out[0] >= 0xf8 && out[0] < 0xfc && outlen >= 5)
144 sprintf (p, "0x%04X", ((out[0] & 0x03) << 24)
145 + ((out[1] & 0x3f) << 18)
146 + ((out[2] & 0x3f) << 12)
147 + ((out[3] & 0x3f) << 6) + (out[4] & 0x3f));
148 out += 5; outlen -= 5;
150 else if (out[0] >= 0xfc && out[0] < 0xfe && outlen >= 6)
152 sprintf (p, "0x%04X", ((out[0] & 0x01) << 30)
153 + ((out[1] & 0x3f) << 24)
154 + ((out[2] & 0x3f) << 18)
155 + ((out[3] & 0x3f) << 12)
156 + ((out[4] & 0x3f) << 6) + (out[5] & 0x3f));
157 out += 6; outlen -= 6;
159 else
161 sprintf (p, "0x????");
162 out += 1; outlen -= 1;
165 p += strlen (p);
168 return hexbuf;
172 main (int argc, char *argv[])
174 const char *charset;
175 iconv_t cd;
177 if (argc != 2)
179 fprintf (stderr, "Usage: tst-table-to charset\n");
180 exit (1);
182 charset = argv[1];
184 cd = iconv_open ("UTF-8", charset);
185 if (cd == (iconv_t)(-1))
187 perror ("iconv_open");
188 exit (1);
192 unsigned char out[6];
193 unsigned char buf[4];
194 unsigned int i0, i1, i2, i3;
195 int result;
197 for (i0 = 0; i0 < 0x100; i0++)
199 buf[0] = i0;
200 result = try (cd, buf, 1, out);
201 if (result < 0)
204 else if (result > 0)
206 printf ("0x%02X\t%s\n",
207 i0, utf8_decode (out, result));
209 else
211 for (i1 = 0; i1 < 0x100; i1++)
213 buf[1] = i1;
214 result = try (cd, buf, 2, out);
215 if (result < 0)
218 else if (result > 0)
220 printf ("0x%02X%02X\t%s\n",
221 i0, i1, utf8_decode (out, result));
223 else
225 for (i2 = 0; i2 < 0x100; i2++)
227 buf[2] = i2;
228 result = try (cd, buf, 3, out);
229 if (result < 0)
232 else if (result > 0)
234 printf ("0x%02X%02X%02X\t%s\n",
235 i0, i1, i2, utf8_decode (out, result));
237 else if (strcmp (charset, "UTF-8"))
239 for (i3 = 0; i3 < 0x100; i3++)
241 buf[3] = i3;
242 result = try (cd, buf, 4, out);
243 if (result < 0)
246 else if (result > 0)
248 printf ("0x%02X%02X%02X%02X\t%s\n",
249 i0, i1, i2, i3,
250 utf8_decode (out, result));
252 else
254 fprintf (stderr,
255 "%s: incomplete byte sequence\n",
256 hexbuf (buf, 4));
257 exit (1);
268 if (iconv_close (cd) < 0)
270 perror ("iconv_close");
271 exit (1);
274 if (ferror (stdin) || fflush (stdout) || ferror (stdout))
276 fprintf (stderr, "I/O error\n");
277 exit (1);
280 return 0;