]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/pretty-print.c
[Ada] Use Standard.Natural on bit references to packed arrays
[thirdparty/gcc.git] / gcc / pretty-print.c
CommitLineData
b6fe0bb8 1/* Various declarations for language-independent pretty-print subroutines.
8d9254fc 2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
b6fe0bb8
GDR
3 Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9dcd6f09 9Software Foundation; either version 3, or (at your option) any later
b6fe0bb8
GDR
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
9dcd6f09
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
b6fe0bb8
GDR
20
21#include "config.h"
b6fe0bb8
GDR
22#include "system.h"
23#include "coretypes.h"
a668adb2 24#include "intl.h"
b6fe0bb8 25#include "pretty-print.h"
4b84d650 26#include "diagnostic-color.h"
4bc1899b 27#include "diagnostic-event-id.h"
4ccab56d 28#include "selftest.h"
a3af5087
JM
29
30#if HAVE_ICONV
31#include <iconv.h>
32#endif
b6fe0bb8 33
db0d1bae
LH
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. */
48static void
49write_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. */
75static int
76find_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. */
113static int
114find_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. */
140static void
141eat_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
637sgr_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 }
5d3083dd
LH
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 }
db0d1bae
LH
654 SetConsoleTextAttribute (h, attrib_add);
655 break;
656 }
657}
658
659int
660mingw_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
db0d1bae
LH
698 return 1;
699}
700
701#endif /* __MINGW32__ */
702
ddd0fd17
LH
703static int
704decode_utf8_char (const unsigned char *, size_t len, unsigned int *);
3f0177e7
MS
705static void pp_quoted_string (pretty_printer *, const char *, size_t = -1);
706
f79520bb 707/* Overwrite the given location/range within this text_info's rich_location.
8a645150
DM
708 For use e.g. when implementing "+" in client format decoders. */
709
710void
85204e23
DM
711text_info::set_location (unsigned int idx, location_t loc,
712 enum range_display_kind range_display_kind)
8a645150
DM
713{
714 gcc_checking_assert (m_richloc);
85204e23 715 m_richloc->set_range (idx, loc, range_display_kind);
8a645150
DM
716}
717
718location_t
719text_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
da6ca2b5
GDR
729// Default construct an output buffer.
730
731output_buffer::output_buffer ()
732 : formatted_obstack (),
733 chunk_obstack (),
734 obstack (&formatted_obstack),
735 cur_chunk_array (),
736 stream (stderr),
737 line_length (),
48749dbc
MLI
738 digit_buffer (),
739 flush_p (true)
da6ca2b5
GDR
740{
741 obstack_init (&formatted_obstack);
742 obstack_init (&chunk_obstack);
743}
744
025311c4
GDR
745// Release resources owned by an output buffer at the end of lifetime.
746
747output_buffer::~output_buffer ()
748{
65f5c720
RB
749 obstack_free (&chunk_obstack, NULL);
750 obstack_free (&formatted_obstack, NULL);
025311c4
GDR
751}
752
b6fe0bb8
GDR
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: \
2a157700 770 pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \
b6fe0bb8
GDR
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. */
781static void
782pp_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. */
804static inline void
805pp_clear_state (pretty_printer *pp)
806{
807 pp->emitted_prefix = false;
808 pp_indentation (pp) = 0;
809}
810
dc3f3805
RS
811/* Print X to PP in decimal. */
812template<unsigned int N, typename T>
813void
814pp_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
831template void pp_wide_integer (pretty_printer *, const poly_uint16_pod &);
832template void pp_wide_integer (pretty_printer *, const poly_int64_pod &);
833template void pp_wide_integer (pretty_printer *, const poly_uint64_pod &);
834
b6fe0bb8 835/* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */
6de9cd9a 836void
b6fe0bb8
GDR
837pp_write_text_to_stream (pretty_printer *pp)
838{
839 const char *text = pp_formatted_text (pp);
db0d1bae
LH
840#ifdef __MINGW32__
841 mingw_ansi_fputs (text, pp_buffer (pp)->stream);
842#else
025311c4 843 fputs (text, pp_buffer (pp)->stream);
db0d1bae 844#endif
b6fe0bb8
GDR
845 pp_clear_output_area (pp);
846}
847
7eba871a
SB
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
857void
858pp_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;
025311c4 862 FILE *fp = pp_buffer (pp)->stream;
7eba871a 863
da3ebf2d 864 for (;*p; p++)
7eba871a 865 {
da3ebf2d 866 bool escape_char;
7eba871a
SB
867 switch (*p)
868 {
869 /* Print newlines as a left-aligned newline. */
870 case '\n':
da3ebf2d
TV
871 fputs ("\\l", fp);
872 escape_char = true;
7eba871a
SB
873 break;
874
795391fb 875 /* The following characters are only special for record-shape nodes. */
7eba871a 876 case '|':
795391fb
TV
877 case '{':
878 case '}':
879 case '<':
880 case '>':
881 case ' ':
da3ebf2d 882 escape_char = for_record;
7eba871a
SB
883 break;
884
885 /* The following characters always have to be escaped
886 for use in labels. */
b3de2446
TV
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. */
7eba871a 893 case '"':
da3ebf2d
TV
894 escape_char = true;
895 break;
896
7eba871a 897 default:
da3ebf2d 898 escape_char = false;
7eba871a
SB
899 break;
900 }
da3ebf2d
TV
901
902 if (escape_char)
903 fputc ('\\', fp);
904
905 fputc (*p, fp);
7eba871a
SB
906 }
907
908 pp_clear_output_area (pp);
909}
910
a326a3de
DM
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 "&apos;" or in HTML as "&#39;");.
923
924 Experiments show that escaping "'" doesn't seem to be necessary. */
925
926void
927pp_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 ("&quot;", fp);
939 break;
940 case '&':
941 fputs ("&amp;", fp);
942 break;
943 case '<':
944 fputs ("&lt;", fp);
945 break;
946 case '>':
947 fputs ("&gt;",fp);
948 break;
949
950 default:
951 fputc (*p, fp);
952 break;
953 }
954 }
955
956 pp_clear_output_area (pp);
957}
958
b6fe0bb8
GDR
959/* Wrap a text delimited by START and END into PRETTY-PRINTER. */
960static void
961pp_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. */
993static inline void
994pp_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. */
1004static inline void
1005pp_append_r (pretty_printer *pp, const char *start, int length)
1006{
c4100eae 1007 output_buffer_append_r (pp_buffer (pp), start, length);
b6fe0bb8
GDR
1008}
1009
4b780675
GDR
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. */
1013void
b066401f 1014pp_indent (pretty_printer *pp)
4b780675
GDR
1015{
1016 int n = pp_indentation (pp);
1017 int i;
1018
1019 for (i = 0; i < n; ++i)
1020 pp_space (pp);
1021}
1022
691eeb65
JJ
1023static const char *get_end_url_string (pretty_printer *);
1024
39ce81c9 1025/* The following format specifiers are recognized as being client independent:
b6fe0bb8
GDR
1026 %d, %i: (signed) integer in base ten.
1027 %u: unsigned integer in base ten.
1028 %o: unsigned integer in base eight.
1029 %x: unsigned integer in base sixteen.
1030 %ld, %li, %lo, %lu, %lx: long versions of the above.
1031 %lld, %lli, %llo, %llu, %llx: long long versions.
1032 %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
204839e7 1033 %f: double
b6fe0bb8
GDR
1034 %c: character.
1035 %s: string.
914bc2b9 1036 %p: pointer (printed in a host-dependent manner).
4b84d650
JJ
1037 %r: if pp_show_color(pp), switch to color identified by const char *.
1038 %R: if pp_show_color(pp), reset color.
b6fe0bb8 1039 %m: strerror(text->err_no) - does not consume a value from args_ptr.
a668adb2 1040 %%: '%'.
ca09cd34
JM
1041 %<: opening quote.
1042 %>: closing quote.
691eeb65
JJ
1043 %{: URL start. Consumes a const char * argument for the URL.
1044 %}: URL end. Does not consume any arguments.
ca09cd34
JM
1045 %': apostrophe (should only be used in untranslated messages;
1046 translations should use appropriate punctuation directly).
4bc1899b 1047 %@: diagnostic_event_id_ptr, for which event_id->known_p () must be true.
39ce81c9
ZW
1048 %.*s: a substring the length of which is specified by an argument
1049 integer.
1050 %Ns: likewise, but length specified as constant in the format string.
39ce81c9 1051 Flag 'q': quote formatted text (must come immediately after '%').
975672f3
PK
1052 %Z: Requires two arguments - array of int, and len. Prints elements
1053 of the array.
39ce81c9
ZW
1054
1055 Arguments can be used sequentially, or through %N$ resp. *N$
1056 notation Nth argument after the format string. If %N$ / *N$
1057 notation is used, it must be used for all arguments, except %m, %%,
691eeb65 1058 %<, %>, %} and %', which may not have a number, as they do not consume
39ce81c9
ZW
1059 an argument. When %M$.*N$s is used, M must be N + 1. (This may
1060 also be written %M$.*s, provided N is not otherwise used.) The
1061 format string must have conversion specifiers with argument numbers
1062 1 up to highest argument; each argument may only be used once.
1063 A format string can have at most 30 arguments. */
1064
1065/* Formatting phases 1 and 2: render TEXT->format_spec plus
025311c4 1066 TEXT->args_ptr into a series of chunks in pp_buffer (PP)->args[].
4ccab56d 1067 Phase 3 is in pp_output_formatted_text. */
39ce81c9 1068
b6fe0bb8 1069void
b066401f 1070pp_format (pretty_printer *pp, text_info *text)
b6fe0bb8 1071{
025311c4 1072 output_buffer *buffer = pp_buffer (pp);
39ce81c9
ZW
1073 const char *p;
1074 const char **args;
1075 struct chunk_info *new_chunk_array;
1076
1077 unsigned int curarg = 0, chunk = 0, argno;
1078 pp_wrapping_mode_t old_wrapping_mode;
1079 bool any_unnumbered = false, any_numbered = false;
1080 const char **formatters[PP_NL_ARGMAX];
1081
1082 /* Allocate a new chunk structure. */
1083 new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
1084 new_chunk_array->prev = buffer->cur_chunk_array;
1085 buffer->cur_chunk_array = new_chunk_array;
1086 args = new_chunk_array->args;
1087
1088 /* Formatting phase 1: split up TEXT->format_spec into chunks in
025311c4 1089 pp_buffer (PP)->args[]. Even-numbered chunks are to be output
39ce81c9 1090 verbatim, odd-numbered chunks are format specifiers.
691eeb65 1091 %m, %%, %<, %>, %} and %' are replaced with the appropriate text at
39ce81c9
ZW
1092 this point. */
1093
1094 memset (formatters, 0, sizeof formatters);
b8698a0f 1095
39ce81c9 1096 for (p = text->format_spec; *p; )
b6fe0bb8 1097 {
39ce81c9
ZW
1098 while (*p != '\0' && *p != '%')
1099 {
1100 obstack_1grow (&buffer->chunk_obstack, *p);
1101 p++;
1102 }
b6fe0bb8 1103
39ce81c9
ZW
1104 if (*p == '\0')
1105 break;
1106
1107 switch (*++p)
1108 {
1109 case '\0':
1110 gcc_unreachable ();
b8698a0f 1111
39ce81c9
ZW
1112 case '%':
1113 obstack_1grow (&buffer->chunk_obstack, '%');
1114 p++;
1115 continue;
b6fe0bb8 1116
39ce81c9 1117 case '<':
4b84d650
JJ
1118 {
1119 obstack_grow (&buffer->chunk_obstack,
1120 open_quote, strlen (open_quote));
1121 const char *colorstr
1122 = colorize_start (pp_show_color (pp), "quote");
1123 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
1124 p++;
1125 continue;
1126 }
39ce81c9
ZW
1127
1128 case '>':
4b84d650
JJ
1129 {
1130 const char *colorstr = colorize_stop (pp_show_color (pp));
1131 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
1132 }
1133 /* FALLTHRU */
39ce81c9
ZW
1134 case '\'':
1135 obstack_grow (&buffer->chunk_obstack,
241de8a0 1136 close_quote, strlen (close_quote));
39ce81c9
ZW
1137 p++;
1138 continue;
1139
691eeb65
JJ
1140 case '}':
1141 {
1142 const char *endurlstr = get_end_url_string (pp);
1143 obstack_grow (&buffer->chunk_obstack, endurlstr,
1144 strlen (endurlstr));
1145 }
1146 p++;
1147 continue;
1148
4b84d650
JJ
1149 case 'R':
1150 {
1151 const char *colorstr = colorize_stop (pp_show_color (pp));
1152 obstack_grow (&buffer->chunk_obstack, colorstr,
1153 strlen (colorstr));
1154 p++;
1155 continue;
1156 }
1157
39ce81c9
ZW
1158 case 'm':
1159 {
1160 const char *errstr = xstrerror (text->err_no);
1161 obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
1162 }
1163 p++;
1164 continue;
1165
1166 default:
1167 /* Handled in phase 2. Terminate the plain chunk here. */
1168 obstack_1grow (&buffer->chunk_obstack, '\0');
1169 gcc_assert (chunk < PP_NL_ARGMAX * 2);
1170 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1171 break;
1172 }
1173
1174 if (ISDIGIT (*p))
1175 {
1176 char *end;
1177 argno = strtoul (p, &end, 10) - 1;
1178 p = end;
1179 gcc_assert (*p == '$');
1180 p++;
1181
1182 any_numbered = true;
1183 gcc_assert (!any_unnumbered);
1184 }
1185 else
1186 {
1187 argno = curarg++;
1188 any_unnumbered = true;
1189 gcc_assert (!any_numbered);
1190 }
1191 gcc_assert (argno < PP_NL_ARGMAX);
1192 gcc_assert (!formatters[argno]);
1193 formatters[argno] = &args[chunk];
1194 do
1195 {
1196 obstack_1grow (&buffer->chunk_obstack, *p);
1197 p++;
1198 }
1199 while (strchr ("qwl+#", p[-1]));
1200
1201 if (p[-1] == '.')
1202 {
1203 /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
1204 (where M == N + 1). */
1205 if (ISDIGIT (*p))
1206 {
1207 do
1208 {
1209 obstack_1grow (&buffer->chunk_obstack, *p);
1210 p++;
1211 }
1212 while (ISDIGIT (p[-1]));
1213 gcc_assert (p[-1] == 's');
1214 }
1215 else
1216 {
1217 gcc_assert (*p == '*');
1218 obstack_1grow (&buffer->chunk_obstack, '*');
1219 p++;
1220
1221 if (ISDIGIT (*p))
1222 {
1223 char *end;
1224 unsigned int argno2 = strtoul (p, &end, 10) - 1;
1225 p = end;
1226 gcc_assert (argno2 == argno - 1);
1227 gcc_assert (!any_unnumbered);
1228 gcc_assert (*p == '$');
1229
1230 p++;
1231 formatters[argno2] = formatters[argno];
1232 }
1233 else
1234 {
1235 gcc_assert (!any_numbered);
1236 formatters[argno+1] = formatters[argno];
1237 curarg++;
1238 }
1239 gcc_assert (*p == 's');
1240 obstack_1grow (&buffer->chunk_obstack, 's');
1241 p++;
1242 }
1243 }
1244 if (*p == '\0')
b6fe0bb8
GDR
1245 break;
1246
39ce81c9
ZW
1247 obstack_1grow (&buffer->chunk_obstack, '\0');
1248 gcc_assert (chunk < PP_NL_ARGMAX * 2);
1249 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1250 }
1251
1252 obstack_1grow (&buffer->chunk_obstack, '\0');
1253 gcc_assert (chunk < PP_NL_ARGMAX * 2);
1254 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1255 args[chunk] = 0;
b8698a0f 1256
39ce81c9
ZW
1257 /* Set output to the argument obstack, and switch line-wrapping and
1258 prefixing off. */
1259 buffer->obstack = &buffer->chunk_obstack;
e9c9a142 1260 const int old_line_length = buffer->line_length;
39ce81c9
ZW
1261 old_wrapping_mode = pp_set_verbatim_wrapping (pp);
1262
1263 /* Second phase. Replace each formatter with the formatted text it
1264 corresponds to. */
1265
1266 for (argno = 0; formatters[argno]; argno++)
1267 {
1268 int precision = 0;
1269 bool wide = false;
1270 bool plus = false;
1271 bool hash = false;
1272 bool quote = false;
1273
1274 /* We do not attempt to enforce any ordering on the modifier
1275 characters. */
1276
1277 for (p = *formatters[argno];; p++)
a668adb2 1278 {
39ce81c9
ZW
1279 switch (*p)
1280 {
1281 case 'q':
1282 gcc_assert (!quote);
1283 quote = true;
1284 continue;
1285
1286 case '+':
1287 gcc_assert (!plus);
1288 plus = true;
1289 continue;
1290
1291 case '#':
1292 gcc_assert (!hash);
1293 hash = true;
1294 continue;
1295
1296 case 'w':
1297 gcc_assert (!wide);
1298 wide = true;
1299 continue;
1300
1301 case 'l':
1302 /* We don't support precision beyond that of "long long". */
1303 gcc_assert (precision < 2);
1304 precision++;
1305 continue;
1306 }
1307 break;
a668adb2 1308 }
39ce81c9
ZW
1309
1310 gcc_assert (!wide || precision == 0);
1311
1312 if (quote)
ce95abc4 1313 pp_begin_quote (pp, pp_show_color (pp));
39ce81c9
ZW
1314
1315 switch (*p)
b6fe0bb8 1316 {
4b84d650
JJ
1317 case 'r':
1318 pp_string (pp, colorize_start (pp_show_color (pp),
1319 va_arg (*text->args_ptr,
1320 const char *)));
1321 break;
1322
b6fe0bb8 1323 case 'c':
3f0177e7
MS
1324 {
1325 /* When quoting, print alphanumeric, punctuation, and the space
1326 character unchanged, and all others in hexadecimal with the
1327 "\x" prefix. Otherwise print them all unchanged. */
1328 int chr = va_arg (*text->args_ptr, int);
1329 if (ISPRINT (chr) || !quote)
1330 pp_character (pp, chr);
1331 else
1332 {
1333 const char str [2] = { chr, '\0' };
1334 pp_quoted_string (pp, str, 1);
1335 }
1336 break;
1337 }
b6fe0bb8
GDR
1338
1339 case 'd':
1340 case 'i':
39ce81c9
ZW
1341 if (wide)
1342 pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
1343 else
1344 pp_integer_with_precision
1345 (pp, *text->args_ptr, precision, int, "d");
b6fe0bb8
GDR
1346 break;
1347
1348 case 'o':
39ce81c9
ZW
1349 if (wide)
1350 pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
1351 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1352 else
1353 pp_integer_with_precision
1354 (pp, *text->args_ptr, precision, unsigned, "o");
b6fe0bb8
GDR
1355 break;
1356
1357 case 's':
3f0177e7
MS
1358 if (quote)
1359 pp_quoted_string (pp, va_arg (*text->args_ptr, const char *));
1360 else
1361 pp_string (pp, va_arg (*text->args_ptr, const char *));
b6fe0bb8
GDR
1362 break;
1363
39ce81c9
ZW
1364 case 'p':
1365 pp_pointer (pp, va_arg (*text->args_ptr, void *));
1366 break;
b6fe0bb8
GDR
1367
1368 case 'u':
39ce81c9
ZW
1369 if (wide)
1370 pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
1371 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1372 else
1373 pp_integer_with_precision
1374 (pp, *text->args_ptr, precision, unsigned, "u");
b6fe0bb8
GDR
1375 break;
1376
204839e7
DM
1377 case 'f':
1378 pp_double (pp, va_arg (*text->args_ptr, double));
1379 break;
1380
975672f3
PK
1381 case 'Z':
1382 {
1383 int *v = va_arg (*text->args_ptr, int *);
1384 unsigned len = va_arg (*text->args_ptr, unsigned);
1385
1386 for (unsigned i = 0; i < len; ++i)
1387 {
1388 pp_scalar (pp, "%i", v[i]);
1389 if (i < len - 1)
1390 {
1391 pp_comma (pp);
1392 pp_space (pp);
1393 }
1394 }
1395 break;
1396 }
1397
b6fe0bb8 1398 case 'x':
39ce81c9
ZW
1399 if (wide)
1400 pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
1401 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1402 else
1403 pp_integer_with_precision
1404 (pp, *text->args_ptr, precision, unsigned, "x");
b6fe0bb8
GDR
1405 break;
1406
b6fe0bb8
GDR
1407 case '.':
1408 {
1409 int n;
1410 const char *s;
d5706a1e 1411
39ce81c9
ZW
1412 /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
1413 (where M == N + 1). The format string should be verified
1414 already from the first phase. */
1415 p++;
1416 if (ISDIGIT (*p))
1417 {
1418 char *end;
1419 n = strtoul (p, &end, 10);
1420 p = end;
1421 gcc_assert (*p == 's');
1422 }
1423 else
1424 {
1425 gcc_assert (*p == '*');
1426 p++;
1427 gcc_assert (*p == 's');
1428 n = va_arg (*text->args_ptr, int);
1429
1430 /* This consumes a second entry in the formatters array. */
1431 gcc_assert (formatters[argno] == formatters[argno+1]);
1432 argno++;
1433 }
1434
b6fe0bb8 1435 s = va_arg (*text->args_ptr, const char *);
0a8923fa 1436
86ef85d3
MS
1437 /* Append the lesser of precision and strlen (s) characters
1438 from the array (which need not be a nul-terminated string).
1439 Negative precision is treated as if it were omitted. */
1440 size_t len = n < 0 ? strlen (s) : strnlen (s, n);
0a8923fa
MS
1441
1442 pp_append_text (pp, s, s + len);
b6fe0bb8
GDR
1443 }
1444 break;
1445
4bc1899b
DM
1446 case '@':
1447 {
1448 /* diagnostic_event_id_t *. */
1449 diagnostic_event_id_ptr event_id
1450 = va_arg (*text->args_ptr, diagnostic_event_id_ptr);
1451 gcc_assert (event_id->known_p ());
1452
1453 pp_string (pp, colorize_start (pp_show_color (pp), "path"));
1454 pp_character (pp, '(');
1455 pp_decimal_int (pp, event_id->one_based ());
1456 pp_character (pp, ')');
1457 pp_string (pp, colorize_stop (pp_show_color (pp)));
1458 }
1459 break;
1460
691eeb65
JJ
1461 case '{':
1462 pp_begin_url (pp, va_arg (*text->args_ptr, const char *));
1463 break;
1464
b6fe0bb8 1465 default:
0e61db61
NS
1466 {
1467 bool ok;
39ce81c9 1468
ce95abc4
DM
1469 /* Call the format decoder.
1470 Pass the address of "quote" so that format decoders can
1471 potentially disable printing of the closing quote
1472 (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family
1473 of frontends). */
0e61db61 1474 gcc_assert (pp_format_decoder (pp));
39ce81c9 1475 ok = pp_format_decoder (pp) (pp, text, p,
ce95abc4 1476 precision, wide, plus, hash, &quote,
f012c8ef 1477 formatters[argno]);
0e61db61
NS
1478 gcc_assert (ok);
1479 }
b6fe0bb8 1480 }
39ce81c9
ZW
1481
1482 if (quote)
ce95abc4 1483 pp_end_quote (pp, pp_show_color (pp));
39ce81c9
ZW
1484
1485 obstack_1grow (&buffer->chunk_obstack, '\0');
1486 *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
b6fe0bb8 1487 }
39ce81c9 1488
b2b29377
MM
1489 if (CHECKING_P)
1490 for (; argno < PP_NL_ARGMAX; argno++)
1491 gcc_assert (!formatters[argno]);
39ce81c9 1492
f012c8ef
DM
1493 /* If the client supplied a postprocessing object, call its "handle"
1494 hook here. */
1495 if (pp->m_format_postprocessor)
1496 pp->m_format_postprocessor->handle (pp);
1497
39ce81c9
ZW
1498 /* Revert to normal obstack and wrapping mode. */
1499 buffer->obstack = &buffer->formatted_obstack;
e9c9a142 1500 buffer->line_length = old_line_length;
39ce81c9
ZW
1501 pp_wrapping_mode (pp) = old_wrapping_mode;
1502 pp_clear_state (pp);
1503}
1504
1505/* Format of a message pointed to by TEXT. */
1506void
b066401f 1507pp_output_formatted_text (pretty_printer *pp)
39ce81c9
ZW
1508{
1509 unsigned int chunk;
1510 output_buffer *buffer = pp_buffer (pp);
1511 struct chunk_info *chunk_array = buffer->cur_chunk_array;
1512 const char **args = chunk_array->args;
1513
1514 gcc_assert (buffer->obstack == &buffer->formatted_obstack);
39ce81c9 1515
b066401f 1516 /* This is a third phase, first 2 phases done in pp_format_args.
39ce81c9
ZW
1517 Now we actually print it. */
1518 for (chunk = 0; args[chunk]; chunk++)
1519 pp_string (pp, args[chunk]);
1520
1521 /* Deallocate the chunk structure and everything after it (i.e. the
1522 associated series of formatted strings). */
1523 buffer->cur_chunk_array = chunk_array->prev;
1524 obstack_free (&buffer->chunk_obstack, chunk_array);
b6fe0bb8
GDR
1525}
1526
1527/* Helper subroutine of output_verbatim and verbatim. Do the appropriate
1528 settings needed by BUFFER for a verbatim formatting. */
1529void
b066401f 1530pp_format_verbatim (pretty_printer *pp, text_info *text)
b6fe0bb8 1531{
b6fe0bb8 1532 /* Set verbatim mode. */
39ce81c9
ZW
1533 pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
1534
b6fe0bb8 1535 /* Do the actual formatting. */
39ce81c9
ZW
1536 pp_format (pp, text);
1537 pp_output_formatted_text (pp);
1538
b6fe0bb8 1539 /* Restore previous settings. */
39ce81c9 1540 pp_wrapping_mode (pp) = oldmode;
b6fe0bb8
GDR
1541}
1542
48749dbc
MLI
1543/* Flush the content of BUFFER onto the attached stream. This
1544 function does nothing unless pp->output_buffer->flush_p. */
b6fe0bb8 1545void
b066401f 1546pp_flush (pretty_printer *pp)
b6fe0bb8 1547{
48749dbc
MLI
1548 pp_clear_state (pp);
1549 if (!pp->buffer->flush_p)
1550 return;
b6fe0bb8 1551 pp_write_text_to_stream (pp);
48749dbc
MLI
1552 fflush (pp_buffer (pp)->stream);
1553}
1554
1555/* Flush the content of BUFFER onto the attached stream independently
1556 of the value of pp->output_buffer->flush_p. */
1557void
1558pp_really_flush (pretty_printer *pp)
1559{
b6fe0bb8 1560 pp_clear_state (pp);
48749dbc 1561 pp_write_text_to_stream (pp);
025311c4 1562 fflush (pp_buffer (pp)->stream);
b6fe0bb8
GDR
1563}
1564
1565/* Sets the number of maximum characters per line PRETTY-PRINTER can
1566 output in line-wrapping mode. A LENGTH value 0 suppresses
1567 line-wrapping. */
1568void
b066401f 1569pp_set_line_maximum_length (pretty_printer *pp, int length)
b6fe0bb8
GDR
1570{
1571 pp_line_cutoff (pp) = length;
1572 pp_set_real_maximum_length (pp);
1573}
1574
1575/* Clear PRETTY-PRINTER output area text info. */
1576void
b066401f 1577pp_clear_output_area (pretty_printer *pp)
b6fe0bb8 1578{
025311c4
GDR
1579 obstack_free (pp_buffer (pp)->obstack,
1580 obstack_base (pp_buffer (pp)->obstack));
1581 pp_buffer (pp)->line_length = 0;
b6fe0bb8
GDR
1582}
1583
653fee19
DM
1584/* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which
1585 will eventually be free-ed. */
1586
b6fe0bb8 1587void
653fee19 1588pp_set_prefix (pretty_printer *pp, char *prefix)
b6fe0bb8 1589{
653fee19 1590 free (pp->prefix);
b6fe0bb8
GDR
1591 pp->prefix = prefix;
1592 pp_set_real_maximum_length (pp);
1593 pp->emitted_prefix = false;
1594 pp_indentation (pp) = 0;
1595}
1596
653fee19 1597/* Take ownership of PP's prefix, setting it to NULL.
04e88369 1598 This allows clients to save, override, and then restore an existing
653fee19
DM
1599 prefix, without it being free-ed. */
1600
1601char *
1602pp_take_prefix (pretty_printer *pp)
1603{
1604 char *result = pp->prefix;
1605 pp->prefix = NULL;
1606 return result;
1607}
1608
b6fe0bb8
GDR
1609/* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */
1610void
b066401f 1611pp_destroy_prefix (pretty_printer *pp)
b6fe0bb8
GDR
1612{
1613 if (pp->prefix != NULL)
1614 {
653fee19 1615 free (pp->prefix);
b6fe0bb8
GDR
1616 pp->prefix = NULL;
1617 }
1618}
1619
1620/* Write out PRETTY-PRINTER's prefix. */
1621void
b066401f 1622pp_emit_prefix (pretty_printer *pp)
b6fe0bb8
GDR
1623{
1624 if (pp->prefix != NULL)
1625 {
1626 switch (pp_prefixing_rule (pp))
1627 {
1628 default:
1629 case DIAGNOSTICS_SHOW_PREFIX_NEVER:
1630 break;
1631
1632 case DIAGNOSTICS_SHOW_PREFIX_ONCE:
1633 if (pp->emitted_prefix)
1634 {
b066401f 1635 pp_indent (pp);
b6fe0bb8
GDR
1636 break;
1637 }
1638 pp_indentation (pp) += 3;
1639 /* Fall through. */
1640
1641 case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
1642 {
1643 int prefix_length = strlen (pp->prefix);
1644 pp_append_r (pp, pp->prefix, prefix_length);
1645 pp->emitted_prefix = true;
1646 }
1647 break;
1648 }
1649 }
1650}
1651
653fee19 1652/* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line. */
da6ca2b5 1653
653fee19 1654pretty_printer::pretty_printer (int maximum_length)
da6ca2b5
GDR
1655 : buffer (new (XCNEW (output_buffer)) output_buffer ()),
1656 prefix (),
1657 padding (pp_none),
1658 maximum_length (),
1659 indent_skip (),
1660 wrapping (),
1661 format_decoder (),
f012c8ef 1662 m_format_postprocessor (NULL),
da6ca2b5
GDR
1663 emitted_prefix (),
1664 need_newline (),
c3284718 1665 translate_identifiers (true),
d2608235 1666 show_color (),
458c8d64 1667 url_format (URL_FORMAT_NONE)
b6fe0bb8 1668{
653fee19 1669 pp_line_cutoff (this) = maximum_length;
da6ca2b5
GDR
1670 /* By default, we emit prefixes once per message. */
1671 pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
653fee19 1672 pp_set_prefix (this, NULL);
b6fe0bb8
GDR
1673}
1674
368877a1
DM
1675/* Copy constructor for pretty_printer. */
1676
1677pretty_printer::pretty_printer (const pretty_printer &other)
1678: buffer (new (XCNEW (output_buffer)) output_buffer ()),
1679 prefix (),
1680 padding (other.padding),
1681 maximum_length (other.maximum_length),
1682 indent_skip (other.indent_skip),
1683 wrapping (other.wrapping),
1684 format_decoder (other.format_decoder),
1685 m_format_postprocessor (NULL),
1686 emitted_prefix (other.emitted_prefix),
1687 need_newline (other.need_newline),
1688 translate_identifiers (other.translate_identifiers),
1689 show_color (other.show_color),
458c8d64 1690 url_format (other.url_format)
368877a1
DM
1691{
1692 pp_line_cutoff (this) = maximum_length;
1693 /* By default, we emit prefixes once per message. */
1694 pp_prefixing_rule (this) = pp_prefixing_rule (&other);
1695 pp_set_prefix (this, NULL);
1696
1697 if (other.m_format_postprocessor)
1698 m_format_postprocessor = other.m_format_postprocessor->clone ();
1699}
1700
025311c4
GDR
1701pretty_printer::~pretty_printer ()
1702{
f012c8ef
DM
1703 if (m_format_postprocessor)
1704 delete m_format_postprocessor;
025311c4
GDR
1705 buffer->~output_buffer ();
1706 XDELETE (buffer);
653fee19 1707 free (prefix);
025311c4
GDR
1708}
1709
368877a1
DM
1710/* Base class implementation of pretty_printer::clone vfunc. */
1711
1712pretty_printer *
1713pretty_printer::clone () const
1714{
1715 return new pretty_printer (*this);
1716}
1717
b6fe0bb8
GDR
1718/* Append a string delimited by START and END to the output area of
1719 PRETTY-PRINTER. No line wrapping is done. However, if beginning a
1720 new line then emit PRETTY-PRINTER's prefix and skip any leading
1721 whitespace if appropriate. The caller must ensure that it is
1722 safe to do so. */
1723void
b066401f 1724pp_append_text (pretty_printer *pp, const char *start, const char *end)
b6fe0bb8
GDR
1725{
1726 /* Emit prefix and skip whitespace if we're starting a new line. */
025311c4 1727 if (pp_buffer (pp)->line_length == 0)
b6fe0bb8
GDR
1728 {
1729 pp_emit_prefix (pp);
1730 if (pp_is_wrapping_line (pp))
1731 while (start != end && *start == ' ')
1732 ++start;
1733 }
1734 pp_append_r (pp, start, end - start);
1735}
1736
1737/* Finishes constructing a NULL-terminated character string representing
1738 the PRETTY-PRINTED text. */
1739const char *
b066401f 1740pp_formatted_text (pretty_printer *pp)
b6fe0bb8 1741{
c4100eae 1742 return output_buffer_formatted_text (pp_buffer (pp));
b6fe0bb8
GDR
1743}
1744
1745/* Return a pointer to the last character emitted in PRETTY-PRINTER's
1746 output area. A NULL pointer means no character available. */
1747const char *
b066401f 1748pp_last_position_in_text (const pretty_printer *pp)
b6fe0bb8 1749{
c4100eae 1750 return output_buffer_last_position_in_text (pp_buffer (pp));
b6fe0bb8
GDR
1751}
1752
1753/* Return the amount of characters PRETTY-PRINTER can accept to
ba228239 1754 make a full line. Meaningful only in line-wrapping mode. */
b6fe0bb8 1755int
b066401f 1756pp_remaining_character_count_for_line (pretty_printer *pp)
b6fe0bb8 1757{
025311c4 1758 return pp->maximum_length - pp_buffer (pp)->line_length;
b6fe0bb8
GDR
1759}
1760
1761
1762/* Format a message into BUFFER a la printf. */
1763void
1764pp_printf (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 = &ap;
1772 text.format_spec = msg;
39ce81c9
ZW
1773 pp_format (pp, &text);
1774 pp_output_formatted_text (pp);
b6fe0bb8
GDR
1775 va_end (ap);
1776}
1777
1778
1779/* Output MESSAGE verbatim into BUFFER. */
1780void
1781pp_verbatim (pretty_printer *pp, const char *msg, ...)
1782{
1783 text_info text;
1784 va_list ap;
1785
1786 va_start (ap, msg);
1787 text.err_no = errno;
1788 text.args_ptr = &ap;
1789 text.format_spec = msg;
1790 pp_format_verbatim (pp, &text);
1791 va_end (ap);
1792}
1793
1794
1795
1796/* Have PRETTY-PRINTER start a new line. */
1797void
b066401f 1798pp_newline (pretty_printer *pp)
b6fe0bb8 1799{
025311c4 1800 obstack_1grow (pp_buffer (pp)->obstack, '\n');
c4669594 1801 pp_needs_newline (pp) = false;
025311c4 1802 pp_buffer (pp)->line_length = 0;
b6fe0bb8
GDR
1803}
1804
1805/* Have PRETTY-PRINTER add a CHARACTER. */
1806void
b066401f 1807pp_character (pretty_printer *pp, int c)
b6fe0bb8
GDR
1808{
1809 if (pp_is_wrapping_line (pp)
ddd0fd17
LH
1810 /* If printing UTF-8, don't wrap in the middle of a sequence. */
1811 && (((unsigned int) c) & 0xC0) != 0x80
b6fe0bb8
GDR
1812 && pp_remaining_character_count_for_line (pp) <= 0)
1813 {
1814 pp_newline (pp);
1815 if (ISSPACE (c))
1816 return;
1817 }
025311c4
GDR
1818 obstack_1grow (pp_buffer (pp)->obstack, c);
1819 ++pp_buffer (pp)->line_length;
b6fe0bb8
GDR
1820}
1821
1822/* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
1823 be line-wrapped if in appropriate mode. */
1824void
b066401f 1825pp_string (pretty_printer *pp, const char *str)
b6fe0bb8 1826{
41d9f1e0
MLI
1827 gcc_checking_assert (str);
1828 pp_maybe_wrap_text (pp, str, str + strlen (str));
b6fe0bb8
GDR
1829}
1830
3f0177e7
MS
1831/* Append the leading N characters of STRING to the output area of
1832 PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
1833 Setting N = -1 is as if N were set to strlen (STRING). The STRING
1834 may be line-wrapped if in appropriate mode. */
1835static void
1836pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
1837{
1838 gcc_checking_assert (str);
1839
1840 const char *last = str;
1841 const char *ps;
1842
1843 /* Compute the length if not specified. */
1844 if (n == (size_t) -1)
1845 n = strlen (str);
1846
1847 for (ps = str; n; ++ps, --n)
1848 {
1849 if (ISPRINT (*ps))
1850 continue;
1851
ddd0fd17
LH
1852 /* Don't escape a valid UTF-8 extended char. */
1853 const unsigned char *ups = (const unsigned char *) ps;
1854 if (*ups & 0x80)
1855 {
1856 unsigned int extended_char;
1857 const int valid_utf8_len = decode_utf8_char (ups, n, &extended_char);
1858 if (valid_utf8_len > 0)
1859 {
1860 ps += valid_utf8_len - 1;
1861 n -= valid_utf8_len - 1;
1862 continue;
1863 }
1864 }
1865
3f0177e7 1866 if (last < ps)
ddd0fd17 1867 pp_maybe_wrap_text (pp, last, ps);
3f0177e7
MS
1868
1869 /* Append the hexadecimal value of the character. Allocate a buffer
1870 that's large enough for a 32-bit char plus the hex prefix. */
1871 char buf [11];
1872 int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
1873 pp_maybe_wrap_text (pp, buf, buf + n);
1874 last = ps + 1;
1875 }
1876
1877 pp_maybe_wrap_text (pp, last, ps);
1878}
1879
471854f8 1880/* Maybe print out a whitespace if needed. */
b6fe0bb8 1881
b9b44fb9 1882void
b066401f 1883pp_maybe_space (pretty_printer *pp)
b9b44fb9 1884{
b066401f 1885 if (pp->padding != pp_none)
b9b44fb9
GDR
1886 {
1887 pp_space (pp);
b066401f 1888 pp->padding = pp_none;
b9b44fb9
GDR
1889 }
1890}
0fc80001
GDR
1891
1892// Add a newline to the pretty printer PP and flush formatted text.
1893
1894void
1895pp_newline_and_flush (pretty_printer *pp)
1896{
1897 pp_newline (pp);
1898 pp_flush (pp);
1899 pp_needs_newline (pp) = false;
1900}
1901
1902// Add a newline to the pretty printer PP, followed by indentation.
1903
1904void
1905pp_newline_and_indent (pretty_printer *pp, int n)
1906{
1907 pp_indentation (pp) += n;
1908 pp_newline (pp);
1909 pp_indent (pp);
1910 pp_needs_newline (pp) = false;
1911}
1912
1913// Add separator C, followed by a single whitespace.
1914
1915void
1916pp_separate_with (pretty_printer *pp, char c)
1917{
1918 pp_character (pp, c);
1919 pp_space (pp);
1920}
1921
ce95abc4
DM
1922/* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
1923 using the "quote" color. */
1924
1925void
1926pp_begin_quote (pretty_printer *pp, bool show_color)
1927{
1928 pp_string (pp, open_quote);
1929 pp_string (pp, colorize_start (show_color, "quote"));
1930}
1931
1932/* If SHOW_COLOR is true, stop colorizing.
1933 Add a localized close quote. */
1934
1935void
1936pp_end_quote (pretty_printer *pp, bool show_color)
1937{
1938 pp_string (pp, colorize_stop (show_color));
1939 pp_string (pp, close_quote);
1940}
1941
a3af5087
JM
1942\f
1943/* The string starting at P has LEN (at least 1) bytes left; if they
1944 start with a valid UTF-8 sequence, return the length of that
1945 sequence and set *VALUE to the value of that sequence, and
1946 otherwise return 0 and set *VALUE to (unsigned int) -1. */
1947
1948static int
1949decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
1950{
1951 unsigned int t = *p;
1952
1953 if (len == 0)
1954 abort ();
1955 if (t & 0x80)
1956 {
1957 size_t utf8_len = 0;
1958 unsigned int ch;
1959 size_t i;
1960 for (t = *p; t & 0x80; t <<= 1)
1961 utf8_len++;
1962
1963 if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
1964 {
1965 *value = (unsigned int) -1;
1966 return 0;
1967 }
1968 ch = *p & ((1 << (7 - utf8_len)) - 1);
1969 for (i = 1; i < utf8_len; i++)
1970 {
1971 unsigned int u = p[i];
1972 if ((u & 0xC0) != 0x80)
1973 {
1974 *value = (unsigned int) -1;
1975 return 0;
1976 }
1977 ch = (ch << 6) | (u & 0x3F);
1978 }
1979 if ( (ch <= 0x7F && utf8_len > 1)
1980 || (ch <= 0x7FF && utf8_len > 2)
1981 || (ch <= 0xFFFF && utf8_len > 3)
1982 || (ch <= 0x1FFFFF && utf8_len > 4)
1983 || (ch <= 0x3FFFFFF && utf8_len > 5)
1984 || (ch >= 0xD800 && ch <= 0xDFFF))
1985 {
1986 *value = (unsigned int) -1;
1987 return 0;
1988 }
1989 *value = ch;
1990 return utf8_len;
1991 }
1992 else
1993 {
1994 *value = t;
1995 return 1;
1996 }
1997}
1998
ab9b814d
JM
1999/* Allocator for identifier_to_locale and corresponding function to
2000 free memory. */
2001
2002void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
2003void (*identifier_to_locale_free) (void *) = free;
2004
a3af5087
JM
2005/* Given IDENT, an identifier in the internal encoding, return a
2006 version of IDENT suitable for diagnostics in the locale character
ab9b814d
JM
2007 set: either IDENT itself, or a string, allocated using
2008 identifier_to_locale_alloc, converted to the locale character set
2009 and using escape sequences if not representable in the locale
2010 character set or containing control characters or invalid byte
2011 sequences. Existing backslashes in IDENT are not doubled, so the
2012 result may not uniquely specify the contents of an arbitrary byte
2013 sequence identifier. */
a3af5087
JM
2014
2015const char *
2016identifier_to_locale (const char *ident)
2017{
2018 const unsigned char *uid = (const unsigned char *) ident;
2019 size_t idlen = strlen (ident);
2020 bool valid_printable_utf8 = true;
2021 bool all_ascii = true;
2022 size_t i;
2023
2024 for (i = 0; i < idlen;)
2025 {
2026 unsigned int c;
2027 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2028 if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
2029 {
2030 valid_printable_utf8 = false;
2031 break;
2032 }
2033 if (utf8_len > 1)
2034 all_ascii = false;
2035 i += utf8_len;
2036 }
2037
2038 /* If IDENT contains invalid UTF-8 sequences (which may occur with
2039 attributes putting arbitrary byte sequences in identifiers), or
2040 control characters, we use octal escape sequences for all bytes
2041 outside printable ASCII. */
2042 if (!valid_printable_utf8)
2043 {
ab9b814d 2044 char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
a3af5087
JM
2045 char *p = ret;
2046 for (i = 0; i < idlen; i++)
2047 {
2048 if (uid[i] > 0x1F && uid[i] < 0x7F)
2049 *p++ = uid[i];
2050 else
2051 {
2052 sprintf (p, "\\%03o", uid[i]);
2053 p += 4;
2054 }
2055 }
2056 *p = 0;
2057 return ret;
2058 }
2059
2060 /* Otherwise, if it is valid printable ASCII, or printable UTF-8
2061 with the locale character set being UTF-8, IDENT is used. */
2062 if (all_ascii || locale_utf8)
2063 return ident;
2064
2065 /* Otherwise IDENT is converted to the locale character set if
2066 possible. */
2067#if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
2068 if (locale_encoding != NULL)
2069 {
2070 iconv_t cd = iconv_open (locale_encoding, "UTF-8");
2071 bool conversion_ok = true;
2072 char *ret = NULL;
2073 if (cd != (iconv_t) -1)
2074 {
2075 size_t ret_alloc = 4 * idlen + 1;
2076 for (;;)
2077 {
2078 /* Repeat the whole conversion process as needed with
2079 larger buffers so non-reversible transformations can
2080 always be detected. */
2081 ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
2082 char *outbuf;
2083 size_t inbytesleft = idlen;
2084 size_t outbytesleft = ret_alloc - 1;
2085 size_t iconv_ret;
2086
ab9b814d 2087 ret = (char *) identifier_to_locale_alloc (ret_alloc);
a3af5087
JM
2088 outbuf = ret;
2089
2090 if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
2091 {
2092 conversion_ok = false;
2093 break;
2094 }
2095
2096 iconv_ret = iconv (cd, &inbuf, &inbytesleft,
2097 &outbuf, &outbytesleft);
2098 if (iconv_ret == (size_t) -1 || inbytesleft != 0)
2099 {
2100 if (errno == E2BIG)
2101 {
2102 ret_alloc *= 2;
ab9b814d 2103 identifier_to_locale_free (ret);
a3af5087
JM
2104 ret = NULL;
2105 continue;
2106 }
2107 else
2108 {
2109 conversion_ok = false;
2110 break;
2111 }
2112 }
2113 else if (iconv_ret != 0)
2114 {
2115 conversion_ok = false;
2116 break;
2117 }
2118 /* Return to initial shift state. */
2119 if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
2120 {
2121 if (errno == E2BIG)
2122 {
2123 ret_alloc *= 2;
ab9b814d 2124 identifier_to_locale_free (ret);
a3af5087
JM
2125 ret = NULL;
2126 continue;
2127 }
2128 else
2129 {
2130 conversion_ok = false;
2131 break;
2132 }
2133 }
2134 *outbuf = 0;
2135 break;
2136 }
2137 iconv_close (cd);
2138 if (conversion_ok)
2139 return ret;
2140 }
2141 }
2142#endif
2143
2144 /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */
2145 {
ab9b814d 2146 char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
a3af5087
JM
2147 char *p = ret;
2148 for (i = 0; i < idlen;)
2149 {
2150 unsigned int c;
2151 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2152 if (utf8_len == 1)
2153 *p++ = uid[i];
2154 else
2155 {
2156 sprintf (p, "\\U%08x", c);
2157 p += 10;
2158 }
2159 i += utf8_len;
2160 }
2161 *p = 0;
2162 return ret;
2163 }
2164}
4ccab56d 2165
d2608235
DM
2166/* Support for encoding URLs.
2167 See egmontkob/Hyperlinks_in_Terminal_Emulators.md
2168 ( https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda ).
2169
2170 > A hyperlink is opened upon encountering an OSC 8 escape sequence with
2171 > the target URI. The syntax is
2172 >
2173 > OSC 8 ; params ; URI ST
2174 >
2175 > A hyperlink is closed with the same escape sequence, omitting the
2176 > parameters and the URI but keeping the separators:
2177 >
2178 > OSC 8 ; ; ST
2179 >
ae169f9e
TB
2180 > OSC (operating system command) is typically ESC ].
2181
2182 Use BEL instead of ST, as that is currently rendered better in some
2183 terminal emulators that don't support OSC 8, like konsole. */
d2608235
DM
2184
2185/* If URL-printing is enabled, write an "open URL" escape sequence to PP
2186 for the given URL. */
2187
2188void
2189pp_begin_url (pretty_printer *pp, const char *url)
2190{
458c8d64 2191 switch (pp->url_format)
691eeb65
JJ
2192 {
2193 case URL_FORMAT_NONE:
2194 break;
2195 case URL_FORMAT_ST:
2196 pp_string (pp, "\33]8;;");
2197 pp_string (pp, url);
2198 pp_string (pp, "\33\\");
2199 break;
2200 case URL_FORMAT_BEL:
2201 pp_string (pp, "\33]8;;");
2202 pp_string (pp, url);
2203 pp_string (pp, "\a");
2204 break;
2205 default:
2206 gcc_unreachable ();
2207 }
2208}
2209
2210/* Helper function for pp_end_url and pp_format, return the "close URL" escape
2211 sequence string. */
2212
2213static const char *
2214get_end_url_string (pretty_printer *pp)
2215{
2216 switch (pp->url_format)
2217 {
2218 case URL_FORMAT_NONE:
2219 return "";
2220 case URL_FORMAT_ST:
2221 return "\33]8;;\33\\";
2222 case URL_FORMAT_BEL:
2223 return "\33]8;;\a";
2224 default:
2225 gcc_unreachable ();
2226 }
d2608235
DM
2227}
2228
2229/* If URL-printing is enabled, write a "close URL" escape sequence to PP. */
2230
2231void
2232pp_end_url (pretty_printer *pp)
2233{
691eeb65
JJ
2234 if (pp->url_format != URL_FORMAT_NONE)
2235 pp_string (pp, get_end_url_string (pp));
d2608235
DM
2236}
2237
4ccab56d
DM
2238#if CHECKING_P
2239
2240namespace selftest {
2241
2242/* Smoketest for pretty_printer. */
2243
2244static void
2245test_basic_printing ()
2246{
2247 pretty_printer pp;
2248 pp_string (&pp, "hello");
2249 pp_space (&pp);
2250 pp_string (&pp, "world");
2251
2252 ASSERT_STREQ ("hello world", pp_formatted_text (&pp));
2253}
2254
2255/* Helper function for testing pp_format.
2256 Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2257 prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */
2258
2259static void
09765e3a
DM
2260assert_pp_format_va (const location &loc, const char *expected,
2261 bool show_color, const char *fmt, va_list *ap)
4ccab56d
DM
2262{
2263 pretty_printer pp;
2264 text_info ti;
2265 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2266
2267 ti.format_spec = fmt;
2268 ti.args_ptr = ap;
2269 ti.err_no = 0;
2270 ti.x_data = NULL;
2271 ti.m_richloc = &rich_loc;
2272
2273 pp_show_color (&pp) = show_color;
2274 pp_format (&pp, &ti);
2275 pp_output_formatted_text (&pp);
09765e3a 2276 ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
4ccab56d
DM
2277}
2278
2279/* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2280 prints EXPECTED, with show_color disabled. */
2281
2282static void
09765e3a
DM
2283assert_pp_format (const location &loc, const char *expected,
2284 const char *fmt, ...)
4ccab56d
DM
2285{
2286 va_list ap;
2287
2288 va_start (ap, fmt);
09765e3a 2289 assert_pp_format_va (loc, expected, false, fmt, &ap);
4ccab56d
DM
2290 va_end (ap);
2291}
2292
2293/* As above, but with colorization enabled. */
2294
2295static void
09765e3a
DM
2296assert_pp_format_colored (const location &loc, const char *expected,
2297 const char *fmt, ...)
4ccab56d 2298{
2fe00b1f
DM
2299 /* The tests of colorization assume the default color scheme.
2300 If GCC_COLORS is set, then the colors have potentially been
2301 overridden; skip the test. */
2302 if (getenv ("GCC_COLORS"))
2303 return;
2304
4ccab56d
DM
2305 va_list ap;
2306
2307 va_start (ap, fmt);
09765e3a 2308 assert_pp_format_va (loc, expected, true, fmt, &ap);
4ccab56d
DM
2309 va_end (ap);
2310}
2311
09765e3a
DM
2312/* Helper function for calling testing pp_format,
2313 by calling assert_pp_format with various numbers of arguments.
2314 These exist mostly to avoid having to write SELFTEST_LOCATION
2315 throughout test_pp_format. */
2316
2317#define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \
2318 SELFTEST_BEGIN_STMT \
2319 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2320 (ARG1)); \
2321 SELFTEST_END_STMT
2322
2323#define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \
2324 SELFTEST_BEGIN_STMT \
2325 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2326 (ARG1), (ARG2)); \
2327 SELFTEST_END_STMT
2328
2329#define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \
2330 SELFTEST_BEGIN_STMT \
2331 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2332 (ARG1), (ARG2), (ARG3)); \
2333 SELFTEST_END_STMT
2334
4ccab56d
DM
2335/* Verify that pp_format works, for various format codes. */
2336
2337static void
2338test_pp_format ()
2339{
2340 /* Avoid introducing locale-specific differences in the results
2341 by hardcoding open_quote and close_quote. */
dbf96d49 2342 auto_fix_quotes fix_quotes;
4ccab56d
DM
2343
2344 /* Verify that plain text is passed through unchanged. */
09765e3a 2345 assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted");
4ccab56d
DM
2346
2347 /* Verify various individual format codes, in the order listed in the
2348 comment for pp_format above. For each code, we append a second
2349 argument with a known bit pattern (0x12345678), to ensure that we
2350 are consuming arguments correctly. */
09765e3a
DM
2351 ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678);
2352 ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678);
2353 ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678);
2354 ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678);
2355 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678);
2356 ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678);
2357 ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678);
2358 ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678);
2359 ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678);
2360 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe,
2361 0x12345678);
2362 ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678);
2363 ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678);
2364 ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678);
2365 ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678);
2366 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe,
2367 0x12345678);
2368 ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678);
2369 ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678);
2370 ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10,
2371 0x12345678);
2372 ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
2373 ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
2374 0x12345678);
204839e7 2375 ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
09765e3a
DM
2376 ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
2377 ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
2378 0x12345678);
86ef85d3
MS
2379
2380 /* Not nul-terminated. */
2381 char arr[5] = { '1', '2', '3', '4', '5' };
2382 ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678);
2383 ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678);
2384 ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678);
2385
914bc2b9
DM
2386 /* We can't test for %p; the pointer is printed in an implementation-defined
2387 manner. */
09765e3a
DM
2388 ASSERT_PP_FORMAT_2 ("normal colored normal 12345678",
2389 "normal %rcolored%R normal %x",
2390 "error", 0x12345678);
4ccab56d 2391 assert_pp_format_colored
09765e3a
DM
2392 (SELFTEST_LOCATION,
2393 "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678",
4ccab56d
DM
2394 "normal %rcolored%R normal %x", "error", 0x12345678);
2395 /* TODO:
2396 %m: strerror(text->err_no) - does not consume a value from args_ptr. */
09765e3a
DM
2397 ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678);
2398 ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678);
2399 ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678);
2400 ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678);
2401 ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678);
2402 ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678);
4ccab56d
DM
2403
2404 /* Verify flag 'q'. */
09765e3a
DM
2405 ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678);
2406 assert_pp_format_colored (SELFTEST_LOCATION,
2407 "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
4ccab56d 2408 "foo", 0x12345678);
4bc1899b
DM
2409 /* Verify "%@". */
2410 {
2411 diagnostic_event_id_t first (2);
2412 diagnostic_event_id_t second (7);
2413
2414 ASSERT_PP_FORMAT_2 ("first `free' at (3); second `free' at (8)",
2415 "first %<free%> at %@; second %<free%> at %@",
2416 &first, &second);
2417 assert_pp_format_colored
2418 (SELFTEST_LOCATION,
2419 "first `\e[01m\e[Kfree\e[m\e[K' at \e[01;36m\e[K(3)\e[m\e[K;"
2420 " second `\e[01m\e[Kfree\e[m\e[K' at \e[01;36m\e[K(8)\e[m\e[K",
2421 "first %<free%> at %@; second %<free%> at %@",
2422 &first, &second);
2423 }
4ccab56d 2424
975672f3
PK
2425 /* Verify %Z. */
2426 int v[] = { 1, 2, 3 };
2427 ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
2428
2429 int v2[] = { 0 };
2430 ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
2431
4ccab56d 2432 /* Verify that combinations work, along with unformatted text. */
09765e3a
DM
2433 assert_pp_format (SELFTEST_LOCATION,
2434 "the quick brown fox jumps over the lazy dog",
4ccab56d
DM
2435 "the %s %s %s jumps over the %s %s",
2436 "quick", "brown", "fox", "lazy", "dog");
09765e3a
DM
2437 assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7);
2438 assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10",
4ccab56d 2439 "problem with %qs at line %i", "bar", 10);
4ccab56d
DM
2440}
2441
553a316b
DM
2442/* A subclass of pretty_printer for use by test_prefixes_and_wrapping. */
2443
2444class test_pretty_printer : public pretty_printer
2445{
2446 public:
2447 test_pretty_printer (enum diagnostic_prefixing_rule_t rule,
2448 int max_line_length)
2449 {
2450 pp_set_prefix (this, xstrdup ("PREFIX: "));
2451 wrapping.rule = rule;
2452 pp_set_line_maximum_length (this, max_line_length);
2453 }
2454};
2455
2456/* Verify that the various values of enum diagnostic_prefixing_rule_t work
2457 as expected, with and without line wrapping. */
2458
2459static void
2460test_prefixes_and_wrapping ()
2461{
2462 /* Tests of the various prefixing rules, without wrapping.
2463 Newlines embedded in pp_string don't affect it; we have to
2464 explicitly call pp_newline. */
2465 {
2466 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 0);
2467 pp_string (&pp, "the quick brown fox");
2468 pp_newline (&pp);
2469 pp_string (&pp, "jumps over the lazy dog");
2470 pp_newline (&pp);
2471 ASSERT_STREQ (pp_formatted_text (&pp),
2472 "PREFIX: the quick brown fox\n"
2473 " jumps over the lazy dog\n");
2474 }
2475 {
2476 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 0);
2477 pp_string (&pp, "the quick brown fox");
2478 pp_newline (&pp);
2479 pp_string (&pp, "jumps over the lazy dog");
2480 pp_newline (&pp);
2481 ASSERT_STREQ (pp_formatted_text (&pp),
2482 "the quick brown fox\n"
2483 "jumps over the lazy dog\n");
2484 }
2485 {
2486 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 0);
2487 pp_string (&pp, "the quick brown fox");
2488 pp_newline (&pp);
2489 pp_string (&pp, "jumps over the lazy dog");
2490 pp_newline (&pp);
2491 ASSERT_STREQ (pp_formatted_text (&pp),
2492 "PREFIX: the quick brown fox\n"
2493 "PREFIX: jumps over the lazy dog\n");
2494 }
2495
2496 /* Tests of the various prefixing rules, with wrapping. */
2497 {
2498 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 20);
2499 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2500 pp_newline (&pp);
2501 pp_string (&pp, "able was I ere I saw elba");
2502 pp_newline (&pp);
2503 ASSERT_STREQ (pp_formatted_text (&pp),
2504 "PREFIX: the quick \n"
2505 " brown fox jumps \n"
2506 " over the lazy \n"
2507 " dog\n"
2508 " able was I ere I \n"
2509 " saw elba\n");
2510 }
2511 {
2512 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 20);
2513 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2514 pp_newline (&pp);
2515 pp_string (&pp, "able was I ere I saw elba");
2516 pp_newline (&pp);
2517 ASSERT_STREQ (pp_formatted_text (&pp),
2518 "the quick brown fox \n"
2519 "jumps over the lazy \n"
2520 "dog\n"
2521 "able was I ere I \n"
2522 "saw elba\n");
2523 }
2524 {
2525 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 20);
2526 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2527 pp_newline (&pp);
2528 pp_string (&pp, "able was I ere I saw elba");
2529 pp_newline (&pp);
2530 ASSERT_STREQ (pp_formatted_text (&pp),
2531 "PREFIX: the quick brown fox jumps over the lazy dog\n"
2532 "PREFIX: able was I ere I saw elba\n");
2533 }
2534
2535}
2536
d2608235
DM
2537/* Verify that URL-printing works as expected. */
2538
2539void
2540test_urls ()
2541{
2542 {
2543 pretty_printer pp;
458c8d64 2544 pp.url_format = URL_FORMAT_NONE;
d2608235
DM
2545 pp_begin_url (&pp, "http://example.com");
2546 pp_string (&pp, "This is a link");
2547 pp_end_url (&pp);
2548 ASSERT_STREQ ("This is a link",
2549 pp_formatted_text (&pp));
2550 }
2551
2552 {
2553 pretty_printer pp;
458c8d64
BE
2554 pp.url_format = URL_FORMAT_ST;
2555 pp_begin_url (&pp, "http://example.com");
2556 pp_string (&pp, "This is a link");
2557 pp_end_url (&pp);
2558 ASSERT_STREQ ("\33]8;;http://example.com\33\\This is a link\33]8;;\33\\",
2559 pp_formatted_text (&pp));
2560 }
2561
2562 {
2563 pretty_printer pp;
2564 pp.url_format = URL_FORMAT_BEL;
d2608235
DM
2565 pp_begin_url (&pp, "http://example.com");
2566 pp_string (&pp, "This is a link");
2567 pp_end_url (&pp);
ae169f9e 2568 ASSERT_STREQ ("\33]8;;http://example.com\aThis is a link\33]8;;\a",
d2608235
DM
2569 pp_formatted_text (&pp));
2570 }
2571}
2572
ddd0fd17
LH
2573/* Test multibyte awareness. */
2574static void test_utf8 ()
2575{
2576
2577 /* Check that pp_quoted_string leaves valid UTF-8 alone. */
2578 {
2579 pretty_printer pp;
2580 const char *s = "\xf0\x9f\x98\x82";
2581 pp_quoted_string (&pp, s);
2582 ASSERT_STREQ (pp_formatted_text (&pp), s);
2583 }
2584
2585 /* Check that pp_quoted_string escapes non-UTF-8 nonprintable bytes. */
2586 {
2587 pretty_printer pp;
2588 pp_quoted_string (&pp, "\xf0!\x9f\x98\x82");
2589 ASSERT_STREQ (pp_formatted_text (&pp),
2590 "\\xf0!\\x9f\\x98\\x82");
2591 }
2592
2593 /* Check that pp_character will line-wrap at the beginning of a UTF-8
2594 sequence, but not in the middle. */
2595 {
2596 pretty_printer pp (3);
2597 const char s[] = "---\xf0\x9f\x98\x82";
2598 for (int i = 0; i != sizeof (s) - 1; ++i)
2599 pp_character (&pp, s[i]);
2600 pp_newline (&pp);
2601 for (int i = 1; i != sizeof (s) - 1; ++i)
2602 pp_character (&pp, s[i]);
2603 pp_character (&pp, '-');
2604 ASSERT_STREQ (pp_formatted_text (&pp),
2605 "---\n"
2606 "\xf0\x9f\x98\x82\n"
2607 "--\xf0\x9f\x98\x82\n"
2608 "-");
2609 }
2610
2611}
2612
4ccab56d
DM
2613/* Run all of the selftests within this file. */
2614
2615void
2616pretty_print_c_tests ()
2617{
2618 test_basic_printing ();
2619 test_pp_format ();
553a316b 2620 test_prefixes_and_wrapping ();
d2608235 2621 test_urls ();
ddd0fd17 2622 test_utf8 ();
4ccab56d
DM
2623}
2624
2625} // namespace selftest
2626
2627#endif /* CHECKING_P */