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