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