struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / support / cpp / gcc / pretty-print.cc
blob84b8db8a636cb6d423971913d30d5aefec4d539e
1 /* Various declarations for language-independent pretty-print subroutines.
2 Copyright (C) 2003-2022 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 /* These symbols might be missing in some versions of mingw */
47 #ifndef COMMON_LVB_UNDERSCORE
48 #define COMMON_LVB_UNDERSCORE 0x8000
49 #endif
50 #ifndef COMMON_LVB_REVERSE_VIDEO
51 #define COMMON_LVB_REVERSE_VIDEO 0x4000
52 #endif
55 /* Write all bytes in [s,s+n) into the specified stream.
56 Errors are ignored. */
57 static void
58 write_all (HANDLE h, const char *s, size_t n)
60 size_t rem = n;
61 DWORD step;
63 while (rem != 0)
65 if (rem <= UINT_MAX)
66 step = rem;
67 else
68 step = UINT_MAX;
69 if (!WriteFile (h, s + n - rem, step, &step, NULL))
70 break;
71 rem -= step;
75 /* Find the beginning of an escape sequence.
76 There are two cases:
77 1. If the sequence begins with an ESC character (0x1B) and a second
78 character X in [0x40,0x5F], returns X and stores a pointer to
79 the third character into *head.
80 2. If the sequence begins with a character X in [0x80,0x9F], returns
81 (X-0x40) and stores a pointer to the second character into *head.
82 Stores the number of ESC character(s) in *prefix_len.
83 Returns 0 if no such sequence can be found. */
84 static int
85 find_esc_head (int *prefix_len, const char **head, const char *str)
87 int c;
88 const char *r = str;
89 int escaped = 0;
91 for (;;)
93 c = (unsigned char) *r;
94 if (c == 0)
96 /* Not found. */
97 return 0;
99 if (escaped && 0x40 <= c && c <= 0x5F)
101 /* Found (case 1). */
102 *prefix_len = 2;
103 *head = r + 1;
104 return c;
106 if (0x80 <= c && c <= 0x9F)
108 /* Found (case 2). */
109 *prefix_len = 1;
110 *head = r + 1;
111 return c - 0x40;
113 ++r;
114 escaped = c == 0x1B;
118 /* Find the terminator of an escape sequence.
119 str should be the value stored in *head by a previous successful
120 call to find_esc_head().
121 Returns 0 if no such sequence can be found. */
122 static int
123 find_esc_terminator (const char **term, const char *str)
125 int c;
126 const char *r = str;
128 for (;;)
130 c = (unsigned char) *r;
131 if (c == 0)
133 /* Not found. */
134 return 0;
136 if (0x40 <= c && c <= 0x7E)
138 /* Found. */
139 *term = r;
140 return c;
142 ++r;
146 /* Handle a sequence of codes. Sequences that are invalid, reserved,
147 unrecognized or unimplemented are ignored silently.
148 There isn't much we can do because of lameness of Windows consoles. */
149 static void
150 eat_esc_sequence (HANDLE h, int esc_code,
151 const char *esc_head, const char *esc_term)
153 /* Numbers in an escape sequence cannot be negative, because
154 a minus sign in the middle of it would have terminated it. */
155 long n1, n2;
156 char *eptr, *delim;
157 CONSOLE_SCREEN_BUFFER_INFO sb;
158 COORD cr;
159 /* ED and EL parameters. */
160 DWORD cnt, step;
161 long rows;
162 /* SGR parameters. */
163 WORD attrib_add, attrib_rm;
164 const char *param;
166 switch (MAKEWORD (esc_code, *esc_term))
168 /* ESC [ n1 'A'
169 Move the cursor up by n1 characters. */
170 case MAKEWORD ('[', 'A'):
171 if (esc_head == esc_term)
172 n1 = 1;
173 else
175 n1 = strtol (esc_head, &eptr, 10);
176 if (eptr != esc_term)
177 break;
180 if (GetConsoleScreenBufferInfo (h, &sb))
182 cr = sb.dwCursorPosition;
183 /* Stop at the topmost boundary. */
184 if (cr.Y > n1)
185 cr.Y -= n1;
186 else
187 cr.Y = 0;
188 SetConsoleCursorPosition (h, cr);
190 break;
192 /* ESC [ n1 'B'
193 Move the cursor down by n1 characters. */
194 case MAKEWORD ('[', 'B'):
195 if (esc_head == esc_term)
196 n1 = 1;
197 else
199 n1 = strtol (esc_head, &eptr, 10);
200 if (eptr != esc_term)
201 break;
204 if (GetConsoleScreenBufferInfo (h, &sb))
206 cr = sb.dwCursorPosition;
207 /* Stop at the bottommost boundary. */
208 if (sb.dwSize.Y - cr.Y > n1)
209 cr.Y += n1;
210 else
211 cr.Y = sb.dwSize.Y;
212 SetConsoleCursorPosition (h, cr);
214 break;
216 /* ESC [ n1 'C'
217 Move the cursor right by n1 characters. */
218 case MAKEWORD ('[', 'C'):
219 if (esc_head == esc_term)
220 n1 = 1;
221 else
223 n1 = strtol (esc_head, &eptr, 10);
224 if (eptr != esc_term)
225 break;
228 if (GetConsoleScreenBufferInfo (h, &sb))
230 cr = sb.dwCursorPosition;
231 /* Stop at the rightmost boundary. */
232 if (sb.dwSize.X - cr.X > n1)
233 cr.X += n1;
234 else
235 cr.X = sb.dwSize.X;
236 SetConsoleCursorPosition (h, cr);
238 break;
240 /* ESC [ n1 'D'
241 Move the cursor left by n1 characters. */
242 case MAKEWORD ('[', 'D'):
243 if (esc_head == esc_term)
244 n1 = 1;
245 else
247 n1 = strtol (esc_head, &eptr, 10);
248 if (eptr != esc_term)
249 break;
252 if (GetConsoleScreenBufferInfo (h, &sb))
254 cr = sb.dwCursorPosition;
255 /* Stop at the leftmost boundary. */
256 if (cr.X > n1)
257 cr.X -= n1;
258 else
259 cr.X = 0;
260 SetConsoleCursorPosition (h, cr);
262 break;
264 /* ESC [ n1 'E'
265 Move the cursor to the beginning of the n1-th line downwards. */
266 case MAKEWORD ('[', 'E'):
267 if (esc_head == esc_term)
268 n1 = 1;
269 else
271 n1 = strtol (esc_head, &eptr, 10);
272 if (eptr != esc_term)
273 break;
276 if (GetConsoleScreenBufferInfo (h, &sb))
278 cr = sb.dwCursorPosition;
279 cr.X = 0;
280 /* Stop at the bottommost boundary. */
281 if (sb.dwSize.Y - cr.Y > n1)
282 cr.Y += n1;
283 else
284 cr.Y = sb.dwSize.Y;
285 SetConsoleCursorPosition (h, cr);
287 break;
289 /* ESC [ n1 'F'
290 Move the cursor to the beginning of the n1-th line upwards. */
291 case MAKEWORD ('[', 'F'):
292 if (esc_head == esc_term)
293 n1 = 1;
294 else
296 n1 = strtol (esc_head, &eptr, 10);
297 if (eptr != esc_term)
298 break;
301 if (GetConsoleScreenBufferInfo (h, &sb))
303 cr = sb.dwCursorPosition;
304 cr.X = 0;
305 /* Stop at the topmost boundary. */
306 if (cr.Y > n1)
307 cr.Y -= n1;
308 else
309 cr.Y = 0;
310 SetConsoleCursorPosition (h, cr);
312 break;
314 /* ESC [ n1 'G'
315 Move the cursor to the (1-based) n1-th column. */
316 case MAKEWORD ('[', 'G'):
317 if (esc_head == esc_term)
318 n1 = 1;
319 else
321 n1 = strtol (esc_head, &eptr, 10);
322 if (eptr != esc_term)
323 break;
326 if (GetConsoleScreenBufferInfo (h, &sb))
328 cr = sb.dwCursorPosition;
329 n1 -= 1;
330 /* Stop at the leftmost or rightmost boundary. */
331 if (n1 < 0)
332 cr.X = 0;
333 else if (n1 > sb.dwSize.X)
334 cr.X = sb.dwSize.X;
335 else
336 cr.X = n1;
337 SetConsoleCursorPosition (h, cr);
339 break;
341 /* ESC [ n1 ';' n2 'H'
342 ESC [ n1 ';' n2 'f'
343 Move the cursor to the (1-based) n1-th row and
344 (also 1-based) n2-th column. */
345 case MAKEWORD ('[', 'H'):
346 case MAKEWORD ('[', 'f'):
347 if (esc_head == esc_term)
349 /* Both parameters are omitted and set to 1 by default. */
350 n1 = 1;
351 n2 = 1;
353 else if (!(delim = (char *) memchr (esc_head, ';',
354 esc_term - esc_head)))
356 /* Only the first parameter is given. The second one is
357 set to 1 by default. */
358 n1 = strtol (esc_head, &eptr, 10);
359 if (eptr != esc_term)
360 break;
361 n2 = 1;
363 else
365 /* Both parameters are given. The first one shall be
366 terminated by the semicolon. */
367 n1 = strtol (esc_head, &eptr, 10);
368 if (eptr != delim)
369 break;
370 n2 = strtol (delim + 1, &eptr, 10);
371 if (eptr != esc_term)
372 break;
375 if (GetConsoleScreenBufferInfo (h, &sb))
377 cr = sb.dwCursorPosition;
378 n1 -= 1;
379 n2 -= 1;
380 /* The cursor position shall be relative to the view coord of
381 the console window, which is usually smaller than the actual
382 buffer. FWIW, the 'appropriate' solution will be shrinking
383 the buffer to match the size of the console window,
384 destroying scrollback in the process. */
385 n1 += sb.srWindow.Top;
386 n2 += sb.srWindow.Left;
387 /* Stop at the topmost or bottommost boundary. */
388 if (n1 < 0)
389 cr.Y = 0;
390 else if (n1 > sb.dwSize.Y)
391 cr.Y = sb.dwSize.Y;
392 else
393 cr.Y = n1;
394 /* Stop at the leftmost or rightmost boundary. */
395 if (n2 < 0)
396 cr.X = 0;
397 else if (n2 > sb.dwSize.X)
398 cr.X = sb.dwSize.X;
399 else
400 cr.X = n2;
401 SetConsoleCursorPosition (h, cr);
403 break;
405 /* ESC [ n1 'J'
406 Erase display. */
407 case MAKEWORD ('[', 'J'):
408 if (esc_head == esc_term)
409 /* This is one of the very few codes whose parameters have
410 a default value of zero. */
411 n1 = 0;
412 else
414 n1 = strtol (esc_head, &eptr, 10);
415 if (eptr != esc_term)
416 break;
419 if (GetConsoleScreenBufferInfo (h, &sb))
421 /* The cursor is not necessarily in the console window, which
422 makes the behavior of this code harder to define. */
423 switch (n1)
425 case 0:
426 /* If the cursor is in or above the window, erase from
427 it to the bottom of the window; otherwise, do nothing. */
428 cr = sb.dwCursorPosition;
429 cnt = sb.dwSize.X - sb.dwCursorPosition.X;
430 rows = sb.srWindow.Bottom - sb.dwCursorPosition.Y;
431 break;
432 case 1:
433 /* If the cursor is in or under the window, erase from
434 it to the top of the window; otherwise, do nothing. */
435 cr.X = 0;
436 cr.Y = sb.srWindow.Top;
437 cnt = sb.dwCursorPosition.X + 1;
438 rows = sb.dwCursorPosition.Y - sb.srWindow.Top;
439 break;
440 case 2:
441 /* Erase the entire window. */
442 cr.X = sb.srWindow.Left;
443 cr.Y = sb.srWindow.Top;
444 cnt = 0;
445 rows = sb.srWindow.Bottom - sb.srWindow.Top + 1;
446 break;
447 default:
448 /* Erase the entire buffer. */
449 cr.X = 0;
450 cr.Y = 0;
451 cnt = 0;
452 rows = sb.dwSize.Y;
453 break;
455 if (rows < 0)
456 break;
457 cnt += rows * sb.dwSize.X;
458 FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step);
459 FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step);
461 break;
463 /* ESC [ n1 'K'
464 Erase line. */
465 case MAKEWORD ('[', 'K'):
466 if (esc_head == esc_term)
467 /* This is one of the very few codes whose parameters have
468 a default value of zero. */
469 n1 = 0;
470 else
472 n1 = strtol (esc_head, &eptr, 10);
473 if (eptr != esc_term)
474 break;
477 if (GetConsoleScreenBufferInfo (h, &sb))
479 switch (n1)
481 case 0:
482 /* Erase from the cursor to the end. */
483 cr = sb.dwCursorPosition;
484 cnt = sb.dwSize.X - sb.dwCursorPosition.X;
485 break;
486 case 1:
487 /* Erase from the cursor to the beginning. */
488 cr = sb.dwCursorPosition;
489 cr.X = 0;
490 cnt = sb.dwCursorPosition.X + 1;
491 break;
492 default:
493 /* Erase the entire line. */
494 cr = sb.dwCursorPosition;
495 cr.X = 0;
496 cnt = sb.dwSize.X;
497 break;
499 FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step);
500 FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step);
502 break;
504 /* ESC [ n1 ';' n2 'm'
505 Set SGR parameters. Zero or more parameters will follow. */
506 case MAKEWORD ('[', 'm'):
507 attrib_add = 0;
508 attrib_rm = 0;
509 if (esc_head == esc_term)
511 /* When no parameter is given, reset the console. */
512 attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
513 | FOREGROUND_BLUE);
514 attrib_rm = -1; /* Removes everything. */
515 goto sgr_set_it;
517 param = esc_head;
520 /* Parse a parameter. */
521 n1 = strtol (param, &eptr, 10);
522 if (*eptr != ';' && eptr != esc_term)
523 goto sgr_set_it;
525 switch (n1)
527 case 0:
528 /* Reset. */
529 attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
530 | FOREGROUND_BLUE);
531 attrib_rm = -1; /* Removes everything. */
532 break;
533 case 1:
534 /* Bold. */
535 attrib_add |= FOREGROUND_INTENSITY;
536 break;
537 case 4:
538 /* Underline. */
539 attrib_add |= COMMON_LVB_UNDERSCORE;
540 break;
541 case 5:
542 /* Blink. */
543 /* XXX: It is not BLINKING at all! */
544 attrib_add |= BACKGROUND_INTENSITY;
545 break;
546 case 7:
547 /* Reverse. */
548 attrib_add |= COMMON_LVB_REVERSE_VIDEO;
549 break;
550 case 22:
551 /* No bold. */
552 attrib_add &= ~FOREGROUND_INTENSITY;
553 attrib_rm |= FOREGROUND_INTENSITY;
554 break;
555 case 24:
556 /* No underline. */
557 attrib_add &= ~COMMON_LVB_UNDERSCORE;
558 attrib_rm |= COMMON_LVB_UNDERSCORE;
559 break;
560 case 25:
561 /* No blink. */
562 /* XXX: It is not BLINKING at all! */
563 attrib_add &= ~BACKGROUND_INTENSITY;
564 attrib_rm |= BACKGROUND_INTENSITY;
565 break;
566 case 27:
567 /* No reverse. */
568 attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
569 attrib_rm |= COMMON_LVB_REVERSE_VIDEO;
570 break;
571 case 30:
572 case 31:
573 case 32:
574 case 33:
575 case 34:
576 case 35:
577 case 36:
578 case 37:
579 /* Foreground color. */
580 attrib_add &= ~(FOREGROUND_RED | FOREGROUND_GREEN
581 | FOREGROUND_BLUE);
582 n1 -= 30;
583 if (n1 & 1)
584 attrib_add |= FOREGROUND_RED;
585 if (n1 & 2)
586 attrib_add |= FOREGROUND_GREEN;
587 if (n1 & 4)
588 attrib_add |= FOREGROUND_BLUE;
589 attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN
590 | FOREGROUND_BLUE);
591 break;
592 case 38:
593 /* Reserved for extended foreground color.
594 Don't know how to handle parameters remaining.
595 Bail out. */
596 goto sgr_set_it;
597 case 39:
598 /* Reset foreground color. */
599 /* Set to grey. */
600 attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
601 | FOREGROUND_BLUE);
602 attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN
603 | FOREGROUND_BLUE);
604 break;
605 case 40:
606 case 41:
607 case 42:
608 case 43:
609 case 44:
610 case 45:
611 case 46:
612 case 47:
613 /* Background color. */
614 attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN
615 | BACKGROUND_BLUE);
616 n1 -= 40;
617 if (n1 & 1)
618 attrib_add |= BACKGROUND_RED;
619 if (n1 & 2)
620 attrib_add |= BACKGROUND_GREEN;
621 if (n1 & 4)
622 attrib_add |= BACKGROUND_BLUE;
623 attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN
624 | BACKGROUND_BLUE);
625 break;
626 case 48:
627 /* Reserved for extended background color.
628 Don't know how to handle parameters remaining.
629 Bail out. */
630 goto sgr_set_it;
631 case 49:
632 /* Reset background color. */
633 /* Set to black. */
634 attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN
635 | BACKGROUND_BLUE);
636 attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN
637 | BACKGROUND_BLUE);
638 break;
641 /* Prepare the next parameter. */
642 param = eptr + 1;
644 while (param != esc_term);
646 sgr_set_it:
647 /* 0xFFFF removes everything. If it is not the case,
648 care must be taken to preserve old attributes. */
649 if (attrib_rm != 0xFFFF && GetConsoleScreenBufferInfo (h, &sb))
651 attrib_add |= sb.wAttributes & ~attrib_rm;
653 if (attrib_add & COMMON_LVB_REVERSE_VIDEO)
655 /* COMMON_LVB_REVERSE_VIDEO is only effective for DBCS.
656 * Swap foreground and background colors by hand.
658 attrib_add = (attrib_add & 0xFF00)
659 | ((attrib_add & 0x00F0) >> 4)
660 | ((attrib_add & 0x000F) << 4);
661 attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
663 SetConsoleTextAttribute (h, attrib_add);
664 break;
669 mingw_ansi_fputs (const char *str, FILE *fp)
671 const char *read = str;
672 HANDLE h;
673 DWORD mode;
674 int esc_code, prefix_len;
675 const char *esc_head, *esc_term;
677 h = (HANDLE) _get_osfhandle (_fileno (fp));
678 if (h == INVALID_HANDLE_VALUE)
679 return EOF;
681 /* Don't mess up stdio functions with Windows APIs. */
682 fflush (fp);
684 if (GetConsoleMode (h, &mode))
685 /* If it is a console, translate ANSI escape codes as needed. */
686 for (;;)
688 if ((esc_code = find_esc_head (&prefix_len, &esc_head, read)) == 0)
690 /* Write all remaining characters, then exit. */
691 write_all (h, read, strlen (read));
692 break;
694 if (find_esc_terminator (&esc_term, esc_head) == 0)
695 /* Ignore incomplete escape sequences at the moment.
696 FIXME: The escape state shall be cached for further calls
697 to this function. */
698 break;
699 write_all (h, read, esc_head - prefix_len - read);
700 eat_esc_sequence (h, esc_code, esc_head, esc_term);
701 read = esc_term + 1;
703 else
704 /* If it is not a console, write everything as-is. */
705 write_all (h, read, strlen (read));
707 return 1;
710 #endif /* __MINGW32__ */
712 static int
713 decode_utf8_char (const unsigned char *, size_t len, unsigned int *);
714 static void pp_quoted_string (pretty_printer *, const char *, size_t = -1);
716 /* Overwrite the given location/range within this text_info's rich_location.
717 For use e.g. when implementing "+" in client format decoders. */
719 void
720 text_info::set_location (unsigned int idx, location_t loc,
721 enum range_display_kind range_display_kind)
723 gcc_checking_assert (m_richloc);
724 m_richloc->set_range (idx, loc, range_display_kind);
727 location_t
728 text_info::get_location (unsigned int index_of_location) const
730 gcc_checking_assert (m_richloc);
732 if (index_of_location == 0)
733 return m_richloc->get_loc ();
734 else
735 return UNKNOWN_LOCATION;
738 // Default construct an output buffer.
740 output_buffer::output_buffer ()
741 : formatted_obstack (),
742 chunk_obstack (),
743 obstack (&formatted_obstack),
744 cur_chunk_array (),
745 stream (stderr),
746 line_length (),
747 digit_buffer (),
748 flush_p (true)
750 obstack_init (&formatted_obstack);
751 obstack_init (&chunk_obstack);
754 // Release resources owned by an output buffer at the end of lifetime.
756 output_buffer::~output_buffer ()
758 obstack_free (&chunk_obstack, NULL);
759 obstack_free (&formatted_obstack, NULL);
763 /* Format an integer given by va_arg (ARG, type-specifier T) where
764 type-specifier is a precision modifier as indicated by PREC. F is
765 a string used to construct the appropriate format-specifier. */
766 #define pp_integer_with_precision(PP, ARG, PREC, T, F) \
767 do \
768 switch (PREC) \
770 case 0: \
771 pp_scalar (PP, "%" F, va_arg (ARG, T)); \
772 break; \
774 case 1: \
775 pp_scalar (PP, "%l" F, va_arg (ARG, long T)); \
776 break; \
778 case 2: \
779 pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \
780 break; \
782 default: \
783 break; \
785 while (0)
788 /* Subroutine of pp_set_maximum_length. Set up PRETTY-PRINTER's
789 internal maximum characters per line. */
790 static void
791 pp_set_real_maximum_length (pretty_printer *pp)
793 /* If we're told not to wrap lines then do the obvious thing. In case
794 we'll emit prefix only once per message, it is appropriate
795 not to increase unnecessarily the line-length cut-off. */
796 if (!pp_is_wrapping_line (pp)
797 || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_ONCE
798 || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
799 pp->maximum_length = pp_line_cutoff (pp);
800 else
802 int prefix_length = pp->prefix ? strlen (pp->prefix) : 0;
803 /* If the prefix is ridiculously too long, output at least
804 32 characters. */
805 if (pp_line_cutoff (pp) - prefix_length < 32)
806 pp->maximum_length = pp_line_cutoff (pp) + 32;
807 else
808 pp->maximum_length = pp_line_cutoff (pp);
812 /* Clear PRETTY-PRINTER's output state. */
813 static inline void
814 pp_clear_state (pretty_printer *pp)
816 pp->emitted_prefix = false;
817 pp_indentation (pp) = 0;
820 /* Print X to PP in decimal. */
821 #if 0 // sdcpp
822 template<unsigned int N, typename T>
823 void
824 pp_wide_integer (pretty_printer *pp, const poly_int_pod<N, T> &x)
826 if (x.is_constant ())
827 pp_wide_integer (pp, x.coeffs[0]);
828 else
830 pp_left_bracket (pp);
831 for (unsigned int i = 0; i < N; ++i)
833 if (i != 0)
834 pp_comma (pp);
835 pp_wide_integer (pp, x.coeffs[i]);
837 pp_right_bracket (pp);
841 template void pp_wide_integer (pretty_printer *, const poly_uint16_pod &);
842 template void pp_wide_integer (pretty_printer *, const poly_int64_pod &);
843 template void pp_wide_integer (pretty_printer *, const poly_uint64_pod &);
844 #endif // sdcpp
846 /* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */
847 void
848 pp_write_text_to_stream (pretty_printer *pp)
850 const char *text = pp_formatted_text (pp);
851 #ifdef __MINGW32__
852 mingw_ansi_fputs (text, pp_buffer (pp)->stream);
853 #else
854 fputs (text, pp_buffer (pp)->stream);
855 #endif
856 pp_clear_output_area (pp);
859 /* As pp_write_text_to_stream, but for GraphViz label output.
861 Flush the formatted text of pretty-printer PP onto the attached stream.
862 Replace characters in PPF that have special meaning in a GraphViz .dot
863 file.
865 This routine is not very fast, but it doesn't have to be as this is only
866 be used by routines dumping intermediate representations in graph form. */
868 void
869 pp_write_text_as_dot_label_to_stream (pretty_printer *pp, bool for_record)
871 const char *text = pp_formatted_text (pp);
872 const char *p = text;
873 FILE *fp = pp_buffer (pp)->stream;
875 for (;*p; p++)
877 bool escape_char;
878 switch (*p)
880 /* Print newlines as a left-aligned newline. */
881 case '\n':
882 fputs ("\\l", fp);
883 escape_char = true;
884 break;
886 /* The following characters are only special for record-shape nodes. */
887 case '|':
888 case '{':
889 case '}':
890 case '<':
891 case '>':
892 case ' ':
893 escape_char = for_record;
894 break;
896 /* The following characters always have to be escaped
897 for use in labels. */
898 case '\\':
899 /* There is a bug in some (f.i. 2.36.0) versions of graphiz
900 ( http://www.graphviz.org/mantisbt/view.php?id=2524 ) related to
901 backslash as last char in label. Let's avoid triggering it. */
902 gcc_assert (*(p + 1) != '\0');
903 /* Fall through. */
904 case '"':
905 escape_char = true;
906 break;
908 default:
909 escape_char = false;
910 break;
913 if (escape_char)
914 fputc ('\\', fp);
916 fputc (*p, fp);
919 pp_clear_output_area (pp);
922 /* As pp_write_text_to_stream, but for GraphViz HTML-like strings.
924 Flush the formatted text of pretty-printer PP onto the attached stream,
925 escaping these characters
926 " & < >
927 using XML escape sequences.
929 http://www.graphviz.org/doc/info/lang.html#html states:
930 special XML escape sequences for ", &, <, and > may be necessary in
931 order to embed these characters in attribute values or raw text
932 This doesn't list "'" (which would normally be escaped in XML
933 as "&apos;" or in HTML as "&#39;");.
935 Experiments show that escaping "'" doesn't seem to be necessary. */
937 void
938 pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp)
940 const char *text = pp_formatted_text (pp);
941 const char *p = text;
942 FILE *fp = pp_buffer (pp)->stream;
944 for (;*p; p++)
946 switch (*p)
948 case '"':
949 fputs ("&quot;", fp);
950 break;
951 case '&':
952 fputs ("&amp;", fp);
953 break;
954 case '<':
955 fputs ("&lt;", fp);
956 break;
957 case '>':
958 fputs ("&gt;",fp);
959 break;
961 default:
962 fputc (*p, fp);
963 break;
967 pp_clear_output_area (pp);
970 /* Wrap a text delimited by START and END into PRETTY-PRINTER. */
971 static void
972 pp_wrap_text (pretty_printer *pp, const char *start, const char *end)
974 bool wrapping_line = pp_is_wrapping_line (pp);
976 while (start != end)
978 /* Dump anything bordered by whitespaces. */
980 const char *p = start;
981 while (p != end && !ISBLANK (*p) && *p != '\n')
982 ++p;
983 if (wrapping_line
984 && p - start >= pp_remaining_character_count_for_line (pp))
985 pp_newline (pp);
986 pp_append_text (pp, start, p);
987 start = p;
990 if (start != end && ISBLANK (*start))
992 pp_space (pp);
993 ++start;
995 if (start != end && *start == '\n')
997 pp_newline (pp);
998 ++start;
1003 /* Same as pp_wrap_text but wrap text only when in line-wrapping mode. */
1004 static inline void
1005 pp_maybe_wrap_text (pretty_printer *pp, const char *start, const char *end)
1007 if (pp_is_wrapping_line (pp))
1008 pp_wrap_text (pp, start, end);
1009 else
1010 pp_append_text (pp, start, end);
1013 /* Append to the output area of PRETTY-PRINTER a string specified by its
1014 STARTing character and LENGTH. */
1015 static inline void
1016 pp_append_r (pretty_printer *pp, const char *start, int length)
1018 output_buffer_append_r (pp_buffer (pp), start, length);
1021 /* Insert enough spaces into the output area of PRETTY-PRINTER to bring
1022 the column position to the current indentation level, assuming that a
1023 newline has just been written to the buffer. */
1024 void
1025 pp_indent (pretty_printer *pp)
1027 int n = pp_indentation (pp);
1028 int i;
1030 for (i = 0; i < n; ++i)
1031 pp_space (pp);
1034 static const char *get_end_url_string (pretty_printer *);
1036 /* The following format specifiers are recognized as being client independent:
1037 %d, %i: (signed) integer in base ten.
1038 %u: unsigned integer in base ten.
1039 %o: unsigned integer in base eight.
1040 %x: unsigned integer in base sixteen.
1041 %ld, %li, %lo, %lu, %lx: long versions of the above.
1042 %lld, %lli, %llo, %llu, %llx: long long versions.
1043 %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
1044 %f: double
1045 %c: character.
1046 %s: string.
1047 %p: pointer (printed in a host-dependent manner).
1048 %r: if pp_show_color(pp), switch to color identified by const char *.
1049 %R: if pp_show_color(pp), reset color.
1050 %m: strerror(text->err_no) - does not consume a value from args_ptr.
1051 %%: '%'.
1052 %<: opening quote.
1053 %>: closing quote.
1054 %{: URL start. Consumes a const char * argument for the URL.
1055 %}: URL end. Does not consume any arguments.
1056 %': apostrophe (should only be used in untranslated messages;
1057 translations should use appropriate punctuation directly).
1058 %@: diagnostic_event_id_ptr, for which event_id->known_p () must be true.
1059 %.*s: a substring the length of which is specified by an argument
1060 integer.
1061 %Ns: likewise, but length specified as constant in the format string.
1062 Flag 'q': quote formatted text (must come immediately after '%').
1063 %Z: Requires two arguments - array of int, and len. Prints elements
1064 of the array.
1066 Arguments can be used sequentially, or through %N$ resp. *N$
1067 notation Nth argument after the format string. If %N$ / *N$
1068 notation is used, it must be used for all arguments, except %m, %%,
1069 %<, %>, %} and %', which may not have a number, as they do not consume
1070 an argument. When %M$.*N$s is used, M must be N + 1. (This may
1071 also be written %M$.*s, provided N is not otherwise used.) The
1072 format string must have conversion specifiers with argument numbers
1073 1 up to highest argument; each argument may only be used once.
1074 A format string can have at most 30 arguments. */
1076 /* Formatting phases 1 and 2: render TEXT->format_spec plus
1077 TEXT->args_ptr into a series of chunks in pp_buffer (PP)->args[].
1078 Phase 3 is in pp_output_formatted_text. */
1080 void
1081 pp_format (pretty_printer *pp, text_info *text)
1083 output_buffer *buffer = pp_buffer (pp);
1084 const char *p;
1085 const char **args;
1086 struct chunk_info *new_chunk_array;
1088 unsigned int curarg = 0, chunk = 0, argno;
1089 pp_wrapping_mode_t old_wrapping_mode;
1090 bool any_unnumbered = false, any_numbered = false;
1091 const char **formatters[PP_NL_ARGMAX];
1093 /* Allocate a new chunk structure. */
1094 new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
1095 new_chunk_array->prev = buffer->cur_chunk_array;
1096 buffer->cur_chunk_array = new_chunk_array;
1097 args = new_chunk_array->args;
1099 /* Formatting phase 1: split up TEXT->format_spec into chunks in
1100 pp_buffer (PP)->args[]. Even-numbered chunks are to be output
1101 verbatim, odd-numbered chunks are format specifiers.
1102 %m, %%, %<, %>, %} and %' are replaced with the appropriate text at
1103 this point. */
1105 memset (formatters, 0, sizeof formatters);
1107 for (p = text->format_spec; *p; )
1109 while (*p != '\0' && *p != '%')
1111 obstack_1grow (&buffer->chunk_obstack, *p);
1112 p++;
1115 if (*p == '\0')
1116 break;
1118 switch (*++p)
1120 case '\0':
1121 gcc_unreachable ();
1123 case '%':
1124 obstack_1grow (&buffer->chunk_obstack, '%');
1125 p++;
1126 continue;
1128 case '<':
1130 obstack_grow (&buffer->chunk_obstack,
1131 open_quote, strlen (open_quote));
1132 const char *colorstr
1133 = colorize_start (pp_show_color (pp), "quote");
1134 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
1135 p++;
1136 continue;
1139 case '>':
1141 const char *colorstr = colorize_stop (pp_show_color (pp));
1142 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
1144 /* FALLTHRU */
1145 case '\'':
1146 obstack_grow (&buffer->chunk_obstack,
1147 close_quote, strlen (close_quote));
1148 p++;
1149 continue;
1151 case '}':
1153 const char *endurlstr = get_end_url_string (pp);
1154 obstack_grow (&buffer->chunk_obstack, endurlstr,
1155 strlen (endurlstr));
1157 p++;
1158 continue;
1160 case 'R':
1162 const char *colorstr = colorize_stop (pp_show_color (pp));
1163 obstack_grow (&buffer->chunk_obstack, colorstr,
1164 strlen (colorstr));
1165 p++;
1166 continue;
1169 case 'm':
1171 const char *errstr = xstrerror (text->err_no);
1172 obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
1174 p++;
1175 continue;
1177 default:
1178 /* Handled in phase 2. Terminate the plain chunk here. */
1179 obstack_1grow (&buffer->chunk_obstack, '\0');
1180 gcc_assert (chunk < PP_NL_ARGMAX * 2);
1181 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1182 break;
1185 if (ISDIGIT (*p))
1187 char *end;
1188 argno = strtoul (p, &end, 10) - 1;
1189 p = end;
1190 gcc_assert (*p == '$');
1191 p++;
1193 any_numbered = true;
1194 gcc_assert (!any_unnumbered);
1196 else
1198 argno = curarg++;
1199 any_unnumbered = true;
1200 gcc_assert (!any_numbered);
1202 gcc_assert (argno < PP_NL_ARGMAX);
1203 gcc_assert (!formatters[argno]);
1204 formatters[argno] = &args[chunk];
1207 obstack_1grow (&buffer->chunk_obstack, *p);
1208 p++;
1210 while (strchr ("qwl+#", p[-1]));
1212 if (p[-1] == '.')
1214 /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
1215 (where M == N + 1). */
1216 if (ISDIGIT (*p))
1220 obstack_1grow (&buffer->chunk_obstack, *p);
1221 p++;
1223 while (ISDIGIT (p[-1]));
1224 gcc_assert (p[-1] == 's');
1226 else
1228 gcc_assert (*p == '*');
1229 obstack_1grow (&buffer->chunk_obstack, '*');
1230 p++;
1232 if (ISDIGIT (*p))
1234 char *end;
1235 unsigned int argno2 = strtoul (p, &end, 10) - 1;
1236 p = end;
1237 gcc_assert (argno2 == argno - 1);
1238 gcc_assert (!any_unnumbered);
1239 gcc_assert (*p == '$');
1241 p++;
1242 formatters[argno2] = formatters[argno];
1244 else
1246 gcc_assert (!any_numbered);
1247 formatters[argno+1] = formatters[argno];
1248 curarg++;
1250 gcc_assert (*p == 's');
1251 obstack_1grow (&buffer->chunk_obstack, 's');
1252 p++;
1255 if (*p == '\0')
1256 break;
1258 obstack_1grow (&buffer->chunk_obstack, '\0');
1259 gcc_assert (chunk < PP_NL_ARGMAX * 2);
1260 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1263 obstack_1grow (&buffer->chunk_obstack, '\0');
1264 gcc_assert (chunk < PP_NL_ARGMAX * 2);
1265 args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1266 args[chunk] = 0;
1268 /* Set output to the argument obstack, and switch line-wrapping and
1269 prefixing off. */
1270 buffer->obstack = &buffer->chunk_obstack;
1271 const int old_line_length = buffer->line_length;
1272 old_wrapping_mode = pp_set_verbatim_wrapping (pp);
1274 /* Second phase. Replace each formatter with the formatted text it
1275 corresponds to. */
1277 for (argno = 0; formatters[argno]; argno++)
1279 int precision = 0;
1280 bool wide = false;
1281 bool plus = false;
1282 bool hash = false;
1283 bool quote = false;
1285 /* We do not attempt to enforce any ordering on the modifier
1286 characters. */
1288 for (p = *formatters[argno];; p++)
1290 switch (*p)
1292 case 'q':
1293 gcc_assert (!quote);
1294 quote = true;
1295 continue;
1297 case '+':
1298 gcc_assert (!plus);
1299 plus = true;
1300 continue;
1302 case '#':
1303 gcc_assert (!hash);
1304 hash = true;
1305 continue;
1307 case 'w':
1308 gcc_assert (!wide);
1309 wide = true;
1310 continue;
1312 case 'l':
1313 /* We don't support precision beyond that of "long long". */
1314 gcc_assert (precision < 2);
1315 precision++;
1316 continue;
1318 break;
1321 gcc_assert (!wide || precision == 0);
1323 if (quote)
1324 pp_begin_quote (pp, pp_show_color (pp));
1326 switch (*p)
1328 case 'r':
1329 pp_string (pp, colorize_start (pp_show_color (pp),
1330 va_arg (*text->args_ptr,
1331 const char *)));
1332 break;
1334 case 'c':
1336 /* When quoting, print alphanumeric, punctuation, and the space
1337 character unchanged, and all others in hexadecimal with the
1338 "\x" prefix. Otherwise print them all unchanged. */
1339 int chr = va_arg (*text->args_ptr, int);
1340 if (ISPRINT (chr) || !quote)
1341 pp_character (pp, chr);
1342 else
1344 const char str [2] = { chr, '\0' };
1345 pp_quoted_string (pp, str, 1);
1347 break;
1350 case 'd':
1351 case 'i':
1352 if (wide)
1353 pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
1354 else
1355 pp_integer_with_precision
1356 (pp, *text->args_ptr, precision, int, "d");
1357 break;
1359 case 'o':
1360 if (wide)
1361 pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
1362 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1363 else
1364 pp_integer_with_precision
1365 (pp, *text->args_ptr, precision, unsigned, "o");
1366 break;
1368 case 's':
1369 if (quote)
1370 pp_quoted_string (pp, va_arg (*text->args_ptr, const char *));
1371 else
1372 pp_string (pp, va_arg (*text->args_ptr, const char *));
1373 break;
1375 case 'p':
1376 pp_pointer (pp, va_arg (*text->args_ptr, void *));
1377 break;
1379 case 'u':
1380 if (wide)
1381 pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
1382 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1383 else
1384 pp_integer_with_precision
1385 (pp, *text->args_ptr, precision, unsigned, "u");
1386 break;
1388 case 'f':
1389 pp_double (pp, va_arg (*text->args_ptr, double));
1390 break;
1392 case 'Z':
1394 int *v = va_arg (*text->args_ptr, int *);
1395 unsigned len = va_arg (*text->args_ptr, unsigned);
1397 for (unsigned i = 0; i < len; ++i)
1399 pp_scalar (pp, "%i", v[i]);
1400 if (i < len - 1)
1402 pp_comma (pp);
1403 pp_space (pp);
1406 break;
1409 case 'x':
1410 if (wide)
1411 pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
1412 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1413 else
1414 pp_integer_with_precision
1415 (pp, *text->args_ptr, precision, unsigned, "x");
1416 break;
1418 case '.':
1420 int n;
1421 const char *s;
1423 /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
1424 (where M == N + 1). The format string should be verified
1425 already from the first phase. */
1426 p++;
1427 if (ISDIGIT (*p))
1429 char *end;
1430 n = strtoul (p, &end, 10);
1431 p = end;
1432 gcc_assert (*p == 's');
1434 else
1436 gcc_assert (*p == '*');
1437 p++;
1438 gcc_assert (*p == 's');
1439 n = va_arg (*text->args_ptr, int);
1441 /* This consumes a second entry in the formatters array. */
1442 gcc_assert (formatters[argno] == formatters[argno+1]);
1443 argno++;
1446 s = va_arg (*text->args_ptr, const char *);
1448 /* Append the lesser of precision and strlen (s) characters
1449 from the array (which need not be a nul-terminated string).
1450 Negative precision is treated as if it were omitted. */
1451 size_t len = n < 0 ? strlen (s) : strnlen (s, n);
1453 pp_append_text (pp, s, s + len);
1455 break;
1457 case '@':
1459 /* diagnostic_event_id_t *. */
1460 diagnostic_event_id_ptr event_id
1461 = va_arg (*text->args_ptr, diagnostic_event_id_ptr);
1462 gcc_assert (event_id->known_p ());
1464 pp_string (pp, colorize_start (pp_show_color (pp), "path"));
1465 pp_character (pp, '(');
1466 pp_decimal_int (pp, event_id->one_based ());
1467 pp_character (pp, ')');
1468 pp_string (pp, colorize_stop (pp_show_color (pp)));
1470 break;
1472 case '{':
1473 pp_begin_url (pp, va_arg (*text->args_ptr, const char *));
1474 break;
1476 default:
1478 bool ok;
1480 /* Call the format decoder.
1481 Pass the address of "quote" so that format decoders can
1482 potentially disable printing of the closing quote
1483 (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family
1484 of frontends). */
1485 gcc_assert (pp_format_decoder (pp));
1486 ok = pp_format_decoder (pp) (pp, text, p,
1487 precision, wide, plus, hash, &quote,
1488 formatters[argno]);
1489 gcc_assert (ok);
1493 if (quote)
1494 pp_end_quote (pp, pp_show_color (pp));
1496 obstack_1grow (&buffer->chunk_obstack, '\0');
1497 *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
1500 if (CHECKING_P)
1501 for (; argno < PP_NL_ARGMAX; argno++)
1502 gcc_assert (!formatters[argno]);
1504 /* If the client supplied a postprocessing object, call its "handle"
1505 hook here. */
1506 if (pp->m_format_postprocessor)
1507 pp->m_format_postprocessor->handle (pp);
1509 /* Revert to normal obstack and wrapping mode. */
1510 buffer->obstack = &buffer->formatted_obstack;
1511 buffer->line_length = old_line_length;
1512 pp_wrapping_mode (pp) = old_wrapping_mode;
1513 pp_clear_state (pp);
1516 /* Format of a message pointed to by TEXT. */
1517 void
1518 pp_output_formatted_text (pretty_printer *pp)
1520 unsigned int chunk;
1521 output_buffer *buffer = pp_buffer (pp);
1522 struct chunk_info *chunk_array = buffer->cur_chunk_array;
1523 const char **args = chunk_array->args;
1525 gcc_assert (buffer->obstack == &buffer->formatted_obstack);
1527 /* This is a third phase, first 2 phases done in pp_format_args.
1528 Now we actually print it. */
1529 for (chunk = 0; args[chunk]; chunk++)
1530 pp_string (pp, args[chunk]);
1532 /* Deallocate the chunk structure and everything after it (i.e. the
1533 associated series of formatted strings). */
1534 buffer->cur_chunk_array = chunk_array->prev;
1535 obstack_free (&buffer->chunk_obstack, chunk_array);
1538 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
1539 settings needed by BUFFER for a verbatim formatting. */
1540 void
1541 pp_format_verbatim (pretty_printer *pp, text_info *text)
1543 /* Set verbatim mode. */
1544 pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
1546 /* Do the actual formatting. */
1547 pp_format (pp, text);
1548 pp_output_formatted_text (pp);
1550 /* Restore previous settings. */
1551 pp_wrapping_mode (pp) = oldmode;
1554 /* Flush the content of BUFFER onto the attached stream. This
1555 function does nothing unless pp->output_buffer->flush_p. */
1556 void
1557 pp_flush (pretty_printer *pp)
1559 pp_clear_state (pp);
1560 if (!pp->buffer->flush_p)
1561 return;
1562 pp_write_text_to_stream (pp);
1563 fflush (pp_buffer (pp)->stream);
1566 /* Flush the content of BUFFER onto the attached stream independently
1567 of the value of pp->output_buffer->flush_p. */
1568 void
1569 pp_really_flush (pretty_printer *pp)
1571 pp_clear_state (pp);
1572 pp_write_text_to_stream (pp);
1573 fflush (pp_buffer (pp)->stream);
1576 /* Sets the number of maximum characters per line PRETTY-PRINTER can
1577 output in line-wrapping mode. A LENGTH value 0 suppresses
1578 line-wrapping. */
1579 void
1580 pp_set_line_maximum_length (pretty_printer *pp, int length)
1582 pp_line_cutoff (pp) = length;
1583 pp_set_real_maximum_length (pp);
1586 /* Clear PRETTY-PRINTER output area text info. */
1587 void
1588 pp_clear_output_area (pretty_printer *pp)
1590 obstack_free (pp_buffer (pp)->obstack,
1591 obstack_base (pp_buffer (pp)->obstack));
1592 pp_buffer (pp)->line_length = 0;
1595 /* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which
1596 will eventually be free-ed. */
1598 void
1599 pp_set_prefix (pretty_printer *pp, char *prefix)
1601 free (pp->prefix);
1602 pp->prefix = prefix;
1603 pp_set_real_maximum_length (pp);
1604 pp->emitted_prefix = false;
1605 pp_indentation (pp) = 0;
1608 /* Take ownership of PP's prefix, setting it to NULL.
1609 This allows clients to save, override, and then restore an existing
1610 prefix, without it being free-ed. */
1612 char *
1613 pp_take_prefix (pretty_printer *pp)
1615 char *result = pp->prefix;
1616 pp->prefix = NULL;
1617 return result;
1620 /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */
1621 void
1622 pp_destroy_prefix (pretty_printer *pp)
1624 if (pp->prefix != NULL)
1626 free (pp->prefix);
1627 pp->prefix = NULL;
1631 /* Write out PRETTY-PRINTER's prefix. */
1632 void
1633 pp_emit_prefix (pretty_printer *pp)
1635 if (pp->prefix != NULL)
1637 switch (pp_prefixing_rule (pp))
1639 default:
1640 case DIAGNOSTICS_SHOW_PREFIX_NEVER:
1641 break;
1643 case DIAGNOSTICS_SHOW_PREFIX_ONCE:
1644 if (pp->emitted_prefix)
1646 pp_indent (pp);
1647 break;
1649 pp_indentation (pp) += 3;
1650 /* Fall through. */
1652 case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
1654 int prefix_length = strlen (pp->prefix);
1655 pp_append_r (pp, pp->prefix, prefix_length);
1656 pp->emitted_prefix = true;
1658 break;
1663 /* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line. */
1665 pretty_printer::pretty_printer (int maximum_length)
1666 : buffer (new (XCNEW (output_buffer)) output_buffer ()),
1667 prefix (),
1668 padding (pp_none),
1669 maximum_length (),
1670 indent_skip (),
1671 wrapping (),
1672 format_decoder (),
1673 m_format_postprocessor (NULL),
1674 emitted_prefix (),
1675 need_newline (),
1676 translate_identifiers (true),
1677 show_color (),
1678 url_format (URL_FORMAT_NONE)
1680 pp_line_cutoff (this) = maximum_length;
1681 /* By default, we emit prefixes once per message. */
1682 pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
1683 pp_set_prefix (this, NULL);
1686 /* Copy constructor for pretty_printer. */
1688 pretty_printer::pretty_printer (const pretty_printer &other)
1689 : buffer (new (XCNEW (output_buffer)) output_buffer ()),
1690 prefix (),
1691 padding (other.padding),
1692 maximum_length (other.maximum_length),
1693 indent_skip (other.indent_skip),
1694 wrapping (other.wrapping),
1695 format_decoder (other.format_decoder),
1696 m_format_postprocessor (NULL),
1697 emitted_prefix (other.emitted_prefix),
1698 need_newline (other.need_newline),
1699 translate_identifiers (other.translate_identifiers),
1700 show_color (other.show_color),
1701 url_format (other.url_format)
1703 pp_line_cutoff (this) = maximum_length;
1704 /* By default, we emit prefixes once per message. */
1705 pp_prefixing_rule (this) = pp_prefixing_rule (&other);
1706 pp_set_prefix (this, NULL);
1708 if (other.m_format_postprocessor)
1709 m_format_postprocessor = other.m_format_postprocessor->clone ();
1712 pretty_printer::~pretty_printer ()
1714 if (m_format_postprocessor)
1715 delete m_format_postprocessor;
1716 buffer->~output_buffer ();
1717 XDELETE (buffer);
1718 free (prefix);
1721 /* Base class implementation of pretty_printer::clone vfunc. */
1723 pretty_printer *
1724 pretty_printer::clone () const
1726 return new pretty_printer (*this);
1729 /* Append a string delimited by START and END to the output area of
1730 PRETTY-PRINTER. No line wrapping is done. However, if beginning a
1731 new line then emit PRETTY-PRINTER's prefix and skip any leading
1732 whitespace if appropriate. The caller must ensure that it is
1733 safe to do so. */
1734 void
1735 pp_append_text (pretty_printer *pp, const char *start, const char *end)
1737 /* Emit prefix and skip whitespace if we're starting a new line. */
1738 if (pp_buffer (pp)->line_length == 0)
1740 pp_emit_prefix (pp);
1741 if (pp_is_wrapping_line (pp))
1742 while (start != end && *start == ' ')
1743 ++start;
1745 pp_append_r (pp, start, end - start);
1748 /* Finishes constructing a NULL-terminated character string representing
1749 the PRETTY-PRINTED text. */
1750 const char *
1751 pp_formatted_text (pretty_printer *pp)
1753 return output_buffer_formatted_text (pp_buffer (pp));
1756 /* Return a pointer to the last character emitted in PRETTY-PRINTER's
1757 output area. A NULL pointer means no character available. */
1758 const char *
1759 pp_last_position_in_text (const pretty_printer *pp)
1761 return output_buffer_last_position_in_text (pp_buffer (pp));
1764 /* Return the amount of characters PRETTY-PRINTER can accept to
1765 make a full line. Meaningful only in line-wrapping mode. */
1767 pp_remaining_character_count_for_line (pretty_printer *pp)
1769 return pp->maximum_length - pp_buffer (pp)->line_length;
1773 /* Format a message into BUFFER a la printf. */
1774 void
1775 pp_printf (pretty_printer *pp, const char *msg, ...)
1777 text_info text;
1778 va_list ap;
1780 va_start (ap, msg);
1781 text.err_no = errno;
1782 text.args_ptr = &ap;
1783 text.format_spec = msg;
1784 pp_format (pp, &text);
1785 pp_output_formatted_text (pp);
1786 va_end (ap);
1790 /* Output MESSAGE verbatim into BUFFER. */
1791 void
1792 pp_verbatim (pretty_printer *pp, const char *msg, ...)
1794 text_info text;
1795 va_list ap;
1797 va_start (ap, msg);
1798 text.err_no = errno;
1799 text.args_ptr = &ap;
1800 text.format_spec = msg;
1801 pp_format_verbatim (pp, &text);
1802 va_end (ap);
1807 /* Have PRETTY-PRINTER start a new line. */
1808 void
1809 pp_newline (pretty_printer *pp)
1811 obstack_1grow (pp_buffer (pp)->obstack, '\n');
1812 pp_needs_newline (pp) = false;
1813 pp_buffer (pp)->line_length = 0;
1816 /* Have PRETTY-PRINTER add a CHARACTER. */
1817 void
1818 pp_character (pretty_printer *pp, int c)
1820 if (pp_is_wrapping_line (pp)
1821 /* If printing UTF-8, don't wrap in the middle of a sequence. */
1822 && (((unsigned int) c) & 0xC0) != 0x80
1823 && pp_remaining_character_count_for_line (pp) <= 0)
1825 pp_newline (pp);
1826 if (ISSPACE (c))
1827 return;
1829 obstack_1grow (pp_buffer (pp)->obstack, c);
1830 ++pp_buffer (pp)->line_length;
1833 /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
1834 be line-wrapped if in appropriate mode. */
1835 void
1836 pp_string (pretty_printer *pp, const char *str)
1838 gcc_checking_assert (str);
1839 pp_maybe_wrap_text (pp, str, str + strlen (str));
1842 /* Append the leading N characters of STRING to the output area of
1843 PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
1844 Setting N = -1 is as if N were set to strlen (STRING). The STRING
1845 may be line-wrapped if in appropriate mode. */
1846 static void
1847 pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
1849 gcc_checking_assert (str);
1851 const char *last = str;
1852 const char *ps;
1854 /* Compute the length if not specified. */
1855 if (n == (size_t) -1)
1856 n = strlen (str);
1858 for (ps = str; n; ++ps, --n)
1860 if (ISPRINT (*ps))
1861 continue;
1863 /* Don't escape a valid UTF-8 extended char. */
1864 const unsigned char *ups = (const unsigned char *) ps;
1865 if (*ups & 0x80)
1867 unsigned int extended_char;
1868 const int valid_utf8_len = decode_utf8_char (ups, n, &extended_char);
1869 if (valid_utf8_len > 0)
1871 ps += valid_utf8_len - 1;
1872 n -= valid_utf8_len - 1;
1873 continue;
1877 if (last < ps)
1878 pp_maybe_wrap_text (pp, last, ps);
1880 /* Append the hexadecimal value of the character. Allocate a buffer
1881 that's large enough for a 32-bit char plus the hex prefix. */
1882 char buf [11];
1883 int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
1884 pp_maybe_wrap_text (pp, buf, buf + n);
1885 last = ps + 1;
1888 pp_maybe_wrap_text (pp, last, ps);
1891 /* Maybe print out a whitespace if needed. */
1893 void
1894 pp_maybe_space (pretty_printer *pp)
1896 if (pp->padding != pp_none)
1898 pp_space (pp);
1899 pp->padding = pp_none;
1903 // Add a newline to the pretty printer PP and flush formatted text.
1905 void
1906 pp_newline_and_flush (pretty_printer *pp)
1908 pp_newline (pp);
1909 pp_flush (pp);
1910 pp_needs_newline (pp) = false;
1913 // Add a newline to the pretty printer PP, followed by indentation.
1915 void
1916 pp_newline_and_indent (pretty_printer *pp, int n)
1918 pp_indentation (pp) += n;
1919 pp_newline (pp);
1920 pp_indent (pp);
1921 pp_needs_newline (pp) = false;
1924 // Add separator C, followed by a single whitespace.
1926 void
1927 pp_separate_with (pretty_printer *pp, char c)
1929 pp_character (pp, c);
1930 pp_space (pp);
1933 /* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
1934 using the "quote" color. */
1936 void
1937 pp_begin_quote (pretty_printer *pp, bool show_color)
1939 pp_string (pp, open_quote);
1940 pp_string (pp, colorize_start (show_color, "quote"));
1943 /* If SHOW_COLOR is true, stop colorizing.
1944 Add a localized close quote. */
1946 void
1947 pp_end_quote (pretty_printer *pp, bool show_color)
1949 pp_string (pp, colorize_stop (show_color));
1950 pp_string (pp, close_quote);
1954 /* The string starting at P has LEN (at least 1) bytes left; if they
1955 start with a valid UTF-8 sequence, return the length of that
1956 sequence and set *VALUE to the value of that sequence, and
1957 otherwise return 0 and set *VALUE to (unsigned int) -1. */
1959 static int
1960 decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
1962 unsigned int t = *p;
1964 if (len == 0)
1965 abort ();
1966 if (t & 0x80)
1968 size_t utf8_len = 0;
1969 unsigned int ch;
1970 size_t i;
1971 for (t = *p; t & 0x80; t <<= 1)
1972 utf8_len++;
1974 if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
1976 *value = (unsigned int) -1;
1977 return 0;
1979 ch = *p & ((1 << (7 - utf8_len)) - 1);
1980 for (i = 1; i < utf8_len; i++)
1982 unsigned int u = p[i];
1983 if ((u & 0xC0) != 0x80)
1985 *value = (unsigned int) -1;
1986 return 0;
1988 ch = (ch << 6) | (u & 0x3F);
1990 if ( (ch <= 0x7F && utf8_len > 1)
1991 || (ch <= 0x7FF && utf8_len > 2)
1992 || (ch <= 0xFFFF && utf8_len > 3)
1993 || (ch <= 0x1FFFFF && utf8_len > 4)
1994 || (ch <= 0x3FFFFFF && utf8_len > 5)
1995 || (ch >= 0xD800 && ch <= 0xDFFF))
1997 *value = (unsigned int) -1;
1998 return 0;
2000 *value = ch;
2001 return utf8_len;
2003 else
2005 *value = t;
2006 return 1;
2010 /* Allocator for identifier_to_locale and corresponding function to
2011 free memory. */
2013 void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
2014 void (*identifier_to_locale_free) (void *) = free;
2016 /* Given IDENT, an identifier in the internal encoding, return a
2017 version of IDENT suitable for diagnostics in the locale character
2018 set: either IDENT itself, or a string, allocated using
2019 identifier_to_locale_alloc, converted to the locale character set
2020 and using escape sequences if not representable in the locale
2021 character set or containing control characters or invalid byte
2022 sequences. Existing backslashes in IDENT are not doubled, so the
2023 result may not uniquely specify the contents of an arbitrary byte
2024 sequence identifier. */
2026 const char *
2027 identifier_to_locale (const char *ident)
2029 const unsigned char *uid = (const unsigned char *) ident;
2030 size_t idlen = strlen (ident);
2031 bool valid_printable_utf8 = true;
2032 bool all_ascii = true;
2033 size_t i;
2035 for (i = 0; i < idlen;)
2037 unsigned int c;
2038 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2039 if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
2041 valid_printable_utf8 = false;
2042 break;
2044 if (utf8_len > 1)
2045 all_ascii = false;
2046 i += utf8_len;
2049 /* If IDENT contains invalid UTF-8 sequences (which may occur with
2050 attributes putting arbitrary byte sequences in identifiers), or
2051 control characters, we use octal escape sequences for all bytes
2052 outside printable ASCII. */
2053 if (!valid_printable_utf8)
2055 char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
2056 char *p = ret;
2057 for (i = 0; i < idlen; i++)
2059 if (uid[i] > 0x1F && uid[i] < 0x7F)
2060 *p++ = uid[i];
2061 else
2063 sprintf (p, "\\%03o", uid[i]);
2064 p += 4;
2067 *p = 0;
2068 return ret;
2071 /* Otherwise, if it is valid printable ASCII, or printable UTF-8
2072 with the locale character set being UTF-8, IDENT is used. */
2073 if (all_ascii || locale_utf8)
2074 return ident;
2076 /* Otherwise IDENT is converted to the locale character set if
2077 possible. */
2078 #if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
2079 if (locale_encoding != NULL)
2081 iconv_t cd = iconv_open (locale_encoding, "UTF-8");
2082 bool conversion_ok = true;
2083 char *ret = NULL;
2084 if (cd != (iconv_t) -1)
2086 size_t ret_alloc = 4 * idlen + 1;
2087 for (;;)
2089 /* Repeat the whole conversion process as needed with
2090 larger buffers so non-reversible transformations can
2091 always be detected. */
2092 ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
2093 char *outbuf;
2094 size_t inbytesleft = idlen;
2095 size_t outbytesleft = ret_alloc - 1;
2096 size_t iconv_ret;
2098 ret = (char *) identifier_to_locale_alloc (ret_alloc);
2099 outbuf = ret;
2101 if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
2103 conversion_ok = false;
2104 break;
2107 iconv_ret = iconv (cd, &inbuf, &inbytesleft,
2108 &outbuf, &outbytesleft);
2109 if (iconv_ret == (size_t) -1 || inbytesleft != 0)
2111 if (errno == E2BIG)
2113 ret_alloc *= 2;
2114 identifier_to_locale_free (ret);
2115 ret = NULL;
2116 continue;
2118 else
2120 conversion_ok = false;
2121 break;
2124 else if (iconv_ret != 0)
2126 conversion_ok = false;
2127 break;
2129 /* Return to initial shift state. */
2130 if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
2132 if (errno == E2BIG)
2134 ret_alloc *= 2;
2135 identifier_to_locale_free (ret);
2136 ret = NULL;
2137 continue;
2139 else
2141 conversion_ok = false;
2142 break;
2145 *outbuf = 0;
2146 break;
2148 iconv_close (cd);
2149 if (conversion_ok)
2150 return ret;
2153 #endif
2155 /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */
2157 char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
2158 char *p = ret;
2159 for (i = 0; i < idlen;)
2161 unsigned int c;
2162 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2163 if (utf8_len == 1)
2164 *p++ = uid[i];
2165 else
2167 sprintf (p, "\\U%08x", c);
2168 p += 10;
2170 i += utf8_len;
2172 *p = 0;
2173 return ret;
2177 /* Support for encoding URLs.
2178 See egmontkob/Hyperlinks_in_Terminal_Emulators.md
2179 ( https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda ).
2181 > A hyperlink is opened upon encountering an OSC 8 escape sequence with
2182 > the target URI. The syntax is
2184 > OSC 8 ; params ; URI ST
2186 > A hyperlink is closed with the same escape sequence, omitting the
2187 > parameters and the URI but keeping the separators:
2189 > OSC 8 ; ; ST
2191 > OSC (operating system command) is typically ESC ].
2193 Use BEL instead of ST, as that is currently rendered better in some
2194 terminal emulators that don't support OSC 8, like konsole. */
2196 /* If URL-printing is enabled, write an "open URL" escape sequence to PP
2197 for the given URL. */
2199 void
2200 pp_begin_url (pretty_printer *pp, const char *url)
2202 switch (pp->url_format)
2204 case URL_FORMAT_NONE:
2205 break;
2206 case URL_FORMAT_ST:
2207 pp_string (pp, "\33]8;;");
2208 pp_string (pp, url);
2209 pp_string (pp, "\33\\");
2210 break;
2211 case URL_FORMAT_BEL:
2212 pp_string (pp, "\33]8;;");
2213 pp_string (pp, url);
2214 pp_string (pp, "\a");
2215 break;
2216 default:
2217 gcc_unreachable ();
2221 /* Helper function for pp_end_url and pp_format, return the "close URL" escape
2222 sequence string. */
2224 static const char *
2225 get_end_url_string (pretty_printer *pp)
2227 switch (pp->url_format)
2229 case URL_FORMAT_NONE:
2230 return "";
2231 case URL_FORMAT_ST:
2232 return "\33]8;;\33\\";
2233 case URL_FORMAT_BEL:
2234 return "\33]8;;\a";
2235 default:
2236 gcc_unreachable ();
2240 /* If URL-printing is enabled, write a "close URL" escape sequence to PP. */
2242 void
2243 pp_end_url (pretty_printer *pp)
2245 if (pp->url_format != URL_FORMAT_NONE)
2246 pp_string (pp, get_end_url_string (pp));
2249 #if CHECKING_P
2251 namespace selftest {
2253 /* Smoketest for pretty_printer. */
2255 static void
2256 test_basic_printing ()
2258 pretty_printer pp;
2259 pp_string (&pp, "hello");
2260 pp_space (&pp);
2261 pp_string (&pp, "world");
2263 ASSERT_STREQ ("hello world", pp_formatted_text (&pp));
2266 /* Helper function for testing pp_format.
2267 Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2268 prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */
2270 static void
2271 assert_pp_format_va (const location &loc, const char *expected,
2272 bool show_color, const char *fmt, va_list *ap)
2274 pretty_printer pp;
2275 text_info ti;
2276 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2278 ti.format_spec = fmt;
2279 ti.args_ptr = ap;
2280 ti.err_no = 0;
2281 ti.x_data = NULL;
2282 ti.m_richloc = &rich_loc;
2284 pp_show_color (&pp) = show_color;
2285 pp_format (&pp, &ti);
2286 pp_output_formatted_text (&pp);
2287 ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
2290 /* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2291 prints EXPECTED, with show_color disabled. */
2293 static void
2294 assert_pp_format (const location &loc, const char *expected,
2295 const char *fmt, ...)
2297 va_list ap;
2299 va_start (ap, fmt);
2300 assert_pp_format_va (loc, expected, false, fmt, &ap);
2301 va_end (ap);
2304 /* As above, but with colorization enabled. */
2306 static void
2307 assert_pp_format_colored (const location &loc, const char *expected,
2308 const char *fmt, ...)
2310 /* The tests of colorization assume the default color scheme.
2311 If GCC_COLORS is set, then the colors have potentially been
2312 overridden; skip the test. */
2313 if (getenv ("GCC_COLORS"))
2314 return;
2316 va_list ap;
2318 va_start (ap, fmt);
2319 assert_pp_format_va (loc, expected, true, fmt, &ap);
2320 va_end (ap);
2323 /* Helper function for calling testing pp_format,
2324 by calling assert_pp_format with various numbers of arguments.
2325 These exist mostly to avoid having to write SELFTEST_LOCATION
2326 throughout test_pp_format. */
2328 #define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \
2329 SELFTEST_BEGIN_STMT \
2330 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2331 (ARG1)); \
2332 SELFTEST_END_STMT
2334 #define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \
2335 SELFTEST_BEGIN_STMT \
2336 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2337 (ARG1), (ARG2)); \
2338 SELFTEST_END_STMT
2340 #define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \
2341 SELFTEST_BEGIN_STMT \
2342 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2343 (ARG1), (ARG2), (ARG3)); \
2344 SELFTEST_END_STMT
2346 /* Verify that pp_format works, for various format codes. */
2348 static void
2349 test_pp_format ()
2351 /* Avoid introducing locale-specific differences in the results
2352 by hardcoding open_quote and close_quote. */
2353 auto_fix_quotes fix_quotes;
2355 /* Verify that plain text is passed through unchanged. */
2356 assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted");
2358 /* Verify various individual format codes, in the order listed in the
2359 comment for pp_format above. For each code, we append a second
2360 argument with a known bit pattern (0x12345678), to ensure that we
2361 are consuming arguments correctly. */
2362 ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678);
2363 ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678);
2364 ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678);
2365 ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678);
2366 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678);
2367 ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678);
2368 ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678);
2369 ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678);
2370 ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678);
2371 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe,
2372 0x12345678);
2373 ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678);
2374 ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678);
2375 ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678);
2376 ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678);
2377 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe,
2378 0x12345678);
2379 ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678);
2380 ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678);
2381 ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10,
2382 0x12345678);
2383 ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
2384 ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
2385 0x12345678);
2386 ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
2387 ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
2388 ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
2389 0x12345678);
2391 /* Not nul-terminated. */
2392 char arr[5] = { '1', '2', '3', '4', '5' };
2393 ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678);
2394 ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678);
2395 ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678);
2397 /* We can't test for %p; the pointer is printed in an implementation-defined
2398 manner. */
2399 ASSERT_PP_FORMAT_2 ("normal colored normal 12345678",
2400 "normal %rcolored%R normal %x",
2401 "error", 0x12345678);
2402 assert_pp_format_colored
2403 (SELFTEST_LOCATION,
2404 "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678",
2405 "normal %rcolored%R normal %x", "error", 0x12345678);
2406 /* TODO:
2407 %m: strerror(text->err_no) - does not consume a value from args_ptr. */
2408 ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678);
2409 ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678);
2410 ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678);
2411 ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678);
2412 ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678);
2413 ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678);
2415 /* Verify flag 'q'. */
2416 ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678);
2417 assert_pp_format_colored (SELFTEST_LOCATION,
2418 "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
2419 "foo", 0x12345678);
2420 /* Verify "%@". */
2422 diagnostic_event_id_t first (2);
2423 diagnostic_event_id_t second (7);
2425 ASSERT_PP_FORMAT_2 ("first `free' at (3); second `free' at (8)",
2426 "first %<free%> at %@; second %<free%> at %@",
2427 &first, &second);
2428 assert_pp_format_colored
2429 (SELFTEST_LOCATION,
2430 "first `\e[01m\e[Kfree\e[m\e[K' at \e[01;36m\e[K(3)\e[m\e[K;"
2431 " second `\e[01m\e[Kfree\e[m\e[K' at \e[01;36m\e[K(8)\e[m\e[K",
2432 "first %<free%> at %@; second %<free%> at %@",
2433 &first, &second);
2436 /* Verify %Z. */
2437 int v[] = { 1, 2, 3 };
2438 ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
2440 int v2[] = { 0 };
2441 ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
2443 /* Verify that combinations work, along with unformatted text. */
2444 assert_pp_format (SELFTEST_LOCATION,
2445 "the quick brown fox jumps over the lazy dog",
2446 "the %s %s %s jumps over the %s %s",
2447 "quick", "brown", "fox", "lazy", "dog");
2448 assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7);
2449 assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10",
2450 "problem with %qs at line %i", "bar", 10);
2453 /* A subclass of pretty_printer for use by test_prefixes_and_wrapping. */
2455 class test_pretty_printer : public pretty_printer
2457 public:
2458 test_pretty_printer (enum diagnostic_prefixing_rule_t rule,
2459 int max_line_length)
2461 pp_set_prefix (this, xstrdup ("PREFIX: "));
2462 wrapping.rule = rule;
2463 pp_set_line_maximum_length (this, max_line_length);
2467 /* Verify that the various values of enum diagnostic_prefixing_rule_t work
2468 as expected, with and without line wrapping. */
2470 static void
2471 test_prefixes_and_wrapping ()
2473 /* Tests of the various prefixing rules, without wrapping.
2474 Newlines embedded in pp_string don't affect it; we have to
2475 explicitly call pp_newline. */
2477 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 0);
2478 pp_string (&pp, "the quick brown fox");
2479 pp_newline (&pp);
2480 pp_string (&pp, "jumps over the lazy dog");
2481 pp_newline (&pp);
2482 ASSERT_STREQ (pp_formatted_text (&pp),
2483 "PREFIX: the quick brown fox\n"
2484 " jumps over the lazy dog\n");
2487 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 0);
2488 pp_string (&pp, "the quick brown fox");
2489 pp_newline (&pp);
2490 pp_string (&pp, "jumps over the lazy dog");
2491 pp_newline (&pp);
2492 ASSERT_STREQ (pp_formatted_text (&pp),
2493 "the quick brown fox\n"
2494 "jumps over the lazy dog\n");
2497 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 0);
2498 pp_string (&pp, "the quick brown fox");
2499 pp_newline (&pp);
2500 pp_string (&pp, "jumps over the lazy dog");
2501 pp_newline (&pp);
2502 ASSERT_STREQ (pp_formatted_text (&pp),
2503 "PREFIX: the quick brown fox\n"
2504 "PREFIX: jumps over the lazy dog\n");
2507 /* Tests of the various prefixing rules, with wrapping. */
2509 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 20);
2510 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2511 pp_newline (&pp);
2512 pp_string (&pp, "able was I ere I saw elba");
2513 pp_newline (&pp);
2514 ASSERT_STREQ (pp_formatted_text (&pp),
2515 "PREFIX: the quick \n"
2516 " brown fox jumps \n"
2517 " over the lazy \n"
2518 " dog\n"
2519 " able was I ere I \n"
2520 " saw elba\n");
2523 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 20);
2524 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2525 pp_newline (&pp);
2526 pp_string (&pp, "able was I ere I saw elba");
2527 pp_newline (&pp);
2528 ASSERT_STREQ (pp_formatted_text (&pp),
2529 "the quick brown fox \n"
2530 "jumps over the lazy \n"
2531 "dog\n"
2532 "able was I ere I \n"
2533 "saw elba\n");
2536 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 20);
2537 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2538 pp_newline (&pp);
2539 pp_string (&pp, "able was I ere I saw elba");
2540 pp_newline (&pp);
2541 ASSERT_STREQ (pp_formatted_text (&pp),
2542 "PREFIX: the quick brown fox jumps over the lazy dog\n"
2543 "PREFIX: able was I ere I saw elba\n");
2548 /* Verify that URL-printing works as expected. */
2550 void
2551 test_urls ()
2554 pretty_printer pp;
2555 pp.url_format = URL_FORMAT_NONE;
2556 pp_begin_url (&pp, "http://example.com");
2557 pp_string (&pp, "This is a link");
2558 pp_end_url (&pp);
2559 ASSERT_STREQ ("This is a link",
2560 pp_formatted_text (&pp));
2564 pretty_printer pp;
2565 pp.url_format = URL_FORMAT_ST;
2566 pp_begin_url (&pp, "http://example.com");
2567 pp_string (&pp, "This is a link");
2568 pp_end_url (&pp);
2569 ASSERT_STREQ ("\33]8;;http://example.com\33\\This is a link\33]8;;\33\\",
2570 pp_formatted_text (&pp));
2574 pretty_printer pp;
2575 pp.url_format = URL_FORMAT_BEL;
2576 pp_begin_url (&pp, "http://example.com");
2577 pp_string (&pp, "This is a link");
2578 pp_end_url (&pp);
2579 ASSERT_STREQ ("\33]8;;http://example.com\aThis is a link\33]8;;\a",
2580 pp_formatted_text (&pp));
2584 /* Test multibyte awareness. */
2585 static void test_utf8 ()
2588 /* Check that pp_quoted_string leaves valid UTF-8 alone. */
2590 pretty_printer pp;
2591 const char *s = "\xf0\x9f\x98\x82";
2592 pp_quoted_string (&pp, s);
2593 ASSERT_STREQ (pp_formatted_text (&pp), s);
2596 /* Check that pp_quoted_string escapes non-UTF-8 nonprintable bytes. */
2598 pretty_printer pp;
2599 pp_quoted_string (&pp, "\xf0!\x9f\x98\x82");
2600 ASSERT_STREQ (pp_formatted_text (&pp),
2601 "\\xf0!\\x9f\\x98\\x82");
2604 /* Check that pp_character will line-wrap at the beginning of a UTF-8
2605 sequence, but not in the middle. */
2607 pretty_printer pp (3);
2608 const char s[] = "---\xf0\x9f\x98\x82";
2609 for (int i = 0; i != sizeof (s) - 1; ++i)
2610 pp_character (&pp, s[i]);
2611 pp_newline (&pp);
2612 for (int i = 1; i != sizeof (s) - 1; ++i)
2613 pp_character (&pp, s[i]);
2614 pp_character (&pp, '-');
2615 ASSERT_STREQ (pp_formatted_text (&pp),
2616 "---\n"
2617 "\xf0\x9f\x98\x82\n"
2618 "--\xf0\x9f\x98\x82\n"
2619 "-");
2624 /* Run all of the selftests within this file. */
2626 void
2627 pretty_print_cc_tests ()
2629 test_basic_printing ();
2630 test_pp_format ();
2631 test_prefixes_and_wrapping ();
2632 test_urls ();
2633 test_utf8 ();
2636 } // namespace selftest
2638 #endif /* CHECKING_P */