Mercurial > hg > CbC > CbC_gcc
annotate gcc/pretty-print.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
rev | line source |
---|---|
0 | 1 /* Various declarations for language-independent pretty-print subroutines. |
131 | 2 Copyright (C) 2003-2018 Free Software Foundation, Inc. |
0 | 3 Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net> |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it under | |
8 the terms of the GNU General Public License as published by the Free | |
9 Software Foundation; either version 3, or (at your option) any later | |
10 version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
21 #include "config.h" | |
22 #include "system.h" | |
23 #include "coretypes.h" | |
24 #include "intl.h" | |
25 #include "pretty-print.h" | |
111 | 26 #include "diagnostic-color.h" |
27 #include "selftest.h" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
28 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
29 #if HAVE_ICONV |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
30 #include <iconv.h> |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
31 #endif |
0 | 32 |
111 | 33 #ifdef __MINGW32__ |
34 | |
35 /* Replacement for fputs() that handles ANSI escape codes on Windows NT. | |
36 Contributed by: Liu Hao (lh_mouse at 126 dot com) | |
37 | |
38 XXX: This file is compiled into libcommon.a that will be self-contained. | |
39 It looks like that these functions can be put nowhere else. */ | |
40 | |
41 #include <io.h> | |
42 #define WIN32_LEAN_AND_MEAN 1 | |
43 #include <windows.h> | |
44 | |
45 /* Write all bytes in [s,s+n) into the specified stream. | |
46 Errors are ignored. */ | |
47 static void | |
48 write_all (HANDLE h, const char *s, size_t n) | |
49 { | |
50 size_t rem = n; | |
51 DWORD step; | |
52 | |
53 while (rem != 0) | |
54 { | |
55 if (rem <= UINT_MAX) | |
56 step = rem; | |
57 else | |
58 step = UINT_MAX; | |
59 if (!WriteFile (h, s + n - rem, step, &step, NULL)) | |
60 break; | |
61 rem -= step; | |
62 } | |
63 } | |
64 | |
65 /* Find the beginning of an escape sequence. | |
66 There are two cases: | |
67 1. If the sequence begins with an ESC character (0x1B) and a second | |
68 character X in [0x40,0x5F], returns X and stores a pointer to | |
69 the third character into *head. | |
70 2. If the sequence begins with a character X in [0x80,0x9F], returns | |
71 (X-0x40) and stores a pointer to the second character into *head. | |
72 Stores the number of ESC character(s) in *prefix_len. | |
73 Returns 0 if no such sequence can be found. */ | |
74 static int | |
75 find_esc_head (int *prefix_len, const char **head, const char *str) | |
76 { | |
77 int c; | |
78 const char *r = str; | |
79 int escaped = 0; | |
80 | |
81 for (;;) | |
82 { | |
83 c = (unsigned char) *r; | |
84 if (c == 0) | |
85 { | |
86 /* Not found. */ | |
87 return 0; | |
88 } | |
89 if (escaped && 0x40 <= c && c <= 0x5F) | |
90 { | |
91 /* Found (case 1). */ | |
92 *prefix_len = 2; | |
93 *head = r + 1; | |
94 return c; | |
95 } | |
96 if (0x80 <= c && c <= 0x9F) | |
97 { | |
98 /* Found (case 2). */ | |
99 *prefix_len = 1; | |
100 *head = r + 1; | |
101 return c - 0x40; | |
102 } | |
103 ++r; | |
104 escaped = c == 0x1B; | |
105 } | |
106 } | |
107 | |
108 /* Find the terminator of an escape sequence. | |
109 str should be the value stored in *head by a previous successful | |
110 call to find_esc_head(). | |
111 Returns 0 if no such sequence can be found. */ | |
112 static int | |
113 find_esc_terminator (const char **term, const char *str) | |
114 { | |
115 int c; | |
116 const char *r = str; | |
117 | |
118 for (;;) | |
119 { | |
120 c = (unsigned char) *r; | |
121 if (c == 0) | |
122 { | |
123 /* Not found. */ | |
124 return 0; | |
125 } | |
126 if (0x40 <= c && c <= 0x7E) | |
127 { | |
128 /* Found. */ | |
129 *term = r; | |
130 return c; | |
131 } | |
132 ++r; | |
133 } | |
134 } | |
135 | |
136 /* Handle a sequence of codes. Sequences that are invalid, reserved, | |
137 unrecognized or unimplemented are ignored silently. | |
138 There isn't much we can do because of lameness of Windows consoles. */ | |
139 static void | |
140 eat_esc_sequence (HANDLE h, int esc_code, | |
141 const char *esc_head, const char *esc_term) | |
142 { | |
143 /* Numbers in an escape sequence cannot be negative, because | |
144 a minus sign in the middle of it would have terminated it. */ | |
145 long n1, n2; | |
146 char *eptr, *delim; | |
147 CONSOLE_SCREEN_BUFFER_INFO sb; | |
148 COORD cr; | |
149 /* ED and EL parameters. */ | |
150 DWORD cnt, step; | |
151 long rows; | |
152 /* SGR parameters. */ | |
153 WORD attrib_add, attrib_rm; | |
154 const char *param; | |
155 | |
156 switch (MAKEWORD (esc_code, *esc_term)) | |
157 { | |
158 /* ESC [ n1 'A' | |
159 Move the cursor up by n1 characters. */ | |
160 case MAKEWORD ('[', 'A'): | |
161 if (esc_head == esc_term) | |
162 n1 = 1; | |
163 else | |
164 { | |
165 n1 = strtol (esc_head, &eptr, 10); | |
166 if (eptr != esc_term) | |
167 break; | |
168 } | |
169 | |
170 if (GetConsoleScreenBufferInfo (h, &sb)) | |
171 { | |
172 cr = sb.dwCursorPosition; | |
173 /* Stop at the topmost boundary. */ | |
174 if (cr.Y > n1) | |
175 cr.Y -= n1; | |
176 else | |
177 cr.Y = 0; | |
178 SetConsoleCursorPosition (h, cr); | |
179 } | |
180 break; | |
181 | |
182 /* ESC [ n1 'B' | |
183 Move the cursor down by n1 characters. */ | |
184 case MAKEWORD ('[', 'B'): | |
185 if (esc_head == esc_term) | |
186 n1 = 1; | |
187 else | |
188 { | |
189 n1 = strtol (esc_head, &eptr, 10); | |
190 if (eptr != esc_term) | |
191 break; | |
192 } | |
193 | |
194 if (GetConsoleScreenBufferInfo (h, &sb)) | |
195 { | |
196 cr = sb.dwCursorPosition; | |
197 /* Stop at the bottommost boundary. */ | |
198 if (sb.dwSize.Y - cr.Y > n1) | |
199 cr.Y += n1; | |
200 else | |
201 cr.Y = sb.dwSize.Y; | |
202 SetConsoleCursorPosition (h, cr); | |
203 } | |
204 break; | |
205 | |
206 /* ESC [ n1 'C' | |
207 Move the cursor right by n1 characters. */ | |
208 case MAKEWORD ('[', 'C'): | |
209 if (esc_head == esc_term) | |
210 n1 = 1; | |
211 else | |
212 { | |
213 n1 = strtol (esc_head, &eptr, 10); | |
214 if (eptr != esc_term) | |
215 break; | |
216 } | |
217 | |
218 if (GetConsoleScreenBufferInfo (h, &sb)) | |
219 { | |
220 cr = sb.dwCursorPosition; | |
221 /* Stop at the rightmost boundary. */ | |
222 if (sb.dwSize.X - cr.X > n1) | |
223 cr.X += n1; | |
224 else | |
225 cr.X = sb.dwSize.X; | |
226 SetConsoleCursorPosition (h, cr); | |
227 } | |
228 break; | |
229 | |
230 /* ESC [ n1 'D' | |
231 Move the cursor left by n1 characters. */ | |
232 case MAKEWORD ('[', 'D'): | |
233 if (esc_head == esc_term) | |
234 n1 = 1; | |
235 else | |
236 { | |
237 n1 = strtol (esc_head, &eptr, 10); | |
238 if (eptr != esc_term) | |
239 break; | |
240 } | |
241 | |
242 if (GetConsoleScreenBufferInfo (h, &sb)) | |
243 { | |
244 cr = sb.dwCursorPosition; | |
245 /* Stop at the leftmost boundary. */ | |
246 if (cr.X > n1) | |
247 cr.X -= n1; | |
248 else | |
249 cr.X = 0; | |
250 SetConsoleCursorPosition (h, cr); | |
251 } | |
252 break; | |
253 | |
254 /* ESC [ n1 'E' | |
255 Move the cursor to the beginning of the n1-th line downwards. */ | |
256 case MAKEWORD ('[', 'E'): | |
257 if (esc_head == esc_term) | |
258 n1 = 1; | |
259 else | |
260 { | |
261 n1 = strtol (esc_head, &eptr, 10); | |
262 if (eptr != esc_term) | |
263 break; | |
264 } | |
265 | |
266 if (GetConsoleScreenBufferInfo (h, &sb)) | |
267 { | |
268 cr = sb.dwCursorPosition; | |
269 cr.X = 0; | |
270 /* Stop at the bottommost boundary. */ | |
271 if (sb.dwSize.Y - cr.Y > n1) | |
272 cr.Y += n1; | |
273 else | |
274 cr.Y = sb.dwSize.Y; | |
275 SetConsoleCursorPosition (h, cr); | |
276 } | |
277 break; | |
278 | |
279 /* ESC [ n1 'F' | |
280 Move the cursor to the beginning of the n1-th line upwards. */ | |
281 case MAKEWORD ('[', 'F'): | |
282 if (esc_head == esc_term) | |
283 n1 = 1; | |
284 else | |
285 { | |
286 n1 = strtol (esc_head, &eptr, 10); | |
287 if (eptr != esc_term) | |
288 break; | |
289 } | |
290 | |
291 if (GetConsoleScreenBufferInfo (h, &sb)) | |
292 { | |
293 cr = sb.dwCursorPosition; | |
294 cr.X = 0; | |
295 /* Stop at the topmost boundary. */ | |
296 if (cr.Y > n1) | |
297 cr.Y -= n1; | |
298 else | |
299 cr.Y = 0; | |
300 SetConsoleCursorPosition (h, cr); | |
301 } | |
302 break; | |
303 | |
304 /* ESC [ n1 'G' | |
305 Move the cursor to the (1-based) n1-th column. */ | |
306 case MAKEWORD ('[', 'G'): | |
307 if (esc_head == esc_term) | |
308 n1 = 1; | |
309 else | |
310 { | |
311 n1 = strtol (esc_head, &eptr, 10); | |
312 if (eptr != esc_term) | |
313 break; | |
314 } | |
315 | |
316 if (GetConsoleScreenBufferInfo (h, &sb)) | |
317 { | |
318 cr = sb.dwCursorPosition; | |
319 n1 -= 1; | |
320 /* Stop at the leftmost or rightmost boundary. */ | |
321 if (n1 < 0) | |
322 cr.X = 0; | |
323 else if (n1 > sb.dwSize.X) | |
324 cr.X = sb.dwSize.X; | |
325 else | |
326 cr.X = n1; | |
327 SetConsoleCursorPosition (h, cr); | |
328 } | |
329 break; | |
330 | |
331 /* ESC [ n1 ';' n2 'H' | |
332 ESC [ n1 ';' n2 'f' | |
333 Move the cursor to the (1-based) n1-th row and | |
334 (also 1-based) n2-th column. */ | |
335 case MAKEWORD ('[', 'H'): | |
336 case MAKEWORD ('[', 'f'): | |
337 if (esc_head == esc_term) | |
338 { | |
339 /* Both parameters are omitted and set to 1 by default. */ | |
340 n1 = 1; | |
341 n2 = 1; | |
342 } | |
343 else if (!(delim = (char *) memchr (esc_head, ';', | |
344 esc_term - esc_head))) | |
345 { | |
346 /* Only the first parameter is given. The second one is | |
347 set to 1 by default. */ | |
348 n1 = strtol (esc_head, &eptr, 10); | |
349 if (eptr != esc_term) | |
350 break; | |
351 n2 = 1; | |
352 } | |
353 else | |
354 { | |
355 /* Both parameters are given. The first one shall be | |
356 terminated by the semicolon. */ | |
357 n1 = strtol (esc_head, &eptr, 10); | |
358 if (eptr != delim) | |
359 break; | |
360 n2 = strtol (delim + 1, &eptr, 10); | |
361 if (eptr != esc_term) | |
362 break; | |
363 } | |
364 | |
365 if (GetConsoleScreenBufferInfo (h, &sb)) | |
366 { | |
367 cr = sb.dwCursorPosition; | |
368 n1 -= 1; | |
369 n2 -= 1; | |
370 /* The cursor position shall be relative to the view coord of | |
371 the console window, which is usually smaller than the actual | |
372 buffer. FWIW, the 'appropriate' solution will be shrinking | |
373 the buffer to match the size of the console window, | |
374 destroying scrollback in the process. */ | |
375 n1 += sb.srWindow.Top; | |
376 n2 += sb.srWindow.Left; | |
377 /* Stop at the topmost or bottommost boundary. */ | |
378 if (n1 < 0) | |
379 cr.Y = 0; | |
380 else if (n1 > sb.dwSize.Y) | |
381 cr.Y = sb.dwSize.Y; | |
382 else | |
383 cr.Y = n1; | |
384 /* Stop at the leftmost or rightmost boundary. */ | |
385 if (n2 < 0) | |
386 cr.X = 0; | |
387 else if (n2 > sb.dwSize.X) | |
388 cr.X = sb.dwSize.X; | |
389 else | |
390 cr.X = n2; | |
391 SetConsoleCursorPosition (h, cr); | |
392 } | |
393 break; | |
394 | |
395 /* ESC [ n1 'J' | |
396 Erase display. */ | |
397 case MAKEWORD ('[', 'J'): | |
398 if (esc_head == esc_term) | |
399 /* This is one of the very few codes whose parameters have | |
400 a default value of zero. */ | |
401 n1 = 0; | |
402 else | |
403 { | |
404 n1 = strtol (esc_head, &eptr, 10); | |
405 if (eptr != esc_term) | |
406 break; | |
407 } | |
408 | |
409 if (GetConsoleScreenBufferInfo (h, &sb)) | |
410 { | |
411 /* The cursor is not necessarily in the console window, which | |
412 makes the behavior of this code harder to define. */ | |
413 switch (n1) | |
414 { | |
415 case 0: | |
416 /* If the cursor is in or above the window, erase from | |
417 it to the bottom of the window; otherwise, do nothing. */ | |
418 cr = sb.dwCursorPosition; | |
419 cnt = sb.dwSize.X - sb.dwCursorPosition.X; | |
420 rows = sb.srWindow.Bottom - sb.dwCursorPosition.Y; | |
421 break; | |
422 case 1: | |
423 /* If the cursor is in or under the window, erase from | |
424 it to the top of the window; otherwise, do nothing. */ | |
425 cr.X = 0; | |
426 cr.Y = sb.srWindow.Top; | |
427 cnt = sb.dwCursorPosition.X + 1; | |
428 rows = sb.dwCursorPosition.Y - sb.srWindow.Top; | |
429 break; | |
430 case 2: | |
431 /* Erase the entire window. */ | |
432 cr.X = sb.srWindow.Left; | |
433 cr.Y = sb.srWindow.Top; | |
434 cnt = 0; | |
435 rows = sb.srWindow.Bottom - sb.srWindow.Top + 1; | |
436 break; | |
437 default: | |
438 /* Erase the entire buffer. */ | |
439 cr.X = 0; | |
440 cr.Y = 0; | |
441 cnt = 0; | |
442 rows = sb.dwSize.Y; | |
443 break; | |
444 } | |
445 if (rows < 0) | |
446 break; | |
447 cnt += rows * sb.dwSize.X; | |
448 FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step); | |
449 FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step); | |
450 } | |
451 break; | |
452 | |
453 /* ESC [ n1 'K' | |
454 Erase line. */ | |
455 case MAKEWORD ('[', 'K'): | |
456 if (esc_head == esc_term) | |
457 /* This is one of the very few codes whose parameters have | |
458 a default value of zero. */ | |
459 n1 = 0; | |
460 else | |
461 { | |
462 n1 = strtol (esc_head, &eptr, 10); | |
463 if (eptr != esc_term) | |
464 break; | |
465 } | |
466 | |
467 if (GetConsoleScreenBufferInfo (h, &sb)) | |
468 { | |
469 switch (n1) | |
470 { | |
471 case 0: | |
472 /* Erase from the cursor to the end. */ | |
473 cr = sb.dwCursorPosition; | |
474 cnt = sb.dwSize.X - sb.dwCursorPosition.X; | |
475 break; | |
476 case 1: | |
477 /* Erase from the cursor to the beginning. */ | |
478 cr = sb.dwCursorPosition; | |
479 cr.X = 0; | |
480 cnt = sb.dwCursorPosition.X + 1; | |
481 break; | |
482 default: | |
483 /* Erase the entire line. */ | |
484 cr = sb.dwCursorPosition; | |
485 cr.X = 0; | |
486 cnt = sb.dwSize.X; | |
487 break; | |
488 } | |
489 FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step); | |
490 FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step); | |
491 } | |
492 break; | |
493 | |
494 /* ESC [ n1 ';' n2 'm' | |
495 Set SGR parameters. Zero or more parameters will follow. */ | |
496 case MAKEWORD ('[', 'm'): | |
497 attrib_add = 0; | |
498 attrib_rm = 0; | |
499 if (esc_head == esc_term) | |
500 { | |
501 /* When no parameter is given, reset the console. */ | |
502 attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN | |
503 | FOREGROUND_BLUE); | |
504 attrib_rm = -1; /* Removes everything. */ | |
505 goto sgr_set_it; | |
506 } | |
507 param = esc_head; | |
508 do | |
509 { | |
510 /* Parse a parameter. */ | |
511 n1 = strtol (param, &eptr, 10); | |
512 if (*eptr != ';' && eptr != esc_term) | |
513 goto sgr_set_it; | |
514 | |
515 switch (n1) | |
516 { | |
517 case 0: | |
518 /* Reset. */ | |
519 attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN | |
520 | FOREGROUND_BLUE); | |
521 attrib_rm = -1; /* Removes everything. */ | |
522 break; | |
523 case 1: | |
524 /* Bold. */ | |
525 attrib_add |= FOREGROUND_INTENSITY; | |
526 break; | |
527 case 4: | |
528 /* Underline. */ | |
529 attrib_add |= COMMON_LVB_UNDERSCORE; | |
530 break; | |
531 case 5: | |
532 /* Blink. */ | |
533 /* XXX: It is not BLINKING at all! */ | |
534 attrib_add |= BACKGROUND_INTENSITY; | |
535 break; | |
536 case 7: | |
537 /* Reverse. */ | |
538 attrib_add |= COMMON_LVB_REVERSE_VIDEO; | |
539 break; | |
540 case 22: | |
541 /* No bold. */ | |
542 attrib_add &= ~FOREGROUND_INTENSITY; | |
543 attrib_rm |= FOREGROUND_INTENSITY; | |
544 break; | |
545 case 24: | |
546 /* No underline. */ | |
547 attrib_add &= ~COMMON_LVB_UNDERSCORE; | |
548 attrib_rm |= COMMON_LVB_UNDERSCORE; | |
549 break; | |
550 case 25: | |
551 /* No blink. */ | |
552 /* XXX: It is not BLINKING at all! */ | |
553 attrib_add &= ~BACKGROUND_INTENSITY; | |
554 attrib_rm |= BACKGROUND_INTENSITY; | |
555 break; | |
556 case 27: | |
557 /* No reverse. */ | |
558 attrib_add &= ~COMMON_LVB_REVERSE_VIDEO; | |
559 attrib_rm |= COMMON_LVB_REVERSE_VIDEO; | |
560 break; | |
561 case 30: | |
562 case 31: | |
563 case 32: | |
564 case 33: | |
565 case 34: | |
566 case 35: | |
567 case 36: | |
568 case 37: | |
569 /* Foreground color. */ | |
570 attrib_add &= ~(FOREGROUND_RED | FOREGROUND_GREEN | |
571 | FOREGROUND_BLUE); | |
572 n1 -= 30; | |
573 if (n1 & 1) | |
574 attrib_add |= FOREGROUND_RED; | |
575 if (n1 & 2) | |
576 attrib_add |= FOREGROUND_GREEN; | |
577 if (n1 & 4) | |
578 attrib_add |= FOREGROUND_BLUE; | |
579 attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN | |
580 | FOREGROUND_BLUE); | |
581 break; | |
582 case 38: | |
583 /* Reserved for extended foreground color. | |
584 Don't know how to handle parameters remaining. | |
585 Bail out. */ | |
586 goto sgr_set_it; | |
587 case 39: | |
588 /* Reset foreground color. */ | |
589 /* Set to grey. */ | |
590 attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN | |
591 | FOREGROUND_BLUE); | |
592 attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN | |
593 | FOREGROUND_BLUE); | |
594 break; | |
595 case 40: | |
596 case 41: | |
597 case 42: | |
598 case 43: | |
599 case 44: | |
600 case 45: | |
601 case 46: | |
602 case 47: | |
603 /* Background color. */ | |
604 attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN | |
605 | BACKGROUND_BLUE); | |
606 n1 -= 40; | |
607 if (n1 & 1) | |
608 attrib_add |= BACKGROUND_RED; | |
609 if (n1 & 2) | |
610 attrib_add |= BACKGROUND_GREEN; | |
611 if (n1 & 4) | |
612 attrib_add |= BACKGROUND_BLUE; | |
613 attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN | |
614 | BACKGROUND_BLUE); | |
615 break; | |
616 case 48: | |
617 /* Reserved for extended background color. | |
618 Don't know how to handle parameters remaining. | |
619 Bail out. */ | |
620 goto sgr_set_it; | |
621 case 49: | |
622 /* Reset background color. */ | |
623 /* Set to black. */ | |
624 attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN | |
625 | BACKGROUND_BLUE); | |
626 attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN | |
627 | BACKGROUND_BLUE); | |
628 break; | |
629 } | |
630 | |
631 /* Prepare the next parameter. */ | |
632 param = eptr + 1; | |
633 } | |
634 while (param != esc_term); | |
635 | |
636 sgr_set_it: | |
637 /* 0xFFFF removes everything. If it is not the case, | |
638 care must be taken to preserve old attributes. */ | |
639 if (attrib_rm != 0xFFFF && GetConsoleScreenBufferInfo (h, &sb)) | |
640 { | |
641 attrib_add |= sb.wAttributes & ~attrib_rm; | |
642 } | |
131 | 643 if (attrib_add & COMMON_LVB_REVERSE_VIDEO) |
644 { | |
645 /* COMMON_LVB_REVERSE_VIDEO is only effective for DBCS. | |
646 * Swap foreground and background colors by hand. | |
647 */ | |
648 attrib_add = (attrib_add & 0xFF00) | |
649 | ((attrib_add & 0x00F0) >> 4) | |
650 | ((attrib_add & 0x000F) << 4); | |
651 attrib_add &= ~COMMON_LVB_REVERSE_VIDEO; | |
652 } | |
111 | 653 SetConsoleTextAttribute (h, attrib_add); |
654 break; | |
655 } | |
656 } | |
657 | |
658 int | |
659 mingw_ansi_fputs (const char *str, FILE *fp) | |
660 { | |
661 const char *read = str; | |
662 HANDLE h; | |
663 DWORD mode; | |
664 int esc_code, prefix_len; | |
665 const char *esc_head, *esc_term; | |
666 | |
667 h = (HANDLE) _get_osfhandle (_fileno (fp)); | |
668 if (h == INVALID_HANDLE_VALUE) | |
669 return EOF; | |
670 | |
671 /* Don't mess up stdio functions with Windows APIs. */ | |
672 fflush (fp); | |
673 | |
674 if (GetConsoleMode (h, &mode)) | |
675 /* If it is a console, translate ANSI escape codes as needed. */ | |
676 for (;;) | |
677 { | |
678 if ((esc_code = find_esc_head (&prefix_len, &esc_head, read)) == 0) | |
679 { | |
680 /* Write all remaining characters, then exit. */ | |
681 write_all (h, read, strlen (read)); | |
682 break; | |
683 } | |
684 if (find_esc_terminator (&esc_term, esc_head) == 0) | |
685 /* Ignore incomplete escape sequences at the moment. | |
686 FIXME: The escape state shall be cached for further calls | |
687 to this function. */ | |
688 break; | |
689 write_all (h, read, esc_head - prefix_len - read); | |
690 eat_esc_sequence (h, esc_code, esc_head, esc_term); | |
691 read = esc_term + 1; | |
692 } | |
693 else | |
694 /* If it is not a console, write everything as-is. */ | |
695 write_all (h, read, strlen (read)); | |
696 | |
697 return 1; | |
698 } | |
699 | |
700 #endif /* __MINGW32__ */ | |
701 | |
702 static void pp_quoted_string (pretty_printer *, const char *, size_t = -1); | |
703 | |
704 /* Overwrite the given location/range within this text_info's rich_location. | |
705 For use e.g. when implementing "+" in client format decoders. */ | |
706 | |
707 void | |
131 | 708 text_info::set_location (unsigned int idx, location_t loc, |
709 enum range_display_kind range_display_kind) | |
111 | 710 { |
711 gcc_checking_assert (m_richloc); | |
131 | 712 m_richloc->set_range (idx, loc, range_display_kind); |
111 | 713 } |
714 | |
715 location_t | |
716 text_info::get_location (unsigned int index_of_location) const | |
717 { | |
718 gcc_checking_assert (m_richloc); | |
719 | |
720 if (index_of_location == 0) | |
721 return m_richloc->get_loc (); | |
722 else | |
723 return UNKNOWN_LOCATION; | |
724 } | |
725 | |
726 // Default construct an output buffer. | |
727 | |
728 output_buffer::output_buffer () | |
729 : formatted_obstack (), | |
730 chunk_obstack (), | |
731 obstack (&formatted_obstack), | |
732 cur_chunk_array (), | |
733 stream (stderr), | |
734 line_length (), | |
735 digit_buffer (), | |
736 flush_p (true) | |
737 { | |
738 obstack_init (&formatted_obstack); | |
739 obstack_init (&chunk_obstack); | |
740 } | |
741 | |
742 // Release resources owned by an output buffer at the end of lifetime. | |
743 | |
744 output_buffer::~output_buffer () | |
745 { | |
746 obstack_free (&chunk_obstack, NULL); | |
747 obstack_free (&formatted_obstack, NULL); | |
748 } | |
749 | |
0 | 750 |
751 /* Format an integer given by va_arg (ARG, type-specifier T) where | |
752 type-specifier is a precision modifier as indicated by PREC. F is | |
753 a string used to construct the appropriate format-specifier. */ | |
754 #define pp_integer_with_precision(PP, ARG, PREC, T, F) \ | |
755 do \ | |
756 switch (PREC) \ | |
757 { \ | |
758 case 0: \ | |
759 pp_scalar (PP, "%" F, va_arg (ARG, T)); \ | |
760 break; \ | |
761 \ | |
762 case 1: \ | |
763 pp_scalar (PP, "%l" F, va_arg (ARG, long T)); \ | |
764 break; \ | |
765 \ | |
766 case 2: \ | |
767 pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \ | |
768 break; \ | |
769 \ | |
770 default: \ | |
771 break; \ | |
772 } \ | |
773 while (0) | |
774 | |
775 | |
776 /* Subroutine of pp_set_maximum_length. Set up PRETTY-PRINTER's | |
777 internal maximum characters per line. */ | |
778 static void | |
779 pp_set_real_maximum_length (pretty_printer *pp) | |
780 { | |
781 /* If we're told not to wrap lines then do the obvious thing. In case | |
782 we'll emit prefix only once per message, it is appropriate | |
783 not to increase unnecessarily the line-length cut-off. */ | |
784 if (!pp_is_wrapping_line (pp) | |
785 || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_ONCE | |
786 || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_NEVER) | |
787 pp->maximum_length = pp_line_cutoff (pp); | |
788 else | |
789 { | |
790 int prefix_length = pp->prefix ? strlen (pp->prefix) : 0; | |
791 /* If the prefix is ridiculously too long, output at least | |
792 32 characters. */ | |
793 if (pp_line_cutoff (pp) - prefix_length < 32) | |
794 pp->maximum_length = pp_line_cutoff (pp) + 32; | |
795 else | |
796 pp->maximum_length = pp_line_cutoff (pp); | |
797 } | |
798 } | |
799 | |
800 /* Clear PRETTY-PRINTER's output state. */ | |
801 static inline void | |
802 pp_clear_state (pretty_printer *pp) | |
803 { | |
804 pp->emitted_prefix = false; | |
805 pp_indentation (pp) = 0; | |
806 } | |
807 | |
131 | 808 /* Print X to PP in decimal. */ |
809 template<unsigned int N, typename T> | |
810 void | |
811 pp_wide_integer (pretty_printer *pp, const poly_int_pod<N, T> &x) | |
812 { | |
813 if (x.is_constant ()) | |
814 pp_wide_integer (pp, x.coeffs[0]); | |
815 else | |
816 { | |
817 pp_left_bracket (pp); | |
818 for (unsigned int i = 0; i < N; ++i) | |
819 { | |
820 if (i != 0) | |
821 pp_comma (pp); | |
822 pp_wide_integer (pp, x.coeffs[i]); | |
823 } | |
824 pp_right_bracket (pp); | |
825 } | |
826 } | |
827 | |
828 template void pp_wide_integer (pretty_printer *, const poly_uint16_pod &); | |
829 template void pp_wide_integer (pretty_printer *, const poly_int64_pod &); | |
830 template void pp_wide_integer (pretty_printer *, const poly_uint64_pod &); | |
831 | |
0 | 832 /* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */ |
833 void | |
834 pp_write_text_to_stream (pretty_printer *pp) | |
835 { | |
836 const char *text = pp_formatted_text (pp); | |
111 | 837 #ifdef __MINGW32__ |
838 mingw_ansi_fputs (text, pp_buffer (pp)->stream); | |
839 #else | |
840 fputs (text, pp_buffer (pp)->stream); | |
841 #endif | |
842 pp_clear_output_area (pp); | |
843 } | |
844 | |
845 /* As pp_write_text_to_stream, but for GraphViz label output. | |
846 | |
847 Flush the formatted text of pretty-printer PP onto the attached stream. | |
848 Replace characters in PPF that have special meaning in a GraphViz .dot | |
849 file. | |
850 | |
851 This routine is not very fast, but it doesn't have to be as this is only | |
852 be used by routines dumping intermediate representations in graph form. */ | |
853 | |
854 void | |
855 pp_write_text_as_dot_label_to_stream (pretty_printer *pp, bool for_record) | |
856 { | |
857 const char *text = pp_formatted_text (pp); | |
858 const char *p = text; | |
859 FILE *fp = pp_buffer (pp)->stream; | |
860 | |
861 for (;*p; p++) | |
862 { | |
863 bool escape_char; | |
864 switch (*p) | |
865 { | |
866 /* Print newlines as a left-aligned newline. */ | |
867 case '\n': | |
868 fputs ("\\l", fp); | |
869 escape_char = true; | |
870 break; | |
871 | |
872 /* The following characters are only special for record-shape nodes. */ | |
873 case '|': | |
874 case '{': | |
875 case '}': | |
876 case '<': | |
877 case '>': | |
878 case ' ': | |
879 escape_char = for_record; | |
880 break; | |
881 | |
882 /* The following characters always have to be escaped | |
883 for use in labels. */ | |
884 case '\\': | |
885 /* There is a bug in some (f.i. 2.36.0) versions of graphiz | |
886 ( http://www.graphviz.org/mantisbt/view.php?id=2524 ) related to | |
887 backslash as last char in label. Let's avoid triggering it. */ | |
888 gcc_assert (*(p + 1) != '\0'); | |
889 /* Fall through. */ | |
890 case '"': | |
891 escape_char = true; | |
892 break; | |
893 | |
894 default: | |
895 escape_char = false; | |
896 break; | |
897 } | |
898 | |
899 if (escape_char) | |
900 fputc ('\\', fp); | |
901 | |
902 fputc (*p, fp); | |
903 } | |
904 | |
0 | 905 pp_clear_output_area (pp); |
906 } | |
907 | |
908 /* Wrap a text delimited by START and END into PRETTY-PRINTER. */ | |
909 static void | |
910 pp_wrap_text (pretty_printer *pp, const char *start, const char *end) | |
911 { | |
912 bool wrapping_line = pp_is_wrapping_line (pp); | |
913 | |
914 while (start != end) | |
915 { | |
916 /* Dump anything bordered by whitespaces. */ | |
917 { | |
918 const char *p = start; | |
919 while (p != end && !ISBLANK (*p) && *p != '\n') | |
920 ++p; | |
921 if (wrapping_line | |
922 && p - start >= pp_remaining_character_count_for_line (pp)) | |
923 pp_newline (pp); | |
924 pp_append_text (pp, start, p); | |
925 start = p; | |
926 } | |
927 | |
928 if (start != end && ISBLANK (*start)) | |
929 { | |
930 pp_space (pp); | |
931 ++start; | |
932 } | |
933 if (start != end && *start == '\n') | |
934 { | |
935 pp_newline (pp); | |
936 ++start; | |
937 } | |
938 } | |
939 } | |
940 | |
941 /* Same as pp_wrap_text but wrap text only when in line-wrapping mode. */ | |
942 static inline void | |
943 pp_maybe_wrap_text (pretty_printer *pp, const char *start, const char *end) | |
944 { | |
945 if (pp_is_wrapping_line (pp)) | |
946 pp_wrap_text (pp, start, end); | |
947 else | |
948 pp_append_text (pp, start, end); | |
949 } | |
950 | |
951 /* Append to the output area of PRETTY-PRINTER a string specified by its | |
952 STARTing character and LENGTH. */ | |
953 static inline void | |
954 pp_append_r (pretty_printer *pp, const char *start, int length) | |
955 { | |
111 | 956 output_buffer_append_r (pp_buffer (pp), start, length); |
0 | 957 } |
958 | |
959 /* Insert enough spaces into the output area of PRETTY-PRINTER to bring | |
960 the column position to the current indentation level, assuming that a | |
961 newline has just been written to the buffer. */ | |
962 void | |
111 | 963 pp_indent (pretty_printer *pp) |
0 | 964 { |
965 int n = pp_indentation (pp); | |
966 int i; | |
967 | |
968 for (i = 0; i < n; ++i) | |
969 pp_space (pp); | |
970 } | |
971 | |
972 /* The following format specifiers are recognized as being client independent: | |
973 %d, %i: (signed) integer in base ten. | |
974 %u: unsigned integer in base ten. | |
975 %o: unsigned integer in base eight. | |
976 %x: unsigned integer in base sixteen. | |
977 %ld, %li, %lo, %lu, %lx: long versions of the above. | |
978 %lld, %lli, %llo, %llu, %llx: long long versions. | |
979 %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions. | |
980 %c: character. | |
981 %s: string. | |
111 | 982 %p: pointer (printed in a host-dependent manner). |
983 %r: if pp_show_color(pp), switch to color identified by const char *. | |
984 %R: if pp_show_color(pp), reset color. | |
0 | 985 %m: strerror(text->err_no) - does not consume a value from args_ptr. |
986 %%: '%'. | |
987 %<: opening quote. | |
988 %>: closing quote. | |
989 %': apostrophe (should only be used in untranslated messages; | |
990 translations should use appropriate punctuation directly). | |
991 %.*s: a substring the length of which is specified by an argument | |
992 integer. | |
993 %Ns: likewise, but length specified as constant in the format string. | |
994 Flag 'q': quote formatted text (must come immediately after '%'). | |
111 | 995 %Z: Requires two arguments - array of int, and len. Prints elements |
996 of the array. | |
0 | 997 |
998 Arguments can be used sequentially, or through %N$ resp. *N$ | |
999 notation Nth argument after the format string. If %N$ / *N$ | |
1000 notation is used, it must be used for all arguments, except %m, %%, | |
1001 %<, %> and %', which may not have a number, as they do not consume | |
1002 an argument. When %M$.*N$s is used, M must be N + 1. (This may | |
1003 also be written %M$.*s, provided N is not otherwise used.) The | |
1004 format string must have conversion specifiers with argument numbers | |
1005 1 up to highest argument; each argument may only be used once. | |
1006 A format string can have at most 30 arguments. */ | |
1007 | |
1008 /* Formatting phases 1 and 2: render TEXT->format_spec plus | |
111 | 1009 TEXT->args_ptr into a series of chunks in pp_buffer (PP)->args[]. |
1010 Phase 3 is in pp_output_formatted_text. */ | |
0 | 1011 |
1012 void | |
111 | 1013 pp_format (pretty_printer *pp, text_info *text) |
0 | 1014 { |
111 | 1015 output_buffer *buffer = pp_buffer (pp); |
0 | 1016 const char *p; |
1017 const char **args; | |
1018 struct chunk_info *new_chunk_array; | |
1019 | |
1020 unsigned int curarg = 0, chunk = 0, argno; | |
1021 pp_wrapping_mode_t old_wrapping_mode; | |
1022 bool any_unnumbered = false, any_numbered = false; | |
1023 const char **formatters[PP_NL_ARGMAX]; | |
1024 | |
1025 /* Allocate a new chunk structure. */ | |
1026 new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info); | |
1027 new_chunk_array->prev = buffer->cur_chunk_array; | |
1028 buffer->cur_chunk_array = new_chunk_array; | |
1029 args = new_chunk_array->args; | |
1030 | |
1031 /* Formatting phase 1: split up TEXT->format_spec into chunks in | |
111 | 1032 pp_buffer (PP)->args[]. Even-numbered chunks are to be output |
0 | 1033 verbatim, odd-numbered chunks are format specifiers. |
1034 %m, %%, %<, %>, and %' are replaced with the appropriate text at | |
1035 this point. */ | |
1036 | |
1037 memset (formatters, 0, sizeof formatters); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1038 |
0 | 1039 for (p = text->format_spec; *p; ) |
1040 { | |
1041 while (*p != '\0' && *p != '%') | |
1042 { | |
1043 obstack_1grow (&buffer->chunk_obstack, *p); | |
1044 p++; | |
1045 } | |
1046 | |
1047 if (*p == '\0') | |
1048 break; | |
1049 | |
1050 switch (*++p) | |
1051 { | |
1052 case '\0': | |
1053 gcc_unreachable (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1054 |
0 | 1055 case '%': |
1056 obstack_1grow (&buffer->chunk_obstack, '%'); | |
1057 p++; | |
1058 continue; | |
1059 | |
1060 case '<': | |
111 | 1061 { |
1062 obstack_grow (&buffer->chunk_obstack, | |
1063 open_quote, strlen (open_quote)); | |
1064 const char *colorstr | |
1065 = colorize_start (pp_show_color (pp), "quote"); | |
1066 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr)); | |
1067 p++; | |
1068 continue; | |
1069 } | |
0 | 1070 |
1071 case '>': | |
111 | 1072 { |
1073 const char *colorstr = colorize_stop (pp_show_color (pp)); | |
1074 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr)); | |
1075 } | |
1076 /* FALLTHRU */ | |
0 | 1077 case '\'': |
1078 obstack_grow (&buffer->chunk_obstack, | |
1079 close_quote, strlen (close_quote)); | |
1080 p++; | |
1081 continue; | |
1082 | |
111 | 1083 case 'R': |
1084 { | |
1085 const char *colorstr = colorize_stop (pp_show_color (pp)); | |
1086 obstack_grow (&buffer->chunk_obstack, colorstr, | |
1087 strlen (colorstr)); | |
1088 p++; | |
1089 continue; | |
1090 } | |
1091 | |
0 | 1092 case 'm': |
1093 { | |
1094 const char *errstr = xstrerror (text->err_no); | |
1095 obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr)); | |
1096 } | |
1097 p++; | |
1098 continue; | |
1099 | |
1100 default: | |
1101 /* Handled in phase 2. Terminate the plain chunk here. */ | |
1102 obstack_1grow (&buffer->chunk_obstack, '\0'); | |
1103 gcc_assert (chunk < PP_NL_ARGMAX * 2); | |
1104 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *); | |
1105 break; | |
1106 } | |
1107 | |
1108 if (ISDIGIT (*p)) | |
1109 { | |
1110 char *end; | |
1111 argno = strtoul (p, &end, 10) - 1; | |
1112 p = end; | |
1113 gcc_assert (*p == '$'); | |
1114 p++; | |
1115 | |
1116 any_numbered = true; | |
1117 gcc_assert (!any_unnumbered); | |
1118 } | |
1119 else | |
1120 { | |
1121 argno = curarg++; | |
1122 any_unnumbered = true; | |
1123 gcc_assert (!any_numbered); | |
1124 } | |
1125 gcc_assert (argno < PP_NL_ARGMAX); | |
1126 gcc_assert (!formatters[argno]); | |
1127 formatters[argno] = &args[chunk]; | |
1128 do | |
1129 { | |
1130 obstack_1grow (&buffer->chunk_obstack, *p); | |
1131 p++; | |
1132 } | |
1133 while (strchr ("qwl+#", p[-1])); | |
1134 | |
1135 if (p[-1] == '.') | |
1136 { | |
1137 /* We handle '%.Ns' and '%.*s' or '%M$.*N$s' | |
1138 (where M == N + 1). */ | |
1139 if (ISDIGIT (*p)) | |
1140 { | |
1141 do | |
1142 { | |
1143 obstack_1grow (&buffer->chunk_obstack, *p); | |
1144 p++; | |
1145 } | |
1146 while (ISDIGIT (p[-1])); | |
1147 gcc_assert (p[-1] == 's'); | |
1148 } | |
1149 else | |
1150 { | |
1151 gcc_assert (*p == '*'); | |
1152 obstack_1grow (&buffer->chunk_obstack, '*'); | |
1153 p++; | |
1154 | |
1155 if (ISDIGIT (*p)) | |
1156 { | |
1157 char *end; | |
1158 unsigned int argno2 = strtoul (p, &end, 10) - 1; | |
1159 p = end; | |
1160 gcc_assert (argno2 == argno - 1); | |
1161 gcc_assert (!any_unnumbered); | |
1162 gcc_assert (*p == '$'); | |
1163 | |
1164 p++; | |
1165 formatters[argno2] = formatters[argno]; | |
1166 } | |
1167 else | |
1168 { | |
1169 gcc_assert (!any_numbered); | |
1170 formatters[argno+1] = formatters[argno]; | |
1171 curarg++; | |
1172 } | |
1173 gcc_assert (*p == 's'); | |
1174 obstack_1grow (&buffer->chunk_obstack, 's'); | |
1175 p++; | |
1176 } | |
1177 } | |
1178 if (*p == '\0') | |
1179 break; | |
1180 | |
1181 obstack_1grow (&buffer->chunk_obstack, '\0'); | |
1182 gcc_assert (chunk < PP_NL_ARGMAX * 2); | |
1183 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *); | |
1184 } | |
1185 | |
1186 obstack_1grow (&buffer->chunk_obstack, '\0'); | |
1187 gcc_assert (chunk < PP_NL_ARGMAX * 2); | |
1188 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *); | |
1189 args[chunk] = 0; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1190 |
0 | 1191 /* Set output to the argument obstack, and switch line-wrapping and |
1192 prefixing off. */ | |
1193 buffer->obstack = &buffer->chunk_obstack; | |
1194 old_wrapping_mode = pp_set_verbatim_wrapping (pp); | |
1195 | |
1196 /* Second phase. Replace each formatter with the formatted text it | |
1197 corresponds to. */ | |
1198 | |
1199 for (argno = 0; formatters[argno]; argno++) | |
1200 { | |
1201 int precision = 0; | |
1202 bool wide = false; | |
1203 bool plus = false; | |
1204 bool hash = false; | |
1205 bool quote = false; | |
1206 | |
1207 /* We do not attempt to enforce any ordering on the modifier | |
1208 characters. */ | |
1209 | |
1210 for (p = *formatters[argno];; p++) | |
1211 { | |
1212 switch (*p) | |
1213 { | |
1214 case 'q': | |
1215 gcc_assert (!quote); | |
1216 quote = true; | |
1217 continue; | |
1218 | |
1219 case '+': | |
1220 gcc_assert (!plus); | |
1221 plus = true; | |
1222 continue; | |
1223 | |
1224 case '#': | |
1225 gcc_assert (!hash); | |
1226 hash = true; | |
1227 continue; | |
1228 | |
1229 case 'w': | |
1230 gcc_assert (!wide); | |
1231 wide = true; | |
1232 continue; | |
1233 | |
1234 case 'l': | |
1235 /* We don't support precision beyond that of "long long". */ | |
1236 gcc_assert (precision < 2); | |
1237 precision++; | |
1238 continue; | |
1239 } | |
1240 break; | |
1241 } | |
1242 | |
1243 gcc_assert (!wide || precision == 0); | |
1244 | |
1245 if (quote) | |
131 | 1246 pp_begin_quote (pp, pp_show_color (pp)); |
0 | 1247 |
1248 switch (*p) | |
1249 { | |
111 | 1250 case 'r': |
1251 pp_string (pp, colorize_start (pp_show_color (pp), | |
1252 va_arg (*text->args_ptr, | |
1253 const char *))); | |
1254 break; | |
1255 | |
0 | 1256 case 'c': |
111 | 1257 { |
1258 /* When quoting, print alphanumeric, punctuation, and the space | |
1259 character unchanged, and all others in hexadecimal with the | |
1260 "\x" prefix. Otherwise print them all unchanged. */ | |
1261 int chr = va_arg (*text->args_ptr, int); | |
1262 if (ISPRINT (chr) || !quote) | |
1263 pp_character (pp, chr); | |
1264 else | |
1265 { | |
1266 const char str [2] = { chr, '\0' }; | |
1267 pp_quoted_string (pp, str, 1); | |
1268 } | |
1269 break; | |
1270 } | |
0 | 1271 |
1272 case 'd': | |
1273 case 'i': | |
1274 if (wide) | |
1275 pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT)); | |
1276 else | |
1277 pp_integer_with_precision | |
1278 (pp, *text->args_ptr, precision, int, "d"); | |
1279 break; | |
1280 | |
1281 case 'o': | |
1282 if (wide) | |
1283 pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o", | |
1284 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT)); | |
1285 else | |
1286 pp_integer_with_precision | |
1287 (pp, *text->args_ptr, precision, unsigned, "o"); | |
1288 break; | |
1289 | |
1290 case 's': | |
111 | 1291 if (quote) |
1292 pp_quoted_string (pp, va_arg (*text->args_ptr, const char *)); | |
1293 else | |
1294 pp_string (pp, va_arg (*text->args_ptr, const char *)); | |
0 | 1295 break; |
1296 | |
1297 case 'p': | |
1298 pp_pointer (pp, va_arg (*text->args_ptr, void *)); | |
1299 break; | |
1300 | |
1301 case 'u': | |
1302 if (wide) | |
1303 pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED, | |
1304 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT)); | |
1305 else | |
1306 pp_integer_with_precision | |
1307 (pp, *text->args_ptr, precision, unsigned, "u"); | |
1308 break; | |
1309 | |
111 | 1310 case 'Z': |
1311 { | |
1312 int *v = va_arg (*text->args_ptr, int *); | |
1313 unsigned len = va_arg (*text->args_ptr, unsigned); | |
1314 | |
1315 for (unsigned i = 0; i < len; ++i) | |
1316 { | |
1317 pp_scalar (pp, "%i", v[i]); | |
1318 if (i < len - 1) | |
1319 { | |
1320 pp_comma (pp); | |
1321 pp_space (pp); | |
1322 } | |
1323 } | |
1324 break; | |
1325 } | |
1326 | |
0 | 1327 case 'x': |
1328 if (wide) | |
1329 pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX, | |
1330 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT)); | |
1331 else | |
1332 pp_integer_with_precision | |
1333 (pp, *text->args_ptr, precision, unsigned, "x"); | |
1334 break; | |
1335 | |
1336 case '.': | |
1337 { | |
1338 int n; | |
1339 const char *s; | |
1340 | |
1341 /* We handle '%.Ns' and '%.*s' or '%M$.*N$s' | |
1342 (where M == N + 1). The format string should be verified | |
1343 already from the first phase. */ | |
1344 p++; | |
1345 if (ISDIGIT (*p)) | |
1346 { | |
1347 char *end; | |
1348 n = strtoul (p, &end, 10); | |
1349 p = end; | |
1350 gcc_assert (*p == 's'); | |
1351 } | |
1352 else | |
1353 { | |
1354 gcc_assert (*p == '*'); | |
1355 p++; | |
1356 gcc_assert (*p == 's'); | |
1357 n = va_arg (*text->args_ptr, int); | |
1358 | |
1359 /* This consumes a second entry in the formatters array. */ | |
1360 gcc_assert (formatters[argno] == formatters[argno+1]); | |
1361 argno++; | |
1362 } | |
1363 | |
1364 s = va_arg (*text->args_ptr, const char *); | |
111 | 1365 |
1366 /* Append the lesser of precision and strlen (s) characters | |
1367 from the array (which need not be a nul-terminated string). | |
1368 Negative precision is treated as if it were omitted. */ | |
1369 size_t len = n < 0 ? strlen (s) : strnlen (s, n); | |
1370 | |
1371 pp_append_text (pp, s, s + len); | |
0 | 1372 } |
1373 break; | |
1374 | |
1375 default: | |
1376 { | |
1377 bool ok; | |
1378 | |
131 | 1379 /* Call the format decoder. |
1380 Pass the address of "quote" so that format decoders can | |
1381 potentially disable printing of the closing quote | |
1382 (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family | |
1383 of frontends). */ | |
0 | 1384 gcc_assert (pp_format_decoder (pp)); |
1385 ok = pp_format_decoder (pp) (pp, text, p, | |
131 | 1386 precision, wide, plus, hash, "e, |
111 | 1387 formatters[argno]); |
0 | 1388 gcc_assert (ok); |
1389 } | |
1390 } | |
1391 | |
1392 if (quote) | |
131 | 1393 pp_end_quote (pp, pp_show_color (pp)); |
0 | 1394 |
1395 obstack_1grow (&buffer->chunk_obstack, '\0'); | |
1396 *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *); | |
1397 } | |
1398 | |
111 | 1399 if (CHECKING_P) |
1400 for (; argno < PP_NL_ARGMAX; argno++) | |
1401 gcc_assert (!formatters[argno]); | |
1402 | |
1403 /* If the client supplied a postprocessing object, call its "handle" | |
1404 hook here. */ | |
1405 if (pp->m_format_postprocessor) | |
1406 pp->m_format_postprocessor->handle (pp); | |
0 | 1407 |
1408 /* Revert to normal obstack and wrapping mode. */ | |
1409 buffer->obstack = &buffer->formatted_obstack; | |
1410 buffer->line_length = 0; | |
1411 pp_wrapping_mode (pp) = old_wrapping_mode; | |
1412 pp_clear_state (pp); | |
1413 } | |
1414 | |
1415 /* Format of a message pointed to by TEXT. */ | |
1416 void | |
111 | 1417 pp_output_formatted_text (pretty_printer *pp) |
0 | 1418 { |
1419 unsigned int chunk; | |
1420 output_buffer *buffer = pp_buffer (pp); | |
1421 struct chunk_info *chunk_array = buffer->cur_chunk_array; | |
1422 const char **args = chunk_array->args; | |
1423 | |
1424 gcc_assert (buffer->obstack == &buffer->formatted_obstack); | |
1425 gcc_assert (buffer->line_length == 0); | |
1426 | |
111 | 1427 /* This is a third phase, first 2 phases done in pp_format_args. |
0 | 1428 Now we actually print it. */ |
1429 for (chunk = 0; args[chunk]; chunk++) | |
1430 pp_string (pp, args[chunk]); | |
1431 | |
1432 /* Deallocate the chunk structure and everything after it (i.e. the | |
1433 associated series of formatted strings). */ | |
1434 buffer->cur_chunk_array = chunk_array->prev; | |
1435 obstack_free (&buffer->chunk_obstack, chunk_array); | |
1436 } | |
1437 | |
1438 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate | |
1439 settings needed by BUFFER for a verbatim formatting. */ | |
1440 void | |
111 | 1441 pp_format_verbatim (pretty_printer *pp, text_info *text) |
0 | 1442 { |
1443 /* Set verbatim mode. */ | |
1444 pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp); | |
1445 | |
1446 /* Do the actual formatting. */ | |
1447 pp_format (pp, text); | |
1448 pp_output_formatted_text (pp); | |
1449 | |
1450 /* Restore previous settings. */ | |
1451 pp_wrapping_mode (pp) = oldmode; | |
1452 } | |
1453 | |
111 | 1454 /* Flush the content of BUFFER onto the attached stream. This |
1455 function does nothing unless pp->output_buffer->flush_p. */ | |
0 | 1456 void |
111 | 1457 pp_flush (pretty_printer *pp) |
0 | 1458 { |
111 | 1459 pp_clear_state (pp); |
1460 if (!pp->buffer->flush_p) | |
1461 return; | |
0 | 1462 pp_write_text_to_stream (pp); |
111 | 1463 fflush (pp_buffer (pp)->stream); |
1464 } | |
1465 | |
1466 /* Flush the content of BUFFER onto the attached stream independently | |
1467 of the value of pp->output_buffer->flush_p. */ | |
1468 void | |
1469 pp_really_flush (pretty_printer *pp) | |
1470 { | |
0 | 1471 pp_clear_state (pp); |
111 | 1472 pp_write_text_to_stream (pp); |
1473 fflush (pp_buffer (pp)->stream); | |
0 | 1474 } |
1475 | |
1476 /* Sets the number of maximum characters per line PRETTY-PRINTER can | |
1477 output in line-wrapping mode. A LENGTH value 0 suppresses | |
1478 line-wrapping. */ | |
1479 void | |
111 | 1480 pp_set_line_maximum_length (pretty_printer *pp, int length) |
0 | 1481 { |
1482 pp_line_cutoff (pp) = length; | |
1483 pp_set_real_maximum_length (pp); | |
1484 } | |
1485 | |
1486 /* Clear PRETTY-PRINTER output area text info. */ | |
1487 void | |
111 | 1488 pp_clear_output_area (pretty_printer *pp) |
0 | 1489 { |
111 | 1490 obstack_free (pp_buffer (pp)->obstack, |
1491 obstack_base (pp_buffer (pp)->obstack)); | |
1492 pp_buffer (pp)->line_length = 0; | |
0 | 1493 } |
1494 | |
131 | 1495 /* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which |
1496 will eventually be free-ed. */ | |
1497 | |
0 | 1498 void |
131 | 1499 pp_set_prefix (pretty_printer *pp, char *prefix) |
0 | 1500 { |
131 | 1501 free (pp->prefix); |
0 | 1502 pp->prefix = prefix; |
1503 pp_set_real_maximum_length (pp); | |
1504 pp->emitted_prefix = false; | |
1505 pp_indentation (pp) = 0; | |
1506 } | |
1507 | |
131 | 1508 /* Take ownership of PP's prefix, setting it to NULL. |
1509 This allows clients to save, overide, and then restore an existing | |
1510 prefix, without it being free-ed. */ | |
1511 | |
1512 char * | |
1513 pp_take_prefix (pretty_printer *pp) | |
1514 { | |
1515 char *result = pp->prefix; | |
1516 pp->prefix = NULL; | |
1517 return result; | |
1518 } | |
1519 | |
0 | 1520 /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */ |
1521 void | |
111 | 1522 pp_destroy_prefix (pretty_printer *pp) |
0 | 1523 { |
1524 if (pp->prefix != NULL) | |
1525 { | |
131 | 1526 free (pp->prefix); |
0 | 1527 pp->prefix = NULL; |
1528 } | |
1529 } | |
1530 | |
1531 /* Write out PRETTY-PRINTER's prefix. */ | |
1532 void | |
111 | 1533 pp_emit_prefix (pretty_printer *pp) |
0 | 1534 { |
1535 if (pp->prefix != NULL) | |
1536 { | |
1537 switch (pp_prefixing_rule (pp)) | |
1538 { | |
1539 default: | |
1540 case DIAGNOSTICS_SHOW_PREFIX_NEVER: | |
1541 break; | |
1542 | |
1543 case DIAGNOSTICS_SHOW_PREFIX_ONCE: | |
1544 if (pp->emitted_prefix) | |
1545 { | |
111 | 1546 pp_indent (pp); |
0 | 1547 break; |
1548 } | |
1549 pp_indentation (pp) += 3; | |
1550 /* Fall through. */ | |
1551 | |
1552 case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE: | |
1553 { | |
1554 int prefix_length = strlen (pp->prefix); | |
1555 pp_append_r (pp, pp->prefix, prefix_length); | |
1556 pp->emitted_prefix = true; | |
1557 } | |
1558 break; | |
1559 } | |
1560 } | |
1561 } | |
1562 | |
131 | 1563 /* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line. */ |
111 | 1564 |
131 | 1565 pretty_printer::pretty_printer (int maximum_length) |
111 | 1566 : buffer (new (XCNEW (output_buffer)) output_buffer ()), |
1567 prefix (), | |
1568 padding (pp_none), | |
1569 maximum_length (), | |
1570 indent_skip (), | |
1571 wrapping (), | |
1572 format_decoder (), | |
1573 m_format_postprocessor (NULL), | |
1574 emitted_prefix (), | |
1575 need_newline (), | |
1576 translate_identifiers (true), | |
1577 show_color () | |
0 | 1578 { |
131 | 1579 pp_line_cutoff (this) = maximum_length; |
111 | 1580 /* By default, we emit prefixes once per message. */ |
1581 pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE; | |
131 | 1582 pp_set_prefix (this, NULL); |
111 | 1583 } |
1584 | |
1585 pretty_printer::~pretty_printer () | |
1586 { | |
1587 if (m_format_postprocessor) | |
1588 delete m_format_postprocessor; | |
1589 buffer->~output_buffer (); | |
1590 XDELETE (buffer); | |
131 | 1591 free (prefix); |
0 | 1592 } |
1593 | |
1594 /* Append a string delimited by START and END to the output area of | |
1595 PRETTY-PRINTER. No line wrapping is done. However, if beginning a | |
1596 new line then emit PRETTY-PRINTER's prefix and skip any leading | |
1597 whitespace if appropriate. The caller must ensure that it is | |
1598 safe to do so. */ | |
1599 void | |
111 | 1600 pp_append_text (pretty_printer *pp, const char *start, const char *end) |
0 | 1601 { |
1602 /* Emit prefix and skip whitespace if we're starting a new line. */ | |
111 | 1603 if (pp_buffer (pp)->line_length == 0) |
0 | 1604 { |
1605 pp_emit_prefix (pp); | |
1606 if (pp_is_wrapping_line (pp)) | |
1607 while (start != end && *start == ' ') | |
1608 ++start; | |
1609 } | |
1610 pp_append_r (pp, start, end - start); | |
1611 } | |
1612 | |
1613 /* Finishes constructing a NULL-terminated character string representing | |
1614 the PRETTY-PRINTED text. */ | |
1615 const char * | |
111 | 1616 pp_formatted_text (pretty_printer *pp) |
0 | 1617 { |
111 | 1618 return output_buffer_formatted_text (pp_buffer (pp)); |
0 | 1619 } |
1620 | |
1621 /* Return a pointer to the last character emitted in PRETTY-PRINTER's | |
1622 output area. A NULL pointer means no character available. */ | |
1623 const char * | |
111 | 1624 pp_last_position_in_text (const pretty_printer *pp) |
0 | 1625 { |
111 | 1626 return output_buffer_last_position_in_text (pp_buffer (pp)); |
0 | 1627 } |
1628 | |
1629 /* Return the amount of characters PRETTY-PRINTER can accept to | |
1630 make a full line. Meaningful only in line-wrapping mode. */ | |
1631 int | |
111 | 1632 pp_remaining_character_count_for_line (pretty_printer *pp) |
0 | 1633 { |
111 | 1634 return pp->maximum_length - pp_buffer (pp)->line_length; |
0 | 1635 } |
1636 | |
1637 | |
1638 /* Format a message into BUFFER a la printf. */ | |
1639 void | |
1640 pp_printf (pretty_printer *pp, const char *msg, ...) | |
1641 { | |
1642 text_info text; | |
1643 va_list ap; | |
1644 | |
1645 va_start (ap, msg); | |
1646 text.err_no = errno; | |
1647 text.args_ptr = ≈ | |
1648 text.format_spec = msg; | |
1649 pp_format (pp, &text); | |
1650 pp_output_formatted_text (pp); | |
1651 va_end (ap); | |
1652 } | |
1653 | |
1654 | |
1655 /* Output MESSAGE verbatim into BUFFER. */ | |
1656 void | |
1657 pp_verbatim (pretty_printer *pp, const char *msg, ...) | |
1658 { | |
1659 text_info text; | |
1660 va_list ap; | |
1661 | |
1662 va_start (ap, msg); | |
1663 text.err_no = errno; | |
1664 text.args_ptr = ≈ | |
1665 text.format_spec = msg; | |
1666 pp_format_verbatim (pp, &text); | |
1667 va_end (ap); | |
1668 } | |
1669 | |
1670 | |
1671 | |
1672 /* Have PRETTY-PRINTER start a new line. */ | |
1673 void | |
111 | 1674 pp_newline (pretty_printer *pp) |
0 | 1675 { |
111 | 1676 obstack_1grow (pp_buffer (pp)->obstack, '\n'); |
1677 pp_needs_newline (pp) = false; | |
1678 pp_buffer (pp)->line_length = 0; | |
0 | 1679 } |
1680 | |
1681 /* Have PRETTY-PRINTER add a CHARACTER. */ | |
1682 void | |
111 | 1683 pp_character (pretty_printer *pp, int c) |
0 | 1684 { |
1685 if (pp_is_wrapping_line (pp) | |
1686 && pp_remaining_character_count_for_line (pp) <= 0) | |
1687 { | |
1688 pp_newline (pp); | |
1689 if (ISSPACE (c)) | |
1690 return; | |
1691 } | |
111 | 1692 obstack_1grow (pp_buffer (pp)->obstack, c); |
1693 ++pp_buffer (pp)->line_length; | |
0 | 1694 } |
1695 | |
1696 /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may | |
1697 be line-wrapped if in appropriate mode. */ | |
1698 void | |
111 | 1699 pp_string (pretty_printer *pp, const char *str) |
1700 { | |
1701 gcc_checking_assert (str); | |
1702 pp_maybe_wrap_text (pp, str, str + strlen (str)); | |
1703 } | |
1704 | |
1705 /* Append the leading N characters of STRING to the output area of | |
1706 PRETTY-PRINTER, quoting in hexadecimal non-printable characters. | |
1707 Setting N = -1 is as if N were set to strlen (STRING). The STRING | |
1708 may be line-wrapped if in appropriate mode. */ | |
1709 static void | |
1710 pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */) | |
0 | 1711 { |
111 | 1712 gcc_checking_assert (str); |
1713 | |
1714 const char *last = str; | |
1715 const char *ps; | |
1716 | |
1717 /* Compute the length if not specified. */ | |
1718 if (n == (size_t) -1) | |
1719 n = strlen (str); | |
1720 | |
1721 for (ps = str; n; ++ps, --n) | |
1722 { | |
1723 if (ISPRINT (*ps)) | |
1724 continue; | |
1725 | |
1726 if (last < ps) | |
1727 pp_maybe_wrap_text (pp, last, ps - 1); | |
1728 | |
1729 /* Append the hexadecimal value of the character. Allocate a buffer | |
1730 that's large enough for a 32-bit char plus the hex prefix. */ | |
1731 char buf [11]; | |
1732 int n = sprintf (buf, "\\x%02x", (unsigned char)*ps); | |
1733 pp_maybe_wrap_text (pp, buf, buf + n); | |
1734 last = ps + 1; | |
1735 } | |
1736 | |
1737 pp_maybe_wrap_text (pp, last, ps); | |
0 | 1738 } |
1739 | |
1740 /* Maybe print out a whitespace if needed. */ | |
1741 | |
1742 void | |
111 | 1743 pp_maybe_space (pretty_printer *pp) |
0 | 1744 { |
111 | 1745 if (pp->padding != pp_none) |
0 | 1746 { |
1747 pp_space (pp); | |
111 | 1748 pp->padding = pp_none; |
0 | 1749 } |
1750 } | |
111 | 1751 |
1752 // Add a newline to the pretty printer PP and flush formatted text. | |
1753 | |
1754 void | |
1755 pp_newline_and_flush (pretty_printer *pp) | |
1756 { | |
1757 pp_newline (pp); | |
1758 pp_flush (pp); | |
1759 pp_needs_newline (pp) = false; | |
1760 } | |
1761 | |
1762 // Add a newline to the pretty printer PP, followed by indentation. | |
1763 | |
1764 void | |
1765 pp_newline_and_indent (pretty_printer *pp, int n) | |
1766 { | |
1767 pp_indentation (pp) += n; | |
1768 pp_newline (pp); | |
1769 pp_indent (pp); | |
1770 pp_needs_newline (pp) = false; | |
1771 } | |
1772 | |
1773 // Add separator C, followed by a single whitespace. | |
1774 | |
1775 void | |
1776 pp_separate_with (pretty_printer *pp, char c) | |
1777 { | |
1778 pp_character (pp, c); | |
1779 pp_space (pp); | |
1780 } | |
1781 | |
131 | 1782 /* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing |
1783 using the "quote" color. */ | |
1784 | |
1785 void | |
1786 pp_begin_quote (pretty_printer *pp, bool show_color) | |
1787 { | |
1788 pp_string (pp, open_quote); | |
1789 pp_string (pp, colorize_start (show_color, "quote")); | |
1790 } | |
1791 | |
1792 /* If SHOW_COLOR is true, stop colorizing. | |
1793 Add a localized close quote. */ | |
1794 | |
1795 void | |
1796 pp_end_quote (pretty_printer *pp, bool show_color) | |
1797 { | |
1798 pp_string (pp, colorize_stop (show_color)); | |
1799 pp_string (pp, close_quote); | |
1800 } | |
1801 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1802 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1803 /* The string starting at P has LEN (at least 1) bytes left; if they |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1804 start with a valid UTF-8 sequence, return the length of that |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1805 sequence and set *VALUE to the value of that sequence, and |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1806 otherwise return 0 and set *VALUE to (unsigned int) -1. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1807 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1808 static int |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1809 decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1810 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1811 unsigned int t = *p; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1812 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1813 if (len == 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1814 abort (); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1815 if (t & 0x80) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1816 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1817 size_t utf8_len = 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1818 unsigned int ch; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1819 size_t i; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1820 for (t = *p; t & 0x80; t <<= 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1821 utf8_len++; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1822 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1823 if (utf8_len > len || utf8_len < 2 || utf8_len > 6) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1824 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1825 *value = (unsigned int) -1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1826 return 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1827 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1828 ch = *p & ((1 << (7 - utf8_len)) - 1); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1829 for (i = 1; i < utf8_len; i++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1830 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1831 unsigned int u = p[i]; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1832 if ((u & 0xC0) != 0x80) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1833 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1834 *value = (unsigned int) -1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1835 return 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1836 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1837 ch = (ch << 6) | (u & 0x3F); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1838 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1839 if ( (ch <= 0x7F && utf8_len > 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1840 || (ch <= 0x7FF && utf8_len > 2) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1841 || (ch <= 0xFFFF && utf8_len > 3) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1842 || (ch <= 0x1FFFFF && utf8_len > 4) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1843 || (ch <= 0x3FFFFFF && utf8_len > 5) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1844 || (ch >= 0xD800 && ch <= 0xDFFF)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1845 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1846 *value = (unsigned int) -1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1847 return 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1848 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1849 *value = ch; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1850 return utf8_len; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1851 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1852 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1853 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1854 *value = t; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1855 return 1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1856 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1857 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1858 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1859 /* Allocator for identifier_to_locale and corresponding function to |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1860 free memory. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1861 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1862 void *(*identifier_to_locale_alloc) (size_t) = xmalloc; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1863 void (*identifier_to_locale_free) (void *) = free; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1864 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1865 /* Given IDENT, an identifier in the internal encoding, return a |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1866 version of IDENT suitable for diagnostics in the locale character |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1867 set: either IDENT itself, or a string, allocated using |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1868 identifier_to_locale_alloc, converted to the locale character set |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1869 and using escape sequences if not representable in the locale |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1870 character set or containing control characters or invalid byte |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1871 sequences. Existing backslashes in IDENT are not doubled, so the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1872 result may not uniquely specify the contents of an arbitrary byte |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1873 sequence identifier. */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1874 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1875 const char * |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1876 identifier_to_locale (const char *ident) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1877 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1878 const unsigned char *uid = (const unsigned char *) ident; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1879 size_t idlen = strlen (ident); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1880 bool valid_printable_utf8 = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1881 bool all_ascii = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1882 size_t i; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1883 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1884 for (i = 0; i < idlen;) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1885 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1886 unsigned int c; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1887 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1888 if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1889 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1890 valid_printable_utf8 = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1891 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1892 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1893 if (utf8_len > 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1894 all_ascii = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1895 i += utf8_len; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1896 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1897 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1898 /* If IDENT contains invalid UTF-8 sequences (which may occur with |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1899 attributes putting arbitrary byte sequences in identifiers), or |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1900 control characters, we use octal escape sequences for all bytes |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1901 outside printable ASCII. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1902 if (!valid_printable_utf8) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1903 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1904 char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1905 char *p = ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1906 for (i = 0; i < idlen; i++) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1907 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1908 if (uid[i] > 0x1F && uid[i] < 0x7F) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1909 *p++ = uid[i]; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1910 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1911 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1912 sprintf (p, "\\%03o", uid[i]); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1913 p += 4; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1914 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1915 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1916 *p = 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1917 return ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1918 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1919 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1920 /* Otherwise, if it is valid printable ASCII, or printable UTF-8 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1921 with the locale character set being UTF-8, IDENT is used. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1922 if (all_ascii || locale_utf8) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1923 return ident; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1924 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1925 /* Otherwise IDENT is converted to the locale character set if |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1926 possible. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1927 #if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1928 if (locale_encoding != NULL) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1929 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1930 iconv_t cd = iconv_open (locale_encoding, "UTF-8"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1931 bool conversion_ok = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1932 char *ret = NULL; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1933 if (cd != (iconv_t) -1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1934 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1935 size_t ret_alloc = 4 * idlen + 1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1936 for (;;) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1937 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1938 /* Repeat the whole conversion process as needed with |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1939 larger buffers so non-reversible transformations can |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1940 always be detected. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1941 ICONV_CONST char *inbuf = CONST_CAST (char *, ident); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1942 char *outbuf; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1943 size_t inbytesleft = idlen; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1944 size_t outbytesleft = ret_alloc - 1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1945 size_t iconv_ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1946 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1947 ret = (char *) identifier_to_locale_alloc (ret_alloc); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1948 outbuf = ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1949 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1950 if (iconv (cd, 0, 0, 0, 0) == (size_t) -1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1951 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1952 conversion_ok = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1953 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1954 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1955 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1956 iconv_ret = iconv (cd, &inbuf, &inbytesleft, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1957 &outbuf, &outbytesleft); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1958 if (iconv_ret == (size_t) -1 || inbytesleft != 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1959 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1960 if (errno == E2BIG) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1961 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1962 ret_alloc *= 2; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1963 identifier_to_locale_free (ret); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1964 ret = NULL; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1965 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1966 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1967 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1968 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1969 conversion_ok = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1970 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1971 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1972 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1973 else if (iconv_ret != 0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1974 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1975 conversion_ok = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1976 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1977 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1978 /* Return to initial shift state. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1979 if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1980 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1981 if (errno == E2BIG) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1982 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1983 ret_alloc *= 2; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1984 identifier_to_locale_free (ret); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1985 ret = NULL; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1986 continue; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1987 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1988 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1989 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1990 conversion_ok = false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1991 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1992 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1993 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1994 *outbuf = 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1995 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1996 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1997 iconv_close (cd); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1998 if (conversion_ok) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1999 return ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2000 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2001 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2002 #endif |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2003 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2004 /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2005 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2006 char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2007 char *p = ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2008 for (i = 0; i < idlen;) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2009 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2010 unsigned int c; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2011 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2012 if (utf8_len == 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2013 *p++ = uid[i]; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2014 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2015 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2016 sprintf (p, "\\U%08x", c); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2017 p += 10; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2018 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2019 i += utf8_len; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2020 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2021 *p = 0; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2022 return ret; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2023 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2024 } |
111 | 2025 |
2026 #if CHECKING_P | |
2027 | |
2028 namespace selftest { | |
2029 | |
2030 /* Smoketest for pretty_printer. */ | |
2031 | |
2032 static void | |
2033 test_basic_printing () | |
2034 { | |
2035 pretty_printer pp; | |
2036 pp_string (&pp, "hello"); | |
2037 pp_space (&pp); | |
2038 pp_string (&pp, "world"); | |
2039 | |
2040 ASSERT_STREQ ("hello world", pp_formatted_text (&pp)); | |
2041 } | |
2042 | |
2043 /* Helper function for testing pp_format. | |
2044 Verify that pp_format (FMT, ...) followed by pp_output_formatted_text | |
2045 prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */ | |
2046 | |
2047 static void | |
2048 assert_pp_format_va (const location &loc, const char *expected, | |
2049 bool show_color, const char *fmt, va_list *ap) | |
2050 { | |
2051 pretty_printer pp; | |
2052 text_info ti; | |
2053 rich_location rich_loc (line_table, UNKNOWN_LOCATION); | |
2054 | |
2055 ti.format_spec = fmt; | |
2056 ti.args_ptr = ap; | |
2057 ti.err_no = 0; | |
2058 ti.x_data = NULL; | |
2059 ti.m_richloc = &rich_loc; | |
2060 | |
2061 pp_show_color (&pp) = show_color; | |
2062 pp_format (&pp, &ti); | |
2063 pp_output_formatted_text (&pp); | |
2064 ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp)); | |
2065 } | |
2066 | |
2067 /* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text | |
2068 prints EXPECTED, with show_color disabled. */ | |
2069 | |
2070 static void | |
2071 assert_pp_format (const location &loc, const char *expected, | |
2072 const char *fmt, ...) | |
2073 { | |
2074 va_list ap; | |
2075 | |
2076 va_start (ap, fmt); | |
2077 assert_pp_format_va (loc, expected, false, fmt, &ap); | |
2078 va_end (ap); | |
2079 } | |
2080 | |
2081 /* As above, but with colorization enabled. */ | |
2082 | |
2083 static void | |
2084 assert_pp_format_colored (const location &loc, const char *expected, | |
2085 const char *fmt, ...) | |
2086 { | |
2087 /* The tests of colorization assume the default color scheme. | |
2088 If GCC_COLORS is set, then the colors have potentially been | |
2089 overridden; skip the test. */ | |
2090 if (getenv ("GCC_COLORS")) | |
2091 return; | |
2092 | |
2093 va_list ap; | |
2094 | |
2095 va_start (ap, fmt); | |
2096 assert_pp_format_va (loc, expected, true, fmt, &ap); | |
2097 va_end (ap); | |
2098 } | |
2099 | |
2100 /* Helper function for calling testing pp_format, | |
2101 by calling assert_pp_format with various numbers of arguments. | |
2102 These exist mostly to avoid having to write SELFTEST_LOCATION | |
2103 throughout test_pp_format. */ | |
2104 | |
2105 #define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \ | |
2106 SELFTEST_BEGIN_STMT \ | |
2107 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \ | |
2108 (ARG1)); \ | |
2109 SELFTEST_END_STMT | |
2110 | |
2111 #define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \ | |
2112 SELFTEST_BEGIN_STMT \ | |
2113 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \ | |
2114 (ARG1), (ARG2)); \ | |
2115 SELFTEST_END_STMT | |
2116 | |
2117 #define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \ | |
2118 SELFTEST_BEGIN_STMT \ | |
2119 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \ | |
2120 (ARG1), (ARG2), (ARG3)); \ | |
2121 SELFTEST_END_STMT | |
2122 | |
2123 /* Verify that pp_format works, for various format codes. */ | |
2124 | |
2125 static void | |
2126 test_pp_format () | |
2127 { | |
2128 /* Avoid introducing locale-specific differences in the results | |
2129 by hardcoding open_quote and close_quote. */ | |
131 | 2130 auto_fix_quotes fix_quotes; |
111 | 2131 |
2132 /* Verify that plain text is passed through unchanged. */ | |
2133 assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted"); | |
2134 | |
2135 /* Verify various individual format codes, in the order listed in the | |
2136 comment for pp_format above. For each code, we append a second | |
2137 argument with a known bit pattern (0x12345678), to ensure that we | |
2138 are consuming arguments correctly. */ | |
2139 ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678); | |
2140 ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678); | |
2141 ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678); | |
2142 ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678); | |
2143 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678); | |
2144 ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678); | |
2145 ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678); | |
2146 ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678); | |
2147 ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678); | |
2148 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe, | |
2149 0x12345678); | |
2150 ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678); | |
2151 ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678); | |
2152 ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678); | |
2153 ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678); | |
2154 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe, | |
2155 0x12345678); | |
2156 ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678); | |
2157 ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678); | |
2158 ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10, | |
2159 0x12345678); | |
2160 ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678); | |
2161 ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe, | |
2162 0x12345678); | |
2163 ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678); | |
2164 ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world", | |
2165 0x12345678); | |
2166 | |
2167 /* Not nul-terminated. */ | |
2168 char arr[5] = { '1', '2', '3', '4', '5' }; | |
2169 ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678); | |
2170 ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678); | |
2171 ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678); | |
2172 | |
2173 /* We can't test for %p; the pointer is printed in an implementation-defined | |
2174 manner. */ | |
2175 ASSERT_PP_FORMAT_2 ("normal colored normal 12345678", | |
2176 "normal %rcolored%R normal %x", | |
2177 "error", 0x12345678); | |
2178 assert_pp_format_colored | |
2179 (SELFTEST_LOCATION, | |
2180 "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678", | |
2181 "normal %rcolored%R normal %x", "error", 0x12345678); | |
2182 /* TODO: | |
2183 %m: strerror(text->err_no) - does not consume a value from args_ptr. */ | |
2184 ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678); | |
2185 ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678); | |
2186 ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678); | |
2187 ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678); | |
2188 ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678); | |
2189 ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678); | |
2190 | |
2191 /* Verify flag 'q'. */ | |
2192 ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678); | |
2193 assert_pp_format_colored (SELFTEST_LOCATION, | |
2194 "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x", | |
2195 "foo", 0x12345678); | |
2196 | |
2197 /* Verify %Z. */ | |
2198 int v[] = { 1, 2, 3 }; | |
2199 ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678); | |
2200 | |
2201 int v2[] = { 0 }; | |
2202 ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678); | |
2203 | |
2204 /* Verify that combinations work, along with unformatted text. */ | |
2205 assert_pp_format (SELFTEST_LOCATION, | |
2206 "the quick brown fox jumps over the lazy dog", | |
2207 "the %s %s %s jumps over the %s %s", | |
2208 "quick", "brown", "fox", "lazy", "dog"); | |
2209 assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7); | |
2210 assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10", | |
2211 "problem with %qs at line %i", "bar", 10); | |
2212 } | |
2213 | |
2214 /* Run all of the selftests within this file. */ | |
2215 | |
2216 void | |
2217 pretty_print_c_tests () | |
2218 { | |
2219 test_basic_printing (); | |
2220 test_pp_format (); | |
2221 } | |
2222 | |
2223 } // namespace selftest | |
2224 | |
2225 #endif /* CHECKING_P */ |