* config/tc-spu.c (spu_cons): Use deferred_expression. Handle
[deliverable/binutils-gdb.git] / binutils / winduni.c
1 /* winduni.c -- unicode support for the windres program.
2 Copyright 1997, 1998, 2000, 2001, 2003, 2007
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
5 Rewritten by Kai Tietz, Onevision.
6
7 This file is part of GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22 02110-1301, USA. */
23
24 /* This file contains unicode support routines for the windres
25 program. Ideally, we would have generic unicode support which
26 would work on all systems. However, we don't. Instead, on a
27 Windows host, we are prepared to call some Windows routines. This
28 means that we will generate different output on Windows and Unix
29 hosts, but that seems better than not really supporting unicode at
30 all. */
31
32 #include "sysdep.h"
33 #include "bfd.h"
34 #include "bucomm.h"
35 #include "winduni.h"
36 #include "safe-ctype.h"
37
38 #ifdef _WIN32
39 #include <windows.h>
40 #endif
41
42 /* Prototypes. */
43 static int unichar_isascii (const unichar *, rc_uint_type);
44
45 /* Convert an ASCII string to a unicode string. We just copy it,
46 expanding chars to shorts, rather than doing something intelligent. */
47
48 void
49 unicode_from_ascii (rc_uint_type *length, unichar **unicode, const char *ascii)
50 {
51 rc_uint_type len;
52 #ifndef _WIN32
53 const char *s;
54 unsigned short *w;
55
56 len = strlen (ascii);
57 *unicode = ((unichar *) res_alloc ((len + 1) * sizeof (unichar)));
58 for (s = ascii, w = *unicode; *s != '\0'; s++, w++)
59 *w = *s & 0xff;
60 *w = 0;
61 #else
62 /* We use MultiByteToWideChar rather than strlen to get the unicode
63 string length to allow multibyte "ascii" chars. The value returned
64 by this function includes the trailing '\0'. */
65 len = (rc_uint_type) MultiByteToWideChar (CP_ACP, 0, ascii, -1, NULL, 0);
66 if (len)
67 {
68 *unicode = ((unichar *) res_alloc (len * sizeof (unichar)));
69 MultiByteToWideChar (CP_ACP, 0, ascii, -1, *unicode, (int) len);
70 }
71 /* Discount the trailing '/0'. If MultiByteToWideChar failed,
72 this will set *length to -1. */
73 len--;
74 #endif
75
76 if (length != NULL)
77 *length = len;
78 }
79
80 /* Convert an unicode string to an ASCII string. We just copy it,
81 shrink shorts to chars, rather than doing something intelligent.
82 Shorts with not within the char range are replaced by '_'. */
83
84 void
85 ascii_from_unicode (rc_uint_type *length, const unichar *unicode, char **ascii)
86 {
87 rc_uint_type len;
88 #ifndef _WIN32
89 char *s;
90 const unsigned short *w;
91
92 len = 0;
93 while (unicode[len] != 0)
94 ++len;
95 *ascii = ((char *) res_alloc (len + 1));
96 for (s = *ascii, w = unicode; *w != '\0'; w++, s++)
97 {
98 if(w[0]==(w[0]&0xff))
99 *s = (char) w[0];
100 else
101 *s = '_';
102 }
103 *s = 0;
104 #else
105 WINBOOL used_def = FALSE;
106 /* We use MultiByteToWideChar rather than strlen to get the unicode
107 string length to allow multibyte "ascii" chars. The value returned
108 by this function includes the trailing '\0'. */
109 len = (rc_uint_type) WideCharToMultiByte (CP_ACP, WC_DEFAULTCHAR, unicode, -1, NULL,
110 0, "_", &used_def);
111 if (len)
112 {
113 *ascii = (char *) res_alloc (len * sizeof (char));
114 WideCharToMultiByte (CP_ACP, WC_DEFAULTCHAR, unicode, -1, *ascii, (int) len,
115 "_", &used_def);
116 }
117 /* Discount the trailing '/0'. If MultiByteToWideChar failed,
118 this will set *length to -1. */
119 len--;
120 #endif
121
122 if (length != NULL)
123 *length = len;
124 }
125
126 /* Print the unicode string UNICODE to the file E. LENGTH is the
127 number of characters to print, or -1 if we should print until the
128 end of the string. FIXME: On a Windows host, we should be calling
129 some Windows function, probably WideCharToMultiByte. */
130
131 void
132 unicode_print (FILE *e, const unichar *unicode, rc_uint_type length)
133 {
134 while (1)
135 {
136 unichar ch;
137
138 if (length == 0)
139 return;
140 if ((bfd_signed_vma) length > 0)
141 --length;
142
143 ch = *unicode;
144
145 if (ch == 0 && (bfd_signed_vma) length < 0)
146 return;
147
148 ++unicode;
149
150 if ((ch & 0x7f) == ch)
151 {
152 if (ch == '\\')
153 fputs ("\\\\", e);
154 else if (ch == '"')
155 fputs ("\"\"", e);
156 else if (ISPRINT (ch))
157 putc (ch, e);
158 else
159 {
160 switch (ch)
161 {
162 case ESCAPE_A:
163 fputs ("\\a", e);
164 break;
165
166 case ESCAPE_B:
167 fputs ("\\b", e);
168 break;
169
170 case ESCAPE_F:
171 fputs ("\\f", e);
172 break;
173
174 case ESCAPE_N:
175 fputs ("\\n", e);
176 break;
177
178 case ESCAPE_R:
179 fputs ("\\r", e);
180 break;
181
182 case ESCAPE_T:
183 fputs ("\\t", e);
184 break;
185
186 case ESCAPE_V:
187 fputs ("\\v", e);
188 break;
189
190 default:
191 fprintf (e, "\\%03o", (unsigned int) ch);
192 break;
193 }
194 }
195 }
196 else if ((ch & 0xff) == ch)
197 fprintf (e, "\\%03o", (unsigned int) ch);
198 else
199 fprintf (e, "\\x%x", (unsigned int) ch);
200 }
201 }
202
203 /* Print a unicode string to a file. */
204 void
205 ascii_print (FILE *e, const char *s, rc_uint_type length)
206 {
207 while (1)
208 {
209 char ch;
210
211 if (length == 0)
212 return;
213 if ((bfd_signed_vma) length > 0)
214 --length;
215
216 ch = *s;
217
218 if (ch == 0 && (bfd_signed_vma) length < 0)
219 return;
220
221 ++s;
222
223 if ((ch & 0x7f) == ch)
224 {
225 if (ch == '\\')
226 fputs ("\\\\", e);
227 else if (ch == '"')
228 fputs ("\"\"", e);
229 else if (ISPRINT (ch))
230 putc (ch, e);
231 else
232 {
233 switch (ch)
234 {
235 case ESCAPE_A:
236 fputs ("\\a", e);
237 break;
238
239 case ESCAPE_B:
240 fputs ("\\b", e);
241 break;
242
243 case ESCAPE_F:
244 fputs ("\\f", e);
245 break;
246
247 case ESCAPE_N:
248 fputs ("\\n", e);
249 break;
250
251 case ESCAPE_R:
252 fputs ("\\r", e);
253 break;
254
255 case ESCAPE_T:
256 fputs ("\\t", e);
257 break;
258
259 case ESCAPE_V:
260 fputs ("\\v", e);
261 break;
262
263 default:
264 fprintf (e, "\\%03o", (unsigned int) ch);
265 break;
266 }
267 }
268 }
269 else
270 fprintf (e, "\\%03o", (unsigned int) ch & 0xff);
271 }
272 }
273
274 rc_uint_type
275 unichar_len (const unichar *unicode)
276 {
277 rc_uint_type r = 0;
278 if (unicode)
279 while (unicode[r] != 0)
280 r++;
281 else
282 --r;
283 return r;
284 }
285
286 unichar *
287 unichar_dup (const unichar *unicode)
288 {
289 unichar *r;
290 int len;
291
292 if (! unicode)
293 return NULL;
294 for (len = 0; unicode[len] != 0; ++len)
295 ;
296 ++len;
297 r = ((unichar *) res_alloc (len * sizeof (unichar)));
298 memcpy (r, unicode, len * sizeof (unichar));
299 return r;
300 }
301
302 unichar *
303 unichar_dup_uppercase (const unichar *u)
304 {
305 unichar *r = unichar_dup (u);
306 int i;
307
308 if (! r)
309 return NULL;
310
311 for (i = 0; r[i] != 0; ++i)
312 {
313 if (r[i] >= 'a' && r[i] <= 'z')
314 r[i] &= 0xdf;
315 }
316 return r;
317 }
318
319 static int
320 unichar_isascii (const unichar *u, rc_uint_type len)
321 {
322 rc_uint_type i;
323 if ((bfd_signed_vma) len < 0)
324 {
325 if (u)
326 len = (rc_uint_type) unichar_len (u);
327 else
328 len = 0;
329 }
330
331 for (i = 0; i < len; i++)
332 if ((u[i] & 0xff80) != 0)
333 return 0;
334 return 1;
335 }
336
337 void
338 unicode_print_quoted (FILE *e, const unichar *u, rc_uint_type len)
339 {
340 if (! unichar_isascii (u, len))
341 fputc ('L', e);
342 fputc ('"', e);
343 unicode_print (e, u, len);
344 fputc ('"', e);
345 }
This page took 0.037091 seconds and 5 git commands to generate.