This source file includes following definitions.
- unicode_to_mb
- fwrite_success_callback
- exit_failure_callback
- fallback_failure_callback
- print_unicode_char
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22
23 #include "unicodeio.h"
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <errno.h>
28
29 #if HAVE_ICONV
30 # include <iconv.h>
31 #endif
32
33 #include <error.h>
34
35 #include "gettext.h"
36 #define _(msgid) gettext (msgid)
37 #define N_(msgid) msgid
38
39 #include "localcharset.h"
40 #include "unistr.h"
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 #define UTF8_NAME "UTF-8"
56
57
58
59
60
61
62
63 long
64 unicode_to_mb (unsigned int code,
65 long (*success) (const char *buf, size_t buflen,
66 void *callback_arg),
67 long (*failure) (unsigned int code, const char *msg,
68 void *callback_arg),
69 void *callback_arg)
70 {
71 static int initialized;
72 static int is_utf8;
73 #if HAVE_ICONV
74 static iconv_t utf8_to_local;
75 #endif
76
77 char inbuf[6];
78 int count;
79
80 if (!initialized)
81 {
82 const char *charset = locale_charset ();
83
84 is_utf8 = !strcmp (charset, UTF8_NAME);
85 #if HAVE_ICONV
86 if (!is_utf8)
87 {
88 utf8_to_local = iconv_open (charset, UTF8_NAME);
89 if (utf8_to_local == (iconv_t)(-1))
90
91 utf8_to_local = iconv_open ("ASCII", UTF8_NAME);
92 }
93 #endif
94 initialized = 1;
95 }
96
97
98 if (!is_utf8)
99 {
100 #if HAVE_ICONV
101 if (utf8_to_local == (iconv_t)(-1))
102 return failure (code, N_("iconv function not usable"), callback_arg);
103 #else
104 return failure (code, N_("iconv function not available"), callback_arg);
105 #endif
106 }
107
108
109 count = u8_uctomb ((unsigned char *) inbuf, code, sizeof (inbuf));
110 if (count < 0)
111 return failure (code, N_("character out of range"), callback_arg);
112
113 #if HAVE_ICONV
114 if (!is_utf8)
115 {
116 char outbuf[25];
117 const char *inptr;
118 size_t inbytesleft;
119 char *outptr;
120 size_t outbytesleft;
121 size_t res;
122
123 inptr = inbuf;
124 inbytesleft = count;
125 outptr = outbuf;
126 outbytesleft = sizeof (outbuf);
127
128
129 res = iconv (utf8_to_local,
130 (ICONV_CONST char **)&inptr, &inbytesleft,
131 &outptr, &outbytesleft);
132
133
134
135
136
137
138
139
140 if (inbytesleft > 0 || res == (size_t)(-1)
141
142 # if !defined _LIBICONV_VERSION && (defined sgi || defined __sgi)
143 || (res > 0 && code != 0 && outptr - outbuf == 1 && *outbuf == '\0')
144 # endif
145
146
147 # if !defined _LIBICONV_VERSION
148 || (res > 0 && outptr - outbuf == 1 && *outbuf == '?')
149 # endif
150
151 # if !defined _LIBICONV_VERSION && MUSL_LIBC
152 || (res > 0 && outptr - outbuf == 1 && *outbuf == '*')
153 # endif
154 )
155 return failure (code, NULL, callback_arg);
156
157
158 # if defined _LIBICONV_VERSION \
159 || !(((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) \
160 && !defined __UCLIBC__) \
161 || defined __sun)
162
163
164 res = iconv (utf8_to_local, NULL, NULL, &outptr, &outbytesleft);
165 if (res == (size_t)(-1))
166 return failure (code, NULL, callback_arg);
167 # endif
168
169 return success (outbuf, outptr - outbuf, callback_arg);
170 }
171 #endif
172
173
174 return success (inbuf, count, callback_arg);
175 }
176
177
178
179 long
180 fwrite_success_callback (const char *buf, size_t buflen, void *callback_arg)
181 {
182 FILE *stream = (FILE *) callback_arg;
183
184
185
186
187
188 fwrite (buf, 1, buflen, stream);
189 return 0;
190 }
191
192
193 static long
194 exit_failure_callback (unsigned int code, const char *msg,
195 _GL_UNUSED void *callback_arg)
196 {
197 if (msg == NULL)
198 error (1, 0, _("cannot convert U+%04X to local character set"), code);
199 else
200 error (1, 0, _("cannot convert U+%04X to local character set: %s"), code,
201 gettext (msg));
202 return -1;
203 }
204
205
206
207 static long
208 fallback_failure_callback (unsigned int code,
209 _GL_UNUSED const char *msg,
210 void *callback_arg)
211 {
212 FILE *stream = (FILE *) callback_arg;
213
214 if (code < 0x10000)
215 fprintf (stream, "\\u%04X", code);
216 else
217 fprintf (stream, "\\U%08X", code);
218 return -1;
219 }
220
221
222
223
224 void
225 print_unicode_char (FILE *stream, unsigned int code, int exit_on_error)
226 {
227 unicode_to_mb (code, fwrite_success_callback,
228 exit_on_error
229 ? exit_failure_callback
230 : fallback_failure_callback,
231 stream);
232 }