c++: retval dtor on rethrow [PR112301]
[official-gcc.git] / gcc / pretty-print.cc
blob80780cfd7b8b7eb760563abbf9af83d90357241e
1 /* Various declarations for language-independent pretty-print subroutines.
2 Copyright (C) 2003-2023 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "intl.h"
25 #include "pretty-print.h"
26 #include "diagnostic-color.h"
27 #include "diagnostic-event-id.h"
28 #include "selftest.h"
30 #if HAVE_ICONV
31 #include <iconv.h>
32 #endif
34 #ifdef __MINGW32__
36 /* Replacement for fputs() that handles ANSI escape codes on Windows NT.
37 Contributed by: Liu Hao (lh_mouse at 126 dot com)
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. */
42 #include <io.h>
43 #define WIN32_LEAN_AND_MEAN 1
44 #include <windows.h>
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)
51 size_t rem = n;
52 DWORD step;
54 while (rem != 0)
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;
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)
78 int c;
79 const char *r = str;
80 int escaped = 0;
82 for (;;)
84 c = (unsigned char) *r;
85 if (c == 0)
87 /* Not found. */
88 return 0;
90 if (escaped && 0x40 <= c && c <= 0x5F)
92 /* Found (case 1). */
93 *prefix_len = 2;
94 *head = r + 1;
95 return c;
97 if (0x80 <= c && c <= 0x9F)
99 /* Found (case 2). */
100 *prefix_len = 1;
101 *head = r + 1;
102 return c - 0x40;
104 ++r;
105 escaped = c == 0x1B;
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)
116 int c;
117 const char *r = str;
119 for (;;)
121 c = (unsigned char) *r;
122 if (c == 0)
124 /* Not found. */
125 return 0;
127 if (0x40 <= c && c <= 0x7E)
129 /* Found. */
130 *term = r;
131 return c;
133 ++r;
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)
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;
157 switch (MAKEWORD (esc_code, *esc_term))
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
166 n1 = strtol (esc_head, &eptr, 10);
167 if (eptr != esc_term)
168 break;
171 if (GetConsoleScreenBufferInfo (h, &sb))
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);
181 break;
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
190 n1 = strtol (esc_head, &eptr, 10);
191 if (eptr != esc_term)
192 break;
195 if (GetConsoleScreenBufferInfo (h, &sb))
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);
205 break;
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
214 n1 = strtol (esc_head, &eptr, 10);
215 if (eptr != esc_term)
216 break;
219 if (GetConsoleScreenBufferInfo (h, &sb))
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);
229 break;
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
238 n1 = strtol (esc_head, &eptr, 10);
239 if (eptr != esc_term)
240 break;
243 if (GetConsoleScreenBufferInfo (h, &sb))
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);
253 break;
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
262 n1 = strtol (esc_head, &eptr, 10);
263 if (eptr != esc_term)
264 break;
267 if (GetConsoleScreenBufferInfo (h, &sb))
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);
278 break;
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
287 n1 = strtol (esc_head, &eptr, 10);
288 if (eptr != esc_term)
289 break;
292 if (GetConsoleScreenBufferInfo (h, &sb))
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);
303 break;
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
312 n1 = strtol (esc_head, &eptr, 10);
313 if (eptr != esc_term)
314 break;
317 if (GetConsoleScreenBufferInfo (h, &sb))
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);
330 break;
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)
340 /* Both parameters are omitted and set to 1 by default. */
341 n1 = 1;
342 n2 = 1;
344 else if (!(delim = (char *) memchr (esc_head, ';',
345 esc_term - esc_head)))
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;
354 else
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;
366 if (GetConsoleScreenBufferInfo (h, &sb))
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);
394 break;
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
405 n1 = strtol (esc_head, &eptr, 10);
406 if (eptr != esc_term)
407 break;
410 if (GetConsoleScreenBufferInfo (h, &sb))
412 /* The cursor is not necessarily in the console window, which
413 makes the behavior of this code harder to define. */
414 switch (n1)
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;
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);
452 break;
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
463 n1 = strtol (esc_head, &eptr, 10);
464 if (eptr != esc_term)
465 break;
468 if (GetConsoleScreenBufferInfo (h, &sb))
470 switch (n1)
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;
490 FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step);
491 FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step);
493 break;
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)
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;
508 param = esc_head;
511 /* Parse a parameter. */
512 n1 = strtol (param, &eptr, 10);
513 if (*eptr != ';' && eptr != esc_term)
514 goto sgr_set_it;
516 switch (n1)
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;
632 /* Prepare the next parameter. */
633 param = eptr + 1;
635 while (param != esc_term);
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))
642 attrib_add |= sb.wAttributes & ~attrib_rm;
644 if (attrib_add & COMMON_LVB_REVERSE_VIDEO)
646 /* COMMON_LVB_REVERSE_VIDEO is only effective for DBCS.
647 * Swap foreground and background colors by hand.
649 attrib_add = (attrib_add & 0xFF00)
650 | ((attrib_add & 0x00F0) >> 4)
651 | ((attrib_add & 0x000F) << 4);
652 attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
654 SetConsoleTextAttribute (h, attrib_add);
655 break;
660 mingw_ansi_fputs (const char *str, FILE *fp)
662 const char *read = str;
663 HANDLE h;
664 DWORD mode;
665 int esc_code, prefix_len;
666 const char *esc_head, *esc_term;
668 h = (HANDLE) _get_osfhandle (_fileno (fp));
669 if (h == INVALID_HANDLE_VALUE)
670 return EOF;
672 /* Don't mess up stdio functions with Windows APIs. */
673 fflush (fp);
675 if (GetConsoleMode (h, &mode))
676 /* If it is a console, translate ANSI escape codes as needed. */
677 for (;;)
679 if ((esc_code = find_esc_head (&prefix_len, &esc_head, read)) == 0)
681 /* Write all remaining characters, then exit. */
682 write_all (h, read, strlen (read));
683 break;
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;
694 else
695 /* If it is not a console, write everything as-is. */
696 write_all (h, read, strlen (read));
698 return 1;
701 #endif /* __MINGW32__ */
703 static int
704 decode_utf8_char (const unsigned char *, size_t len, unsigned int *);
705 static void pp_quoted_string (pretty_printer *, const char *, size_t = -1);
707 /* Overwrite the given location/range within this text_info's rich_location.
708 For use e.g. when implementing "+" in client format decoders. */
710 void
711 text_info::set_location (unsigned int idx, location_t loc,
712 enum range_display_kind range_display_kind)
714 gcc_checking_assert (m_richloc);
715 m_richloc->set_range (idx, loc, range_display_kind);
718 location_t
719 text_info::get_location (unsigned int index_of_location) const
721 gcc_checking_assert (m_richloc);
723 if (index_of_location == 0)
724 return m_richloc->get_loc ();
725 else
726 return UNKNOWN_LOCATION;
729 // Default construct an output buffer.
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)
741 obstack_init (&formatted_obstack);
742 obstack_init (&chunk_obstack);
745 // Release resources owned by an output buffer at the end of lifetime.
747 output_buffer::~output_buffer ()
749 obstack_free (&chunk_obstack, NULL);
750 obstack_free (&formatted_obstack, NULL);
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) \
761 case 0: \
762 pp_scalar (PP, "%" F, va_arg (ARG, T)); \
763 break; \
765 case 1: \
766 pp_scalar (PP, "%l" F, va_arg (ARG, long T)); \
767 break; \
769 case 2: \
770 pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \
771 break; \
773 default: \
774 break; \
776 while (0)
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)
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
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);
803 /* Clear PRETTY-PRINTER's output state. */
804 static inline void
805 pp_clear_state (pretty_printer *pp)
807 pp->emitted_prefix = false;
808 pp_indentation (pp) = 0;
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<N, T> &x)
816 if (x.is_constant ())
817 pp_wide_integer (pp, x.coeffs[0]);
818 else
820 pp_left_bracket (pp);
821 for (unsigned int i = 0; i < N; ++i)
823 if (i != 0)
824 pp_comma (pp);
825 pp_wide_integer (pp, x.coeffs[i]);
827 pp_right_bracket (pp);
831 template void pp_wide_integer (pretty_printer *, const poly_uint16 &);
832 template void pp_wide_integer (pretty_printer *, const poly_int64 &);
833 template void pp_wide_integer (pretty_printer *, const poly_uint64 &);
835 /* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */
836 void
837 pp_write_text_to_stream (pretty_printer *pp)
839 const char *text = pp_formatted_text (pp);
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);
848 /* As pp_write_text_to_stream, but for GraphViz label output.
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.
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. */
857 void
858 pp_write_text_as_dot_label_to_stream (pretty_printer *pp, bool for_record)
860 const char *text = pp_formatted_text (pp);
861 const char *p = text;
862 FILE *fp = pp_buffer (pp)->stream;
864 for (;*p; p++)
866 bool escape_char;
867 switch (*p)
869 /* Print newlines as a left-aligned newline. */
870 case '\n':
871 fputs ("\\l", fp);
872 escape_char = true;
873 break;
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;
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;
897 default:
898 escape_char = false;
899 break;
902 if (escape_char)
903 fputc ('\\', fp);
905 fputc (*p, fp);
908 pp_clear_output_area (pp);
911 /* As pp_write_text_to_stream, but for GraphViz HTML-like strings.
913 Flush the formatted text of pretty-printer PP onto the attached stream,
914 escaping these characters
915 " & < >
916 using XML escape sequences.
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;");.
924 Experiments show that escaping "'" doesn't seem to be necessary. */
926 void
927 pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp)
929 const char *text = pp_formatted_text (pp);
930 const char *p = text;
931 FILE *fp = pp_buffer (pp)->stream;
933 for (;*p; p++)
935 switch (*p)
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;
950 default:
951 fputc (*p, fp);
952 break;
956 pp_clear_output_area (pp);
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)
963 bool wrapping_line = pp_is_wrapping_line (pp);
965 while (start != end)
967 /* Dump anything bordered by whitespaces. */
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;
979 if (start != end && ISBLANK (*start))
981 pp_space (pp);
982 ++start;
984 if (start != end && *start == '\n')
986 pp_newline (pp);
987 ++start;
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)
996 if (pp_is_wrapping_line (pp))
997 pp_wrap_text (pp, start, end);
998 else
999 pp_append_text (pp, start, end);
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)
1007 output_buffer_append_r (pp_buffer (pp), start, length);
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
1014 pp_indent (pretty_printer *pp)
1016 int n = pp_indentation (pp);
1017 int i;
1019 for (i = 0; i < n; ++i)
1020 pp_space (pp);
1023 static const char *get_end_url_string (pretty_printer *);
1025 /* The following format specifiers are recognized as being client independent:
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.
1033 %f: double
1034 %c: character.
1035 %s: string.
1036 %p: pointer (printed in a host-dependent manner).
1037 %r: if pp_show_color(pp), switch to color identified by const char *.
1038 %R: if pp_show_color(pp), reset color.
1039 %m: strerror(text->err_no) - does not consume a value from args_ptr.
1040 %%: '%'.
1041 %<: opening quote.
1042 %>: closing quote.
1043 %{: URL start. Consumes a const char * argument for the URL.
1044 %}: URL end. Does not consume any arguments.
1045 %': apostrophe (should only be used in untranslated messages;
1046 translations should use appropriate punctuation directly).
1047 %@: diagnostic_event_id_ptr, for which event_id->known_p () must be true.
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.
1051 Flag 'q': quote formatted text (must come immediately after '%').
1052 %Z: Requires two arguments - array of int, and len. Prints elements
1053 of the array.
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, %%,
1058 %<, %>, %} and %', which may not have a number, as they do not consume
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. */
1065 /* Formatting phases 1 and 2: render TEXT->format_spec plus
1066 text->m_args_ptr into a series of chunks in pp_buffer (PP)->args[].
1067 Phase 3 is in pp_output_formatted_text. */
1069 void
1070 pp_format (pretty_printer *pp, text_info *text)
1072 output_buffer *buffer = pp_buffer (pp);
1073 const char *p;
1074 const char **args;
1075 struct chunk_info *new_chunk_array;
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];
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;
1088 /* Formatting phase 1: split up TEXT->format_spec into chunks in
1089 pp_buffer (PP)->args[]. Even-numbered chunks are to be output
1090 verbatim, odd-numbered chunks are format specifiers.
1091 %m, %%, %<, %>, %} and %' are replaced with the appropriate text at
1092 this point. */
1094 memset (formatters, 0, sizeof formatters);
1096 for (p = text->m_format_spec; *p; )
1098 while (*p != '\0' && *p != '%')
1100 obstack_1grow (&buffer->chunk_obstack, *p);
1101 p++;
1104 if (*p == '\0')
1105 break;
1107 switch (*++p)
1109 case '\0':
1110 gcc_unreachable ();
1112 case '%':
1113 obstack_1grow (&buffer->chunk_obstack, '%');
1114 p++;
1115 continue;
1117 case '<':
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;
1128 case '>':
1130 const char *colorstr = colorize_stop (pp_show_color (pp));
1131 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
1133 /* FALLTHRU */
1134 case '\'':
1135 obstack_grow (&buffer->chunk_obstack,
1136 close_quote, strlen (close_quote));
1137 p++;
1138 continue;
1140 case '}':
1142 const char *endurlstr = get_end_url_string (pp);
1143 obstack_grow (&buffer->chunk_obstack, endurlstr,
1144 strlen (endurlstr));
1146 p++;
1147 continue;
1149 case 'R':
1151 const char *colorstr = colorize_stop (pp_show_color (pp));
1152 obstack_grow (&buffer->chunk_obstack, colorstr,
1153 strlen (colorstr));
1154 p++;
1155 continue;
1158 case 'm':
1160 const char *errstr = xstrerror (text->m_err_no);
1161 obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
1163 p++;
1164 continue;
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;
1174 if (ISDIGIT (*p))
1176 char *end;
1177 argno = strtoul (p, &end, 10) - 1;
1178 p = end;
1179 gcc_assert (*p == '$');
1180 p++;
1182 any_numbered = true;
1183 gcc_assert (!any_unnumbered);
1185 else
1187 argno = curarg++;
1188 any_unnumbered = true;
1189 gcc_assert (!any_numbered);
1191 gcc_assert (argno < PP_NL_ARGMAX);
1192 gcc_assert (!formatters[argno]);
1193 formatters[argno] = &args[chunk];
1196 obstack_1grow (&buffer->chunk_obstack, *p);
1197 p++;
1199 while (strchr ("qwl+#", p[-1]));
1201 if (p[-1] == '.')
1203 /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
1204 (where M == N + 1). */
1205 if (ISDIGIT (*p))
1209 obstack_1grow (&buffer->chunk_obstack, *p);
1210 p++;
1212 while (ISDIGIT (p[-1]));
1213 gcc_assert (p[-1] == 's');
1215 else
1217 gcc_assert (*p == '*');
1218 obstack_1grow (&buffer->chunk_obstack, '*');
1219 p++;
1221 if (ISDIGIT (*p))
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 == '$');
1230 p++;
1231 formatters[argno2] = formatters[argno];
1233 else
1235 gcc_assert (!any_numbered);
1236 formatters[argno+1] = formatters[argno];
1237 curarg++;
1239 gcc_assert (*p == 's');
1240 obstack_1grow (&buffer->chunk_obstack, 's');
1241 p++;
1244 if (*p == '\0')
1245 break;
1247 obstack_1grow (&buffer->chunk_obstack, '\0');
1248 gcc_assert (chunk < PP_NL_ARGMAX * 2);
1249 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
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;
1257 /* Set output to the argument obstack, and switch line-wrapping and
1258 prefixing off. */
1259 buffer->obstack = &buffer->chunk_obstack;
1260 const int old_line_length = buffer->line_length;
1261 old_wrapping_mode = pp_set_verbatim_wrapping (pp);
1263 /* Second phase. Replace each formatter with the formatted text it
1264 corresponds to. */
1266 for (argno = 0; formatters[argno]; argno++)
1268 int precision = 0;
1269 bool wide = false;
1270 bool plus = false;
1271 bool hash = false;
1272 bool quote = false;
1274 /* We do not attempt to enforce any ordering on the modifier
1275 characters. */
1277 for (p = *formatters[argno];; p++)
1279 switch (*p)
1281 case 'q':
1282 gcc_assert (!quote);
1283 quote = true;
1284 continue;
1286 case '+':
1287 gcc_assert (!plus);
1288 plus = true;
1289 continue;
1291 case '#':
1292 gcc_assert (!hash);
1293 hash = true;
1294 continue;
1296 case 'w':
1297 gcc_assert (!wide);
1298 wide = true;
1299 continue;
1301 case 'l':
1302 /* We don't support precision beyond that of "long long". */
1303 gcc_assert (precision < 2);
1304 precision++;
1305 continue;
1307 break;
1310 gcc_assert (!wide || precision == 0);
1312 if (quote)
1313 pp_begin_quote (pp, pp_show_color (pp));
1315 switch (*p)
1317 case 'r':
1318 pp_string (pp, colorize_start (pp_show_color (pp),
1319 va_arg (*text->m_args_ptr,
1320 const char *)));
1321 break;
1323 case 'c':
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->m_args_ptr, int);
1329 if (ISPRINT (chr) || !quote)
1330 pp_character (pp, chr);
1331 else
1333 const char str [2] = { chr, '\0' };
1334 pp_quoted_string (pp, str, 1);
1336 break;
1339 case 'd':
1340 case 'i':
1341 if (wide)
1342 pp_wide_integer (pp, va_arg (*text->m_args_ptr, HOST_WIDE_INT));
1343 else
1344 pp_integer_with_precision
1345 (pp, *text->m_args_ptr, precision, int, "d");
1346 break;
1348 case 'o':
1349 if (wide)
1350 pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
1351 va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
1352 else
1353 pp_integer_with_precision
1354 (pp, *text->m_args_ptr, precision, unsigned, "o");
1355 break;
1357 case 's':
1358 if (quote)
1359 pp_quoted_string (pp, va_arg (*text->m_args_ptr, const char *));
1360 else
1361 pp_string (pp, va_arg (*text->m_args_ptr, const char *));
1362 break;
1364 case 'p':
1365 pp_pointer (pp, va_arg (*text->m_args_ptr, void *));
1366 break;
1368 case 'u':
1369 if (wide)
1370 pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
1371 va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
1372 else
1373 pp_integer_with_precision
1374 (pp, *text->m_args_ptr, precision, unsigned, "u");
1375 break;
1377 case 'f':
1378 pp_double (pp, va_arg (*text->m_args_ptr, double));
1379 break;
1381 case 'Z':
1383 int *v = va_arg (*text->m_args_ptr, int *);
1384 unsigned len = va_arg (*text->m_args_ptr, unsigned);
1386 for (unsigned i = 0; i < len; ++i)
1388 pp_scalar (pp, "%i", v[i]);
1389 if (i < len - 1)
1391 pp_comma (pp);
1392 pp_space (pp);
1395 break;
1398 case 'x':
1399 if (wide)
1400 pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
1401 va_arg (*text->m_args_ptr, unsigned HOST_WIDE_INT));
1402 else
1403 pp_integer_with_precision
1404 (pp, *text->m_args_ptr, precision, unsigned, "x");
1405 break;
1407 case '.':
1409 int n;
1410 const char *s;
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))
1418 char *end;
1419 n = strtoul (p, &end, 10);
1420 p = end;
1421 gcc_assert (*p == 's');
1423 else
1425 gcc_assert (*p == '*');
1426 p++;
1427 gcc_assert (*p == 's');
1428 n = va_arg (*text->m_args_ptr, int);
1430 /* This consumes a second entry in the formatters array. */
1431 gcc_assert (formatters[argno] == formatters[argno+1]);
1432 argno++;
1435 s = va_arg (*text->m_args_ptr, const char *);
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);
1442 pp_append_text (pp, s, s + len);
1444 break;
1446 case '@':
1448 /* diagnostic_event_id_t *. */
1449 diagnostic_event_id_ptr event_id
1450 = va_arg (*text->m_args_ptr, diagnostic_event_id_ptr);
1451 gcc_assert (event_id->known_p ());
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)));
1459 break;
1461 case '{':
1462 pp_begin_url (pp, va_arg (*text->m_args_ptr, const char *));
1463 break;
1465 default:
1467 bool ok;
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). */
1474 gcc_assert (pp_format_decoder (pp));
1475 ok = pp_format_decoder (pp) (pp, text, p,
1476 precision, wide, plus, hash, &quote,
1477 formatters[argno]);
1478 gcc_assert (ok);
1482 if (quote)
1483 pp_end_quote (pp, pp_show_color (pp));
1485 obstack_1grow (&buffer->chunk_obstack, '\0');
1486 *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
1489 if (CHECKING_P)
1490 for (; argno < PP_NL_ARGMAX; argno++)
1491 gcc_assert (!formatters[argno]);
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);
1498 /* Revert to normal obstack and wrapping mode. */
1499 buffer->obstack = &buffer->formatted_obstack;
1500 buffer->line_length = old_line_length;
1501 pp_wrapping_mode (pp) = old_wrapping_mode;
1502 pp_clear_state (pp);
1505 /* Format of a message pointed to by TEXT. */
1506 void
1507 pp_output_formatted_text (pretty_printer *pp)
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;
1514 gcc_assert (buffer->obstack == &buffer->formatted_obstack);
1516 /* This is a third phase, first 2 phases done in pp_format_args.
1517 Now we actually print it. */
1518 for (chunk = 0; args[chunk]; chunk++)
1519 pp_string (pp, args[chunk]);
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);
1527 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
1528 settings needed by BUFFER for a verbatim formatting. */
1529 void
1530 pp_format_verbatim (pretty_printer *pp, text_info *text)
1532 /* Set verbatim mode. */
1533 pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
1535 /* Do the actual formatting. */
1536 pp_format (pp, text);
1537 pp_output_formatted_text (pp);
1539 /* Restore previous settings. */
1540 pp_wrapping_mode (pp) = oldmode;
1543 /* Flush the content of BUFFER onto the attached stream. This
1544 function does nothing unless pp->output_buffer->flush_p. */
1545 void
1546 pp_flush (pretty_printer *pp)
1548 pp_clear_state (pp);
1549 if (!pp->buffer->flush_p)
1550 return;
1551 pp_write_text_to_stream (pp);
1552 fflush (pp_buffer (pp)->stream);
1555 /* Flush the content of BUFFER onto the attached stream independently
1556 of the value of pp->output_buffer->flush_p. */
1557 void
1558 pp_really_flush (pretty_printer *pp)
1560 pp_clear_state (pp);
1561 pp_write_text_to_stream (pp);
1562 fflush (pp_buffer (pp)->stream);
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. */
1568 void
1569 pp_set_line_maximum_length (pretty_printer *pp, int length)
1571 pp_line_cutoff (pp) = length;
1572 pp_set_real_maximum_length (pp);
1575 /* Clear PRETTY-PRINTER output area text info. */
1576 void
1577 pp_clear_output_area (pretty_printer *pp)
1579 obstack_free (pp_buffer (pp)->obstack,
1580 obstack_base (pp_buffer (pp)->obstack));
1581 pp_buffer (pp)->line_length = 0;
1584 /* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which
1585 will eventually be free-ed. */
1587 void
1588 pp_set_prefix (pretty_printer *pp, char *prefix)
1590 free (pp->prefix);
1591 pp->prefix = prefix;
1592 pp_set_real_maximum_length (pp);
1593 pp->emitted_prefix = false;
1594 pp_indentation (pp) = 0;
1597 /* Take ownership of PP's prefix, setting it to NULL.
1598 This allows clients to save, override, and then restore an existing
1599 prefix, without it being free-ed. */
1601 char *
1602 pp_take_prefix (pretty_printer *pp)
1604 char *result = pp->prefix;
1605 pp->prefix = NULL;
1606 return result;
1609 /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */
1610 void
1611 pp_destroy_prefix (pretty_printer *pp)
1613 if (pp->prefix != NULL)
1615 free (pp->prefix);
1616 pp->prefix = NULL;
1620 /* Write out PRETTY-PRINTER's prefix. */
1621 void
1622 pp_emit_prefix (pretty_printer *pp)
1624 if (pp->prefix != NULL)
1626 switch (pp_prefixing_rule (pp))
1628 default:
1629 case DIAGNOSTICS_SHOW_PREFIX_NEVER:
1630 break;
1632 case DIAGNOSTICS_SHOW_PREFIX_ONCE:
1633 if (pp->emitted_prefix)
1635 pp_indent (pp);
1636 break;
1638 pp_indentation (pp) += 3;
1639 /* Fall through. */
1641 case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
1643 int prefix_length = strlen (pp->prefix);
1644 pp_append_r (pp, pp->prefix, prefix_length);
1645 pp->emitted_prefix = true;
1647 break;
1652 /* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line. */
1654 pretty_printer::pretty_printer (int maximum_length)
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 (),
1662 m_format_postprocessor (NULL),
1663 emitted_prefix (),
1664 need_newline (),
1665 translate_identifiers (true),
1666 show_color (),
1667 url_format (URL_FORMAT_NONE),
1668 m_skipping_null_url (false)
1670 pp_line_cutoff (this) = maximum_length;
1671 /* By default, we emit prefixes once per message. */
1672 pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
1673 pp_set_prefix (this, NULL);
1676 /* Copy constructor for pretty_printer. */
1678 pretty_printer::pretty_printer (const pretty_printer &other)
1679 : buffer (new (XCNEW (output_buffer)) output_buffer ()),
1680 prefix (),
1681 padding (other.padding),
1682 maximum_length (other.maximum_length),
1683 indent_skip (other.indent_skip),
1684 wrapping (other.wrapping),
1685 format_decoder (other.format_decoder),
1686 m_format_postprocessor (NULL),
1687 emitted_prefix (other.emitted_prefix),
1688 need_newline (other.need_newline),
1689 translate_identifiers (other.translate_identifiers),
1690 show_color (other.show_color),
1691 url_format (other.url_format),
1692 m_skipping_null_url (false)
1694 pp_line_cutoff (this) = maximum_length;
1695 /* By default, we emit prefixes once per message. */
1696 pp_prefixing_rule (this) = pp_prefixing_rule (&other);
1697 pp_set_prefix (this, NULL);
1699 if (other.m_format_postprocessor)
1700 m_format_postprocessor = other.m_format_postprocessor->clone ();
1703 pretty_printer::~pretty_printer ()
1705 if (m_format_postprocessor)
1706 delete m_format_postprocessor;
1707 buffer->~output_buffer ();
1708 XDELETE (buffer);
1709 free (prefix);
1712 /* Base class implementation of pretty_printer::clone vfunc. */
1714 pretty_printer *
1715 pretty_printer::clone () const
1717 return new pretty_printer (*this);
1720 /* Append a string delimited by START and END to the output area of
1721 PRETTY-PRINTER. No line wrapping is done. However, if beginning a
1722 new line then emit PRETTY-PRINTER's prefix and skip any leading
1723 whitespace if appropriate. The caller must ensure that it is
1724 safe to do so. */
1725 void
1726 pp_append_text (pretty_printer *pp, const char *start, const char *end)
1728 /* Emit prefix and skip whitespace if we're starting a new line. */
1729 if (pp_buffer (pp)->line_length == 0)
1731 pp_emit_prefix (pp);
1732 if (pp_is_wrapping_line (pp))
1733 while (start != end && *start == ' ')
1734 ++start;
1736 pp_append_r (pp, start, end - start);
1739 /* Finishes constructing a NULL-terminated character string representing
1740 the PRETTY-PRINTED text. */
1741 const char *
1742 pp_formatted_text (pretty_printer *pp)
1744 return output_buffer_formatted_text (pp_buffer (pp));
1747 /* Return a pointer to the last character emitted in PRETTY-PRINTER's
1748 output area. A NULL pointer means no character available. */
1749 const char *
1750 pp_last_position_in_text (const pretty_printer *pp)
1752 return output_buffer_last_position_in_text (pp_buffer (pp));
1755 /* Return the amount of characters PRETTY-PRINTER can accept to
1756 make a full line. Meaningful only in line-wrapping mode. */
1758 pp_remaining_character_count_for_line (pretty_printer *pp)
1760 return pp->maximum_length - pp_buffer (pp)->line_length;
1764 /* Format a message into BUFFER a la printf. */
1765 void
1766 pp_printf (pretty_printer *pp, const char *msg, ...)
1768 va_list ap;
1770 va_start (ap, msg);
1771 text_info text (msg, &ap, errno);
1772 pp_format (pp, &text);
1773 pp_output_formatted_text (pp);
1774 va_end (ap);
1778 /* Output MESSAGE verbatim into BUFFER. */
1779 void
1780 pp_verbatim (pretty_printer *pp, const char *msg, ...)
1782 va_list ap;
1784 va_start (ap, msg);
1785 text_info text (msg, &ap, errno);
1786 pp_format_verbatim (pp, &text);
1787 va_end (ap);
1792 /* Have PRETTY-PRINTER start a new line. */
1793 void
1794 pp_newline (pretty_printer *pp)
1796 obstack_1grow (pp_buffer (pp)->obstack, '\n');
1797 pp_needs_newline (pp) = false;
1798 pp_buffer (pp)->line_length = 0;
1801 /* Have PRETTY-PRINTER add a CHARACTER. */
1802 void
1803 pp_character (pretty_printer *pp, int c)
1805 if (pp_is_wrapping_line (pp)
1806 /* If printing UTF-8, don't wrap in the middle of a sequence. */
1807 && (((unsigned int) c) & 0xC0) != 0x80
1808 && pp_remaining_character_count_for_line (pp) <= 0)
1810 pp_newline (pp);
1811 if (ISSPACE (c))
1812 return;
1814 obstack_1grow (pp_buffer (pp)->obstack, c);
1815 ++pp_buffer (pp)->line_length;
1818 /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
1819 be line-wrapped if in appropriate mode. */
1820 void
1821 pp_string (pretty_printer *pp, const char *str)
1823 gcc_checking_assert (str);
1824 pp_maybe_wrap_text (pp, str, str + strlen (str));
1827 /* Append code point C to the output area of PRETTY-PRINTER, encoding it
1828 as UTF-8. */
1830 void
1831 pp_unicode_character (pretty_printer *pp, unsigned c)
1833 static const uchar masks[6] = { 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
1834 static const uchar limits[6] = { 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
1835 size_t nbytes;
1836 uchar buf[6], *p = &buf[6];
1838 nbytes = 1;
1839 if (c < 0x80)
1840 *--p = c;
1841 else
1845 *--p = ((c & 0x3F) | 0x80);
1846 c >>= 6;
1847 nbytes++;
1849 while (c >= 0x3F || (c & limits[nbytes-1]));
1850 *--p = (c | masks[nbytes-1]);
1853 pp_append_r (pp, (const char *)p, nbytes);
1856 /* Append the leading N characters of STRING to the output area of
1857 PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
1858 Setting N = -1 is as if N were set to strlen (STRING). The STRING
1859 may be line-wrapped if in appropriate mode. */
1860 static void
1861 pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
1863 gcc_checking_assert (str);
1865 const char *last = str;
1866 const char *ps;
1868 /* Compute the length if not specified. */
1869 if (n == (size_t) -1)
1870 n = strlen (str);
1872 for (ps = str; n; ++ps, --n)
1874 if (ISPRINT (*ps))
1875 continue;
1877 /* Don't escape a valid UTF-8 extended char. */
1878 const unsigned char *ups = (const unsigned char *) ps;
1879 if (*ups & 0x80)
1881 unsigned int extended_char;
1882 const int valid_utf8_len = decode_utf8_char (ups, n, &extended_char);
1883 if (valid_utf8_len > 0)
1885 ps += valid_utf8_len - 1;
1886 n -= valid_utf8_len - 1;
1887 continue;
1891 if (last < ps)
1892 pp_maybe_wrap_text (pp, last, ps);
1894 /* Append the hexadecimal value of the character. Allocate a buffer
1895 that's large enough for a 32-bit char plus the hex prefix. */
1896 char buf [11];
1897 int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
1898 pp_maybe_wrap_text (pp, buf, buf + n);
1899 last = ps + 1;
1902 pp_maybe_wrap_text (pp, last, ps);
1905 /* Maybe print out a whitespace if needed. */
1907 void
1908 pp_maybe_space (pretty_printer *pp)
1910 if (pp->padding != pp_none)
1912 pp_space (pp);
1913 pp->padding = pp_none;
1917 // Add a newline to the pretty printer PP and flush formatted text.
1919 void
1920 pp_newline_and_flush (pretty_printer *pp)
1922 pp_newline (pp);
1923 pp_flush (pp);
1924 pp_needs_newline (pp) = false;
1927 // Add a newline to the pretty printer PP, followed by indentation.
1929 void
1930 pp_newline_and_indent (pretty_printer *pp, int n)
1932 pp_indentation (pp) += n;
1933 pp_newline (pp);
1934 pp_indent (pp);
1935 pp_needs_newline (pp) = false;
1938 // Add separator C, followed by a single whitespace.
1940 void
1941 pp_separate_with (pretty_printer *pp, char c)
1943 pp_character (pp, c);
1944 pp_space (pp);
1947 /* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
1948 using the "quote" color. */
1950 void
1951 pp_begin_quote (pretty_printer *pp, bool show_color)
1953 pp_string (pp, open_quote);
1954 pp_string (pp, colorize_start (show_color, "quote"));
1957 /* If SHOW_COLOR is true, stop colorizing.
1958 Add a localized close quote. */
1960 void
1961 pp_end_quote (pretty_printer *pp, bool show_color)
1963 pp_string (pp, colorize_stop (show_color));
1964 pp_string (pp, close_quote);
1968 /* The string starting at P has LEN (at least 1) bytes left; if they
1969 start with a valid UTF-8 sequence, return the length of that
1970 sequence and set *VALUE to the value of that sequence, and
1971 otherwise return 0 and set *VALUE to (unsigned int) -1. */
1973 static int
1974 decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
1976 unsigned int t = *p;
1978 if (len == 0)
1979 abort ();
1980 if (t & 0x80)
1982 size_t utf8_len = 0;
1983 unsigned int ch;
1984 size_t i;
1985 for (t = *p; t & 0x80; t <<= 1)
1986 utf8_len++;
1988 if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
1990 *value = (unsigned int) -1;
1991 return 0;
1993 ch = *p & ((1 << (7 - utf8_len)) - 1);
1994 for (i = 1; i < utf8_len; i++)
1996 unsigned int u = p[i];
1997 if ((u & 0xC0) != 0x80)
1999 *value = (unsigned int) -1;
2000 return 0;
2002 ch = (ch << 6) | (u & 0x3F);
2004 if ( (ch <= 0x7F && utf8_len > 1)
2005 || (ch <= 0x7FF && utf8_len > 2)
2006 || (ch <= 0xFFFF && utf8_len > 3)
2007 || (ch <= 0x1FFFFF && utf8_len > 4)
2008 || (ch <= 0x3FFFFFF && utf8_len > 5)
2009 || (ch >= 0xD800 && ch <= 0xDFFF))
2011 *value = (unsigned int) -1;
2012 return 0;
2014 *value = ch;
2015 return utf8_len;
2017 else
2019 *value = t;
2020 return 1;
2024 /* Allocator for identifier_to_locale and corresponding function to
2025 free memory. */
2027 void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
2028 void (*identifier_to_locale_free) (void *) = free;
2030 /* Given IDENT, an identifier in the internal encoding, return a
2031 version of IDENT suitable for diagnostics in the locale character
2032 set: either IDENT itself, or a string, allocated using
2033 identifier_to_locale_alloc, converted to the locale character set
2034 and using escape sequences if not representable in the locale
2035 character set or containing control characters or invalid byte
2036 sequences. Existing backslashes in IDENT are not doubled, so the
2037 result may not uniquely specify the contents of an arbitrary byte
2038 sequence identifier. */
2040 const char *
2041 identifier_to_locale (const char *ident)
2043 const unsigned char *uid = (const unsigned char *) ident;
2044 size_t idlen = strlen (ident);
2045 bool valid_printable_utf8 = true;
2046 bool all_ascii = true;
2047 size_t i;
2049 for (i = 0; i < idlen;)
2051 unsigned int c;
2052 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2053 if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
2055 valid_printable_utf8 = false;
2056 break;
2058 if (utf8_len > 1)
2059 all_ascii = false;
2060 i += utf8_len;
2063 /* If IDENT contains invalid UTF-8 sequences (which may occur with
2064 attributes putting arbitrary byte sequences in identifiers), or
2065 control characters, we use octal escape sequences for all bytes
2066 outside printable ASCII. */
2067 if (!valid_printable_utf8)
2069 char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
2070 char *p = ret;
2071 for (i = 0; i < idlen; i++)
2073 if (uid[i] > 0x1F && uid[i] < 0x7F)
2074 *p++ = uid[i];
2075 else
2077 sprintf (p, "\\%03o", uid[i]);
2078 p += 4;
2081 *p = 0;
2082 return ret;
2085 /* Otherwise, if it is valid printable ASCII, or printable UTF-8
2086 with the locale character set being UTF-8, IDENT is used. */
2087 if (all_ascii || locale_utf8)
2088 return ident;
2090 /* Otherwise IDENT is converted to the locale character set if
2091 possible. */
2092 #if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
2093 if (locale_encoding != NULL)
2095 iconv_t cd = iconv_open (locale_encoding, "UTF-8");
2096 bool conversion_ok = true;
2097 char *ret = NULL;
2098 if (cd != (iconv_t) -1)
2100 size_t ret_alloc = 4 * idlen + 1;
2101 for (;;)
2103 /* Repeat the whole conversion process as needed with
2104 larger buffers so non-reversible transformations can
2105 always be detected. */
2106 ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
2107 char *outbuf;
2108 size_t inbytesleft = idlen;
2109 size_t outbytesleft = ret_alloc - 1;
2110 size_t iconv_ret;
2112 ret = (char *) identifier_to_locale_alloc (ret_alloc);
2113 outbuf = ret;
2115 if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
2117 conversion_ok = false;
2118 break;
2121 iconv_ret = iconv (cd, &inbuf, &inbytesleft,
2122 &outbuf, &outbytesleft);
2123 if (iconv_ret == (size_t) -1 || inbytesleft != 0)
2125 if (errno == E2BIG)
2127 ret_alloc *= 2;
2128 identifier_to_locale_free (ret);
2129 ret = NULL;
2130 continue;
2132 else
2134 conversion_ok = false;
2135 break;
2138 else if (iconv_ret != 0)
2140 conversion_ok = false;
2141 break;
2143 /* Return to initial shift state. */
2144 if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
2146 if (errno == E2BIG)
2148 ret_alloc *= 2;
2149 identifier_to_locale_free (ret);
2150 ret = NULL;
2151 continue;
2153 else
2155 conversion_ok = false;
2156 break;
2159 *outbuf = 0;
2160 break;
2162 iconv_close (cd);
2163 if (conversion_ok)
2164 return ret;
2167 #endif
2169 /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */
2171 char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
2172 char *p = ret;
2173 for (i = 0; i < idlen;)
2175 unsigned int c;
2176 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2177 if (utf8_len == 1)
2178 *p++ = uid[i];
2179 else
2181 sprintf (p, "\\U%08x", c);
2182 p += 10;
2184 i += utf8_len;
2186 *p = 0;
2187 return ret;
2191 /* Support for encoding URLs.
2192 See egmontkob/Hyperlinks_in_Terminal_Emulators.md
2193 ( https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda ).
2195 > A hyperlink is opened upon encountering an OSC 8 escape sequence with
2196 > the target URI. The syntax is
2198 > OSC 8 ; params ; URI ST
2200 > A hyperlink is closed with the same escape sequence, omitting the
2201 > parameters and the URI but keeping the separators:
2203 > OSC 8 ; ; ST
2205 > OSC (operating system command) is typically ESC ].
2207 Use BEL instead of ST, as that is currently rendered better in some
2208 terminal emulators that don't support OSC 8, like konsole. */
2210 /* If URL-printing is enabled, write an "open URL" escape sequence to PP
2211 for the given URL. */
2213 void
2214 pp_begin_url (pretty_printer *pp, const char *url)
2216 if (!url)
2218 /* Handle null URL by skipping all output here,
2219 and in the next pp_end_url. */
2220 pp->m_skipping_null_url = true;
2221 return;
2223 switch (pp->url_format)
2225 case URL_FORMAT_NONE:
2226 break;
2227 case URL_FORMAT_ST:
2228 pp_string (pp, "\33]8;;");
2229 pp_string (pp, url);
2230 pp_string (pp, "\33\\");
2231 break;
2232 case URL_FORMAT_BEL:
2233 pp_string (pp, "\33]8;;");
2234 pp_string (pp, url);
2235 pp_string (pp, "\a");
2236 break;
2237 default:
2238 gcc_unreachable ();
2242 /* Helper function for pp_end_url and pp_format, return the "close URL" escape
2243 sequence string. */
2245 static const char *
2246 get_end_url_string (pretty_printer *pp)
2248 switch (pp->url_format)
2250 case URL_FORMAT_NONE:
2251 return "";
2252 case URL_FORMAT_ST:
2253 return "\33]8;;\33\\";
2254 case URL_FORMAT_BEL:
2255 return "\33]8;;\a";
2256 default:
2257 gcc_unreachable ();
2261 /* If URL-printing is enabled, write a "close URL" escape sequence to PP. */
2263 void
2264 pp_end_url (pretty_printer *pp)
2266 if (pp->m_skipping_null_url)
2268 /* We gracefully handle pp_begin_url (NULL) by omitting output for
2269 both begin and end. Here we handle the latter. */
2270 pp->m_skipping_null_url = false;
2271 return;
2273 if (pp->url_format != URL_FORMAT_NONE)
2274 pp_string (pp, get_end_url_string (pp));
2277 #if CHECKING_P
2279 namespace selftest {
2281 /* Smoketest for pretty_printer. */
2283 static void
2284 test_basic_printing ()
2286 pretty_printer pp;
2287 pp_string (&pp, "hello");
2288 pp_space (&pp);
2289 pp_string (&pp, "world");
2291 ASSERT_STREQ ("hello world", pp_formatted_text (&pp));
2294 /* Helper function for testing pp_format.
2295 Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2296 prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */
2298 static void
2299 assert_pp_format_va (const location &loc, const char *expected,
2300 bool show_color, const char *fmt, va_list *ap)
2302 pretty_printer pp;
2303 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2305 text_info ti (fmt, ap, 0, nullptr, &rich_loc);
2307 pp_show_color (&pp) = show_color;
2308 pp_format (&pp, &ti);
2309 pp_output_formatted_text (&pp);
2310 ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
2313 /* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2314 prints EXPECTED, with show_color disabled. */
2316 static void
2317 assert_pp_format (const location &loc, const char *expected,
2318 const char *fmt, ...)
2320 va_list ap;
2322 va_start (ap, fmt);
2323 assert_pp_format_va (loc, expected, false, fmt, &ap);
2324 va_end (ap);
2327 /* As above, but with colorization enabled. */
2329 static void
2330 assert_pp_format_colored (const location &loc, const char *expected,
2331 const char *fmt, ...)
2333 /* The tests of colorization assume the default color scheme.
2334 If GCC_COLORS is set, then the colors have potentially been
2335 overridden; skip the test. */
2336 if (getenv ("GCC_COLORS"))
2337 return;
2339 va_list ap;
2341 va_start (ap, fmt);
2342 assert_pp_format_va (loc, expected, true, fmt, &ap);
2343 va_end (ap);
2346 /* Helper function for calling testing pp_format,
2347 by calling assert_pp_format with various numbers of arguments.
2348 These exist mostly to avoid having to write SELFTEST_LOCATION
2349 throughout test_pp_format. */
2351 #define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \
2352 SELFTEST_BEGIN_STMT \
2353 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2354 (ARG1)); \
2355 SELFTEST_END_STMT
2357 #define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \
2358 SELFTEST_BEGIN_STMT \
2359 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2360 (ARG1), (ARG2)); \
2361 SELFTEST_END_STMT
2363 #define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \
2364 SELFTEST_BEGIN_STMT \
2365 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2366 (ARG1), (ARG2), (ARG3)); \
2367 SELFTEST_END_STMT
2369 /* Verify that pp_format works, for various format codes. */
2371 static void
2372 test_pp_format ()
2374 /* Avoid introducing locale-specific differences in the results
2375 by hardcoding open_quote and close_quote. */
2376 auto_fix_quotes fix_quotes;
2378 /* Verify that plain text is passed through unchanged. */
2379 assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted");
2381 /* Verify various individual format codes, in the order listed in the
2382 comment for pp_format above. For each code, we append a second
2383 argument with a known bit pattern (0x12345678), to ensure that we
2384 are consuming arguments correctly. */
2385 ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678);
2386 ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678);
2387 ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678);
2388 ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678);
2389 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678);
2390 ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678);
2391 ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678);
2392 ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678);
2393 ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678);
2394 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe,
2395 0x12345678);
2396 ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678);
2397 ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678);
2398 ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678);
2399 ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678);
2400 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe,
2401 0x12345678);
2402 ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678);
2403 ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678);
2404 ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10,
2405 0x12345678);
2406 ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
2407 ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
2408 0x12345678);
2409 ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
2410 ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
2411 ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
2412 0x12345678);
2414 /* Not nul-terminated. */
2415 char arr[5] = { '1', '2', '3', '4', '5' };
2416 ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678);
2417 ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678);
2418 ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678);
2420 /* We can't test for %p; the pointer is printed in an implementation-defined
2421 manner. */
2422 ASSERT_PP_FORMAT_2 ("normal colored normal 12345678",
2423 "normal %rcolored%R normal %x",
2424 "error", 0x12345678);
2425 assert_pp_format_colored
2426 (SELFTEST_LOCATION,
2427 "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678",
2428 "normal %rcolored%R normal %x", "error", 0x12345678);
2429 /* TODO:
2430 %m: strerror(text->err_no) - does not consume a value from args_ptr. */
2431 ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678);
2432 ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678);
2433 ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678);
2434 ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678);
2435 ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678);
2436 ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678);
2438 /* Verify flag 'q'. */
2439 ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678);
2440 assert_pp_format_colored (SELFTEST_LOCATION,
2441 "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
2442 "foo", 0x12345678);
2443 /* Verify "%@". */
2445 diagnostic_event_id_t first (2);
2446 diagnostic_event_id_t second (7);
2448 ASSERT_PP_FORMAT_2 ("first `free' at (3); second `free' at (8)",
2449 "first %<free%> at %@; second %<free%> at %@",
2450 &first, &second);
2451 assert_pp_format_colored
2452 (SELFTEST_LOCATION,
2453 "first `\e[01m\e[Kfree\e[m\e[K' at \e[01;36m\e[K(3)\e[m\e[K;"
2454 " second `\e[01m\e[Kfree\e[m\e[K' at \e[01;36m\e[K(8)\e[m\e[K",
2455 "first %<free%> at %@; second %<free%> at %@",
2456 &first, &second);
2459 /* Verify %Z. */
2460 int v[] = { 1, 2, 3 };
2461 ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
2463 int v2[] = { 0 };
2464 ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
2466 /* Verify that combinations work, along with unformatted text. */
2467 assert_pp_format (SELFTEST_LOCATION,
2468 "the quick brown fox jumps over the lazy dog",
2469 "the %s %s %s jumps over the %s %s",
2470 "quick", "brown", "fox", "lazy", "dog");
2471 assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7);
2472 assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10",
2473 "problem with %qs at line %i", "bar", 10);
2476 /* A subclass of pretty_printer for use by test_prefixes_and_wrapping. */
2478 class test_pretty_printer : public pretty_printer
2480 public:
2481 test_pretty_printer (enum diagnostic_prefixing_rule_t rule,
2482 int max_line_length)
2484 pp_set_prefix (this, xstrdup ("PREFIX: "));
2485 wrapping.rule = rule;
2486 pp_set_line_maximum_length (this, max_line_length);
2490 /* Verify that the various values of enum diagnostic_prefixing_rule_t work
2491 as expected, with and without line wrapping. */
2493 static void
2494 test_prefixes_and_wrapping ()
2496 /* Tests of the various prefixing rules, without wrapping.
2497 Newlines embedded in pp_string don't affect it; we have to
2498 explicitly call pp_newline. */
2500 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 0);
2501 pp_string (&pp, "the quick brown fox");
2502 pp_newline (&pp);
2503 pp_string (&pp, "jumps over the lazy dog");
2504 pp_newline (&pp);
2505 ASSERT_STREQ (pp_formatted_text (&pp),
2506 "PREFIX: the quick brown fox\n"
2507 " jumps over the lazy dog\n");
2510 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 0);
2511 pp_string (&pp, "the quick brown fox");
2512 pp_newline (&pp);
2513 pp_string (&pp, "jumps over the lazy dog");
2514 pp_newline (&pp);
2515 ASSERT_STREQ (pp_formatted_text (&pp),
2516 "the quick brown fox\n"
2517 "jumps over the lazy dog\n");
2520 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 0);
2521 pp_string (&pp, "the quick brown fox");
2522 pp_newline (&pp);
2523 pp_string (&pp, "jumps over the lazy dog");
2524 pp_newline (&pp);
2525 ASSERT_STREQ (pp_formatted_text (&pp),
2526 "PREFIX: the quick brown fox\n"
2527 "PREFIX: jumps over the lazy dog\n");
2530 /* Tests of the various prefixing rules, with wrapping. */
2532 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 20);
2533 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2534 pp_newline (&pp);
2535 pp_string (&pp, "able was I ere I saw elba");
2536 pp_newline (&pp);
2537 ASSERT_STREQ (pp_formatted_text (&pp),
2538 "PREFIX: the quick \n"
2539 " brown fox jumps \n"
2540 " over the lazy \n"
2541 " dog\n"
2542 " able was I ere I \n"
2543 " saw elba\n");
2546 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 20);
2547 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2548 pp_newline (&pp);
2549 pp_string (&pp, "able was I ere I saw elba");
2550 pp_newline (&pp);
2551 ASSERT_STREQ (pp_formatted_text (&pp),
2552 "the quick brown fox \n"
2553 "jumps over the lazy \n"
2554 "dog\n"
2555 "able was I ere I \n"
2556 "saw elba\n");
2559 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 20);
2560 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2561 pp_newline (&pp);
2562 pp_string (&pp, "able was I ere I saw elba");
2563 pp_newline (&pp);
2564 ASSERT_STREQ (pp_formatted_text (&pp),
2565 "PREFIX: the quick brown fox jumps over the lazy dog\n"
2566 "PREFIX: able was I ere I saw elba\n");
2571 /* Verify that URL-printing works as expected. */
2573 void
2574 test_urls ()
2577 pretty_printer pp;
2578 pp.url_format = URL_FORMAT_NONE;
2579 pp_begin_url (&pp, "http://example.com");
2580 pp_string (&pp, "This is a link");
2581 pp_end_url (&pp);
2582 ASSERT_STREQ ("This is a link",
2583 pp_formatted_text (&pp));
2587 pretty_printer pp;
2588 pp.url_format = URL_FORMAT_ST;
2589 pp_begin_url (&pp, "http://example.com");
2590 pp_string (&pp, "This is a link");
2591 pp_end_url (&pp);
2592 ASSERT_STREQ ("\33]8;;http://example.com\33\\This is a link\33]8;;\33\\",
2593 pp_formatted_text (&pp));
2597 pretty_printer pp;
2598 pp.url_format = URL_FORMAT_BEL;
2599 pp_begin_url (&pp, "http://example.com");
2600 pp_string (&pp, "This is a link");
2601 pp_end_url (&pp);
2602 ASSERT_STREQ ("\33]8;;http://example.com\aThis is a link\33]8;;\a",
2603 pp_formatted_text (&pp));
2607 /* Verify that we gracefully reject null URLs. */
2609 void
2610 test_null_urls ()
2613 pretty_printer pp;
2614 pp.url_format = URL_FORMAT_NONE;
2615 pp_begin_url (&pp, nullptr);
2616 pp_string (&pp, "This isn't a link");
2617 pp_end_url (&pp);
2618 ASSERT_STREQ ("This isn't a link",
2619 pp_formatted_text (&pp));
2623 pretty_printer pp;
2624 pp.url_format = URL_FORMAT_ST;
2625 pp_begin_url (&pp, nullptr);
2626 pp_string (&pp, "This isn't a link");
2627 pp_end_url (&pp);
2628 ASSERT_STREQ ("This isn't a link",
2629 pp_formatted_text (&pp));
2633 pretty_printer pp;
2634 pp.url_format = URL_FORMAT_BEL;
2635 pp_begin_url (&pp, nullptr);
2636 pp_string (&pp, "This isn't a link");
2637 pp_end_url (&pp);
2638 ASSERT_STREQ ("This isn't a link",
2639 pp_formatted_text (&pp));
2643 /* Test multibyte awareness. */
2644 static void test_utf8 ()
2647 /* Check that pp_quoted_string leaves valid UTF-8 alone. */
2649 pretty_printer pp;
2650 const char *s = "\xf0\x9f\x98\x82";
2651 pp_quoted_string (&pp, s);
2652 ASSERT_STREQ (pp_formatted_text (&pp), s);
2655 /* Check that pp_quoted_string escapes non-UTF-8 nonprintable bytes. */
2657 pretty_printer pp;
2658 pp_quoted_string (&pp, "\xf0!\x9f\x98\x82");
2659 ASSERT_STREQ (pp_formatted_text (&pp),
2660 "\\xf0!\\x9f\\x98\\x82");
2663 /* Check that pp_character will line-wrap at the beginning of a UTF-8
2664 sequence, but not in the middle. */
2666 pretty_printer pp (3);
2667 const char s[] = "---\xf0\x9f\x98\x82";
2668 for (int i = 0; i != sizeof (s) - 1; ++i)
2669 pp_character (&pp, s[i]);
2670 pp_newline (&pp);
2671 for (int i = 1; i != sizeof (s) - 1; ++i)
2672 pp_character (&pp, s[i]);
2673 pp_character (&pp, '-');
2674 ASSERT_STREQ (pp_formatted_text (&pp),
2675 "---\n"
2676 "\xf0\x9f\x98\x82\n"
2677 "--\xf0\x9f\x98\x82\n"
2678 "-");
2683 /* Run all of the selftests within this file. */
2685 void
2686 pretty_print_cc_tests ()
2688 test_basic_printing ();
2689 test_pp_format ();
2690 test_prefixes_and_wrapping ();
2691 test_urls ();
2692 test_null_urls ();
2693 test_utf8 ();
2696 } // namespace selftest
2698 #endif /* CHECKING_P */