]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/pretty-print.c
rs6000: Use symbolic names for the CR fields in more cases
[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
368877a1
DM
1593/* Copy constructor for pretty_printer. */
1594
1595pretty_printer::pretty_printer (const pretty_printer &other)
1596: buffer (new (XCNEW (output_buffer)) output_buffer ()),
1597 prefix (),
1598 padding (other.padding),
1599 maximum_length (other.maximum_length),
1600 indent_skip (other.indent_skip),
1601 wrapping (other.wrapping),
1602 format_decoder (other.format_decoder),
1603 m_format_postprocessor (NULL),
1604 emitted_prefix (other.emitted_prefix),
1605 need_newline (other.need_newline),
1606 translate_identifiers (other.translate_identifiers),
1607 show_color (other.show_color),
1608 show_urls (other.show_urls)
1609{
1610 pp_line_cutoff (this) = maximum_length;
1611 /* By default, we emit prefixes once per message. */
1612 pp_prefixing_rule (this) = pp_prefixing_rule (&other);
1613 pp_set_prefix (this, NULL);
1614
1615 if (other.m_format_postprocessor)
1616 m_format_postprocessor = other.m_format_postprocessor->clone ();
1617}
1618
025311c4
GDR
1619pretty_printer::~pretty_printer ()
1620{
f012c8ef
DM
1621 if (m_format_postprocessor)
1622 delete m_format_postprocessor;
025311c4
GDR
1623 buffer->~output_buffer ();
1624 XDELETE (buffer);
653fee19 1625 free (prefix);
025311c4
GDR
1626}
1627
368877a1
DM
1628/* Base class implementation of pretty_printer::clone vfunc. */
1629
1630pretty_printer *
1631pretty_printer::clone () const
1632{
1633 return new pretty_printer (*this);
1634}
1635
b6fe0bb8
GDR
1636/* Append a string delimited by START and END to the output area of
1637 PRETTY-PRINTER. No line wrapping is done. However, if beginning a
1638 new line then emit PRETTY-PRINTER's prefix and skip any leading
1639 whitespace if appropriate. The caller must ensure that it is
1640 safe to do so. */
1641void
b066401f 1642pp_append_text (pretty_printer *pp, const char *start, const char *end)
b6fe0bb8
GDR
1643{
1644 /* Emit prefix and skip whitespace if we're starting a new line. */
025311c4 1645 if (pp_buffer (pp)->line_length == 0)
b6fe0bb8
GDR
1646 {
1647 pp_emit_prefix (pp);
1648 if (pp_is_wrapping_line (pp))
1649 while (start != end && *start == ' ')
1650 ++start;
1651 }
1652 pp_append_r (pp, start, end - start);
1653}
1654
1655/* Finishes constructing a NULL-terminated character string representing
1656 the PRETTY-PRINTED text. */
1657const char *
b066401f 1658pp_formatted_text (pretty_printer *pp)
b6fe0bb8 1659{
c4100eae 1660 return output_buffer_formatted_text (pp_buffer (pp));
b6fe0bb8
GDR
1661}
1662
1663/* Return a pointer to the last character emitted in PRETTY-PRINTER's
1664 output area. A NULL pointer means no character available. */
1665const char *
b066401f 1666pp_last_position_in_text (const pretty_printer *pp)
b6fe0bb8 1667{
c4100eae 1668 return output_buffer_last_position_in_text (pp_buffer (pp));
b6fe0bb8
GDR
1669}
1670
1671/* Return the amount of characters PRETTY-PRINTER can accept to
ba228239 1672 make a full line. Meaningful only in line-wrapping mode. */
b6fe0bb8 1673int
b066401f 1674pp_remaining_character_count_for_line (pretty_printer *pp)
b6fe0bb8 1675{
025311c4 1676 return pp->maximum_length - pp_buffer (pp)->line_length;
b6fe0bb8
GDR
1677}
1678
1679
1680/* Format a message into BUFFER a la printf. */
1681void
1682pp_printf (pretty_printer *pp, const char *msg, ...)
1683{
1684 text_info text;
1685 va_list ap;
1686
1687 va_start (ap, msg);
1688 text.err_no = errno;
1689 text.args_ptr = &ap;
1690 text.format_spec = msg;
39ce81c9
ZW
1691 pp_format (pp, &text);
1692 pp_output_formatted_text (pp);
b6fe0bb8
GDR
1693 va_end (ap);
1694}
1695
1696
1697/* Output MESSAGE verbatim into BUFFER. */
1698void
1699pp_verbatim (pretty_printer *pp, const char *msg, ...)
1700{
1701 text_info text;
1702 va_list ap;
1703
1704 va_start (ap, msg);
1705 text.err_no = errno;
1706 text.args_ptr = &ap;
1707 text.format_spec = msg;
1708 pp_format_verbatim (pp, &text);
1709 va_end (ap);
1710}
1711
1712
1713
1714/* Have PRETTY-PRINTER start a new line. */
1715void
b066401f 1716pp_newline (pretty_printer *pp)
b6fe0bb8 1717{
025311c4 1718 obstack_1grow (pp_buffer (pp)->obstack, '\n');
c4669594 1719 pp_needs_newline (pp) = false;
025311c4 1720 pp_buffer (pp)->line_length = 0;
b6fe0bb8
GDR
1721}
1722
1723/* Have PRETTY-PRINTER add a CHARACTER. */
1724void
b066401f 1725pp_character (pretty_printer *pp, int c)
b6fe0bb8
GDR
1726{
1727 if (pp_is_wrapping_line (pp)
ddd0fd17
LH
1728 /* If printing UTF-8, don't wrap in the middle of a sequence. */
1729 && (((unsigned int) c) & 0xC0) != 0x80
b6fe0bb8
GDR
1730 && pp_remaining_character_count_for_line (pp) <= 0)
1731 {
1732 pp_newline (pp);
1733 if (ISSPACE (c))
1734 return;
1735 }
025311c4
GDR
1736 obstack_1grow (pp_buffer (pp)->obstack, c);
1737 ++pp_buffer (pp)->line_length;
b6fe0bb8
GDR
1738}
1739
1740/* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
1741 be line-wrapped if in appropriate mode. */
1742void
b066401f 1743pp_string (pretty_printer *pp, const char *str)
b6fe0bb8 1744{
41d9f1e0
MLI
1745 gcc_checking_assert (str);
1746 pp_maybe_wrap_text (pp, str, str + strlen (str));
b6fe0bb8
GDR
1747}
1748
3f0177e7
MS
1749/* Append the leading N characters of STRING to the output area of
1750 PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
1751 Setting N = -1 is as if N were set to strlen (STRING). The STRING
1752 may be line-wrapped if in appropriate mode. */
1753static void
1754pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
1755{
1756 gcc_checking_assert (str);
1757
1758 const char *last = str;
1759 const char *ps;
1760
1761 /* Compute the length if not specified. */
1762 if (n == (size_t) -1)
1763 n = strlen (str);
1764
1765 for (ps = str; n; ++ps, --n)
1766 {
1767 if (ISPRINT (*ps))
1768 continue;
1769
ddd0fd17
LH
1770 /* Don't escape a valid UTF-8 extended char. */
1771 const unsigned char *ups = (const unsigned char *) ps;
1772 if (*ups & 0x80)
1773 {
1774 unsigned int extended_char;
1775 const int valid_utf8_len = decode_utf8_char (ups, n, &extended_char);
1776 if (valid_utf8_len > 0)
1777 {
1778 ps += valid_utf8_len - 1;
1779 n -= valid_utf8_len - 1;
1780 continue;
1781 }
1782 }
1783
3f0177e7 1784 if (last < ps)
ddd0fd17 1785 pp_maybe_wrap_text (pp, last, ps);
3f0177e7
MS
1786
1787 /* Append the hexadecimal value of the character. Allocate a buffer
1788 that's large enough for a 32-bit char plus the hex prefix. */
1789 char buf [11];
1790 int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
1791 pp_maybe_wrap_text (pp, buf, buf + n);
1792 last = ps + 1;
1793 }
1794
1795 pp_maybe_wrap_text (pp, last, ps);
1796}
1797
471854f8 1798/* Maybe print out a whitespace if needed. */
b6fe0bb8 1799
b9b44fb9 1800void
b066401f 1801pp_maybe_space (pretty_printer *pp)
b9b44fb9 1802{
b066401f 1803 if (pp->padding != pp_none)
b9b44fb9
GDR
1804 {
1805 pp_space (pp);
b066401f 1806 pp->padding = pp_none;
b9b44fb9
GDR
1807 }
1808}
0fc80001
GDR
1809
1810// Add a newline to the pretty printer PP and flush formatted text.
1811
1812void
1813pp_newline_and_flush (pretty_printer *pp)
1814{
1815 pp_newline (pp);
1816 pp_flush (pp);
1817 pp_needs_newline (pp) = false;
1818}
1819
1820// Add a newline to the pretty printer PP, followed by indentation.
1821
1822void
1823pp_newline_and_indent (pretty_printer *pp, int n)
1824{
1825 pp_indentation (pp) += n;
1826 pp_newline (pp);
1827 pp_indent (pp);
1828 pp_needs_newline (pp) = false;
1829}
1830
1831// Add separator C, followed by a single whitespace.
1832
1833void
1834pp_separate_with (pretty_printer *pp, char c)
1835{
1836 pp_character (pp, c);
1837 pp_space (pp);
1838}
1839
ce95abc4
DM
1840/* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
1841 using the "quote" color. */
1842
1843void
1844pp_begin_quote (pretty_printer *pp, bool show_color)
1845{
1846 pp_string (pp, open_quote);
1847 pp_string (pp, colorize_start (show_color, "quote"));
1848}
1849
1850/* If SHOW_COLOR is true, stop colorizing.
1851 Add a localized close quote. */
1852
1853void
1854pp_end_quote (pretty_printer *pp, bool show_color)
1855{
1856 pp_string (pp, colorize_stop (show_color));
1857 pp_string (pp, close_quote);
1858}
1859
a3af5087
JM
1860\f
1861/* The string starting at P has LEN (at least 1) bytes left; if they
1862 start with a valid UTF-8 sequence, return the length of that
1863 sequence and set *VALUE to the value of that sequence, and
1864 otherwise return 0 and set *VALUE to (unsigned int) -1. */
1865
1866static int
1867decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
1868{
1869 unsigned int t = *p;
1870
1871 if (len == 0)
1872 abort ();
1873 if (t & 0x80)
1874 {
1875 size_t utf8_len = 0;
1876 unsigned int ch;
1877 size_t i;
1878 for (t = *p; t & 0x80; t <<= 1)
1879 utf8_len++;
1880
1881 if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
1882 {
1883 *value = (unsigned int) -1;
1884 return 0;
1885 }
1886 ch = *p & ((1 << (7 - utf8_len)) - 1);
1887 for (i = 1; i < utf8_len; i++)
1888 {
1889 unsigned int u = p[i];
1890 if ((u & 0xC0) != 0x80)
1891 {
1892 *value = (unsigned int) -1;
1893 return 0;
1894 }
1895 ch = (ch << 6) | (u & 0x3F);
1896 }
1897 if ( (ch <= 0x7F && utf8_len > 1)
1898 || (ch <= 0x7FF && utf8_len > 2)
1899 || (ch <= 0xFFFF && utf8_len > 3)
1900 || (ch <= 0x1FFFFF && utf8_len > 4)
1901 || (ch <= 0x3FFFFFF && utf8_len > 5)
1902 || (ch >= 0xD800 && ch <= 0xDFFF))
1903 {
1904 *value = (unsigned int) -1;
1905 return 0;
1906 }
1907 *value = ch;
1908 return utf8_len;
1909 }
1910 else
1911 {
1912 *value = t;
1913 return 1;
1914 }
1915}
1916
ab9b814d
JM
1917/* Allocator for identifier_to_locale and corresponding function to
1918 free memory. */
1919
1920void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
1921void (*identifier_to_locale_free) (void *) = free;
1922
a3af5087
JM
1923/* Given IDENT, an identifier in the internal encoding, return a
1924 version of IDENT suitable for diagnostics in the locale character
ab9b814d
JM
1925 set: either IDENT itself, or a string, allocated using
1926 identifier_to_locale_alloc, converted to the locale character set
1927 and using escape sequences if not representable in the locale
1928 character set or containing control characters or invalid byte
1929 sequences. Existing backslashes in IDENT are not doubled, so the
1930 result may not uniquely specify the contents of an arbitrary byte
1931 sequence identifier. */
a3af5087
JM
1932
1933const char *
1934identifier_to_locale (const char *ident)
1935{
1936 const unsigned char *uid = (const unsigned char *) ident;
1937 size_t idlen = strlen (ident);
1938 bool valid_printable_utf8 = true;
1939 bool all_ascii = true;
1940 size_t i;
1941
1942 for (i = 0; i < idlen;)
1943 {
1944 unsigned int c;
1945 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
1946 if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
1947 {
1948 valid_printable_utf8 = false;
1949 break;
1950 }
1951 if (utf8_len > 1)
1952 all_ascii = false;
1953 i += utf8_len;
1954 }
1955
1956 /* If IDENT contains invalid UTF-8 sequences (which may occur with
1957 attributes putting arbitrary byte sequences in identifiers), or
1958 control characters, we use octal escape sequences for all bytes
1959 outside printable ASCII. */
1960 if (!valid_printable_utf8)
1961 {
ab9b814d 1962 char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
a3af5087
JM
1963 char *p = ret;
1964 for (i = 0; i < idlen; i++)
1965 {
1966 if (uid[i] > 0x1F && uid[i] < 0x7F)
1967 *p++ = uid[i];
1968 else
1969 {
1970 sprintf (p, "\\%03o", uid[i]);
1971 p += 4;
1972 }
1973 }
1974 *p = 0;
1975 return ret;
1976 }
1977
1978 /* Otherwise, if it is valid printable ASCII, or printable UTF-8
1979 with the locale character set being UTF-8, IDENT is used. */
1980 if (all_ascii || locale_utf8)
1981 return ident;
1982
1983 /* Otherwise IDENT is converted to the locale character set if
1984 possible. */
1985#if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
1986 if (locale_encoding != NULL)
1987 {
1988 iconv_t cd = iconv_open (locale_encoding, "UTF-8");
1989 bool conversion_ok = true;
1990 char *ret = NULL;
1991 if (cd != (iconv_t) -1)
1992 {
1993 size_t ret_alloc = 4 * idlen + 1;
1994 for (;;)
1995 {
1996 /* Repeat the whole conversion process as needed with
1997 larger buffers so non-reversible transformations can
1998 always be detected. */
1999 ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
2000 char *outbuf;
2001 size_t inbytesleft = idlen;
2002 size_t outbytesleft = ret_alloc - 1;
2003 size_t iconv_ret;
2004
ab9b814d 2005 ret = (char *) identifier_to_locale_alloc (ret_alloc);
a3af5087
JM
2006 outbuf = ret;
2007
2008 if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
2009 {
2010 conversion_ok = false;
2011 break;
2012 }
2013
2014 iconv_ret = iconv (cd, &inbuf, &inbytesleft,
2015 &outbuf, &outbytesleft);
2016 if (iconv_ret == (size_t) -1 || inbytesleft != 0)
2017 {
2018 if (errno == E2BIG)
2019 {
2020 ret_alloc *= 2;
ab9b814d 2021 identifier_to_locale_free (ret);
a3af5087
JM
2022 ret = NULL;
2023 continue;
2024 }
2025 else
2026 {
2027 conversion_ok = false;
2028 break;
2029 }
2030 }
2031 else if (iconv_ret != 0)
2032 {
2033 conversion_ok = false;
2034 break;
2035 }
2036 /* Return to initial shift state. */
2037 if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
2038 {
2039 if (errno == E2BIG)
2040 {
2041 ret_alloc *= 2;
ab9b814d 2042 identifier_to_locale_free (ret);
a3af5087
JM
2043 ret = NULL;
2044 continue;
2045 }
2046 else
2047 {
2048 conversion_ok = false;
2049 break;
2050 }
2051 }
2052 *outbuf = 0;
2053 break;
2054 }
2055 iconv_close (cd);
2056 if (conversion_ok)
2057 return ret;
2058 }
2059 }
2060#endif
2061
2062 /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */
2063 {
ab9b814d 2064 char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
a3af5087
JM
2065 char *p = ret;
2066 for (i = 0; i < idlen;)
2067 {
2068 unsigned int c;
2069 size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2070 if (utf8_len == 1)
2071 *p++ = uid[i];
2072 else
2073 {
2074 sprintf (p, "\\U%08x", c);
2075 p += 10;
2076 }
2077 i += utf8_len;
2078 }
2079 *p = 0;
2080 return ret;
2081 }
2082}
4ccab56d 2083
d2608235
DM
2084/* Support for encoding URLs.
2085 See egmontkob/Hyperlinks_in_Terminal_Emulators.md
2086 ( https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda ).
2087
2088 > A hyperlink is opened upon encountering an OSC 8 escape sequence with
2089 > the target URI. The syntax is
2090 >
2091 > OSC 8 ; params ; URI ST
2092 >
2093 > A hyperlink is closed with the same escape sequence, omitting the
2094 > parameters and the URI but keeping the separators:
2095 >
2096 > OSC 8 ; ; ST
2097 >
ae169f9e
TB
2098 > OSC (operating system command) is typically ESC ].
2099
2100 Use BEL instead of ST, as that is currently rendered better in some
2101 terminal emulators that don't support OSC 8, like konsole. */
d2608235
DM
2102
2103/* If URL-printing is enabled, write an "open URL" escape sequence to PP
2104 for the given URL. */
2105
2106void
2107pp_begin_url (pretty_printer *pp, const char *url)
2108{
2109 if (pp->show_urls)
ae169f9e 2110 pp_printf (pp, "\33]8;;%s\a", url);
d2608235
DM
2111}
2112
2113/* If URL-printing is enabled, write a "close URL" escape sequence to PP. */
2114
2115void
2116pp_end_url (pretty_printer *pp)
2117{
2118 if (pp->show_urls)
ae169f9e 2119 pp_string (pp, "\33]8;;\a");
d2608235
DM
2120}
2121
4ccab56d
DM
2122#if CHECKING_P
2123
2124namespace selftest {
2125
2126/* Smoketest for pretty_printer. */
2127
2128static void
2129test_basic_printing ()
2130{
2131 pretty_printer pp;
2132 pp_string (&pp, "hello");
2133 pp_space (&pp);
2134 pp_string (&pp, "world");
2135
2136 ASSERT_STREQ ("hello world", pp_formatted_text (&pp));
2137}
2138
2139/* Helper function for testing pp_format.
2140 Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2141 prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */
2142
2143static void
09765e3a
DM
2144assert_pp_format_va (const location &loc, const char *expected,
2145 bool show_color, const char *fmt, va_list *ap)
4ccab56d
DM
2146{
2147 pretty_printer pp;
2148 text_info ti;
2149 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2150
2151 ti.format_spec = fmt;
2152 ti.args_ptr = ap;
2153 ti.err_no = 0;
2154 ti.x_data = NULL;
2155 ti.m_richloc = &rich_loc;
2156
2157 pp_show_color (&pp) = show_color;
2158 pp_format (&pp, &ti);
2159 pp_output_formatted_text (&pp);
09765e3a 2160 ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
4ccab56d
DM
2161}
2162
2163/* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2164 prints EXPECTED, with show_color disabled. */
2165
2166static void
09765e3a
DM
2167assert_pp_format (const location &loc, const char *expected,
2168 const char *fmt, ...)
4ccab56d
DM
2169{
2170 va_list ap;
2171
2172 va_start (ap, fmt);
09765e3a 2173 assert_pp_format_va (loc, expected, false, fmt, &ap);
4ccab56d
DM
2174 va_end (ap);
2175}
2176
2177/* As above, but with colorization enabled. */
2178
2179static void
09765e3a
DM
2180assert_pp_format_colored (const location &loc, const char *expected,
2181 const char *fmt, ...)
4ccab56d 2182{
2fe00b1f
DM
2183 /* The tests of colorization assume the default color scheme.
2184 If GCC_COLORS is set, then the colors have potentially been
2185 overridden; skip the test. */
2186 if (getenv ("GCC_COLORS"))
2187 return;
2188
4ccab56d
DM
2189 va_list ap;
2190
2191 va_start (ap, fmt);
09765e3a 2192 assert_pp_format_va (loc, expected, true, fmt, &ap);
4ccab56d
DM
2193 va_end (ap);
2194}
2195
09765e3a
DM
2196/* Helper function for calling testing pp_format,
2197 by calling assert_pp_format with various numbers of arguments.
2198 These exist mostly to avoid having to write SELFTEST_LOCATION
2199 throughout test_pp_format. */
2200
2201#define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \
2202 SELFTEST_BEGIN_STMT \
2203 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2204 (ARG1)); \
2205 SELFTEST_END_STMT
2206
2207#define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \
2208 SELFTEST_BEGIN_STMT \
2209 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2210 (ARG1), (ARG2)); \
2211 SELFTEST_END_STMT
2212
2213#define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \
2214 SELFTEST_BEGIN_STMT \
2215 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2216 (ARG1), (ARG2), (ARG3)); \
2217 SELFTEST_END_STMT
2218
4ccab56d
DM
2219/* Verify that pp_format works, for various format codes. */
2220
2221static void
2222test_pp_format ()
2223{
2224 /* Avoid introducing locale-specific differences in the results
2225 by hardcoding open_quote and close_quote. */
dbf96d49 2226 auto_fix_quotes fix_quotes;
4ccab56d
DM
2227
2228 /* Verify that plain text is passed through unchanged. */
09765e3a 2229 assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted");
4ccab56d
DM
2230
2231 /* Verify various individual format codes, in the order listed in the
2232 comment for pp_format above. For each code, we append a second
2233 argument with a known bit pattern (0x12345678), to ensure that we
2234 are consuming arguments correctly. */
09765e3a
DM
2235 ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678);
2236 ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678);
2237 ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678);
2238 ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678);
2239 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678);
2240 ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678);
2241 ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678);
2242 ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678);
2243 ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678);
2244 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe,
2245 0x12345678);
2246 ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678);
2247 ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678);
2248 ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678);
2249 ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678);
2250 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe,
2251 0x12345678);
2252 ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678);
2253 ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678);
2254 ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10,
2255 0x12345678);
2256 ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
2257 ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
2258 0x12345678);
204839e7 2259 ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
09765e3a
DM
2260 ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
2261 ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
2262 0x12345678);
86ef85d3
MS
2263
2264 /* Not nul-terminated. */
2265 char arr[5] = { '1', '2', '3', '4', '5' };
2266 ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678);
2267 ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678);
2268 ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678);
2269
914bc2b9
DM
2270 /* We can't test for %p; the pointer is printed in an implementation-defined
2271 manner. */
09765e3a
DM
2272 ASSERT_PP_FORMAT_2 ("normal colored normal 12345678",
2273 "normal %rcolored%R normal %x",
2274 "error", 0x12345678);
4ccab56d 2275 assert_pp_format_colored
09765e3a
DM
2276 (SELFTEST_LOCATION,
2277 "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678",
4ccab56d
DM
2278 "normal %rcolored%R normal %x", "error", 0x12345678);
2279 /* TODO:
2280 %m: strerror(text->err_no) - does not consume a value from args_ptr. */
09765e3a
DM
2281 ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678);
2282 ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678);
2283 ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678);
2284 ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678);
2285 ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678);
2286 ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678);
4ccab56d
DM
2287
2288 /* Verify flag 'q'. */
09765e3a
DM
2289 ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678);
2290 assert_pp_format_colored (SELFTEST_LOCATION,
2291 "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
4ccab56d
DM
2292 "foo", 0x12345678);
2293
975672f3
PK
2294 /* Verify %Z. */
2295 int v[] = { 1, 2, 3 };
2296 ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
2297
2298 int v2[] = { 0 };
2299 ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
2300
4ccab56d 2301 /* Verify that combinations work, along with unformatted text. */
09765e3a
DM
2302 assert_pp_format (SELFTEST_LOCATION,
2303 "the quick brown fox jumps over the lazy dog",
4ccab56d
DM
2304 "the %s %s %s jumps over the %s %s",
2305 "quick", "brown", "fox", "lazy", "dog");
09765e3a
DM
2306 assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7);
2307 assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10",
4ccab56d 2308 "problem with %qs at line %i", "bar", 10);
4ccab56d
DM
2309}
2310
553a316b
DM
2311/* A subclass of pretty_printer for use by test_prefixes_and_wrapping. */
2312
2313class test_pretty_printer : public pretty_printer
2314{
2315 public:
2316 test_pretty_printer (enum diagnostic_prefixing_rule_t rule,
2317 int max_line_length)
2318 {
2319 pp_set_prefix (this, xstrdup ("PREFIX: "));
2320 wrapping.rule = rule;
2321 pp_set_line_maximum_length (this, max_line_length);
2322 }
2323};
2324
2325/* Verify that the various values of enum diagnostic_prefixing_rule_t work
2326 as expected, with and without line wrapping. */
2327
2328static void
2329test_prefixes_and_wrapping ()
2330{
2331 /* Tests of the various prefixing rules, without wrapping.
2332 Newlines embedded in pp_string don't affect it; we have to
2333 explicitly call pp_newline. */
2334 {
2335 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 0);
2336 pp_string (&pp, "the quick brown fox");
2337 pp_newline (&pp);
2338 pp_string (&pp, "jumps over the lazy dog");
2339 pp_newline (&pp);
2340 ASSERT_STREQ (pp_formatted_text (&pp),
2341 "PREFIX: the quick brown fox\n"
2342 " jumps over the lazy dog\n");
2343 }
2344 {
2345 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 0);
2346 pp_string (&pp, "the quick brown fox");
2347 pp_newline (&pp);
2348 pp_string (&pp, "jumps over the lazy dog");
2349 pp_newline (&pp);
2350 ASSERT_STREQ (pp_formatted_text (&pp),
2351 "the quick brown fox\n"
2352 "jumps over the lazy dog\n");
2353 }
2354 {
2355 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 0);
2356 pp_string (&pp, "the quick brown fox");
2357 pp_newline (&pp);
2358 pp_string (&pp, "jumps over the lazy dog");
2359 pp_newline (&pp);
2360 ASSERT_STREQ (pp_formatted_text (&pp),
2361 "PREFIX: the quick brown fox\n"
2362 "PREFIX: jumps over the lazy dog\n");
2363 }
2364
2365 /* Tests of the various prefixing rules, with wrapping. */
2366 {
2367 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 20);
2368 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2369 pp_newline (&pp);
2370 pp_string (&pp, "able was I ere I saw elba");
2371 pp_newline (&pp);
2372 ASSERT_STREQ (pp_formatted_text (&pp),
2373 "PREFIX: the quick \n"
2374 " brown fox jumps \n"
2375 " over the lazy \n"
2376 " dog\n"
2377 " able was I ere I \n"
2378 " saw elba\n");
2379 }
2380 {
2381 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 20);
2382 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2383 pp_newline (&pp);
2384 pp_string (&pp, "able was I ere I saw elba");
2385 pp_newline (&pp);
2386 ASSERT_STREQ (pp_formatted_text (&pp),
2387 "the quick brown fox \n"
2388 "jumps over the lazy \n"
2389 "dog\n"
2390 "able was I ere I \n"
2391 "saw elba\n");
2392 }
2393 {
2394 test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 20);
2395 pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2396 pp_newline (&pp);
2397 pp_string (&pp, "able was I ere I saw elba");
2398 pp_newline (&pp);
2399 ASSERT_STREQ (pp_formatted_text (&pp),
2400 "PREFIX: the quick brown fox jumps over the lazy dog\n"
2401 "PREFIX: able was I ere I saw elba\n");
2402 }
2403
2404}
2405
d2608235
DM
2406/* Verify that URL-printing works as expected. */
2407
2408void
2409test_urls ()
2410{
2411 {
2412 pretty_printer pp;
2413 pp.show_urls = false;
2414 pp_begin_url (&pp, "http://example.com");
2415 pp_string (&pp, "This is a link");
2416 pp_end_url (&pp);
2417 ASSERT_STREQ ("This is a link",
2418 pp_formatted_text (&pp));
2419 }
2420
2421 {
2422 pretty_printer pp;
2423 pp.show_urls = true;
2424 pp_begin_url (&pp, "http://example.com");
2425 pp_string (&pp, "This is a link");
2426 pp_end_url (&pp);
ae169f9e 2427 ASSERT_STREQ ("\33]8;;http://example.com\aThis is a link\33]8;;\a",
d2608235
DM
2428 pp_formatted_text (&pp));
2429 }
2430}
2431
ddd0fd17
LH
2432/* Test multibyte awareness. */
2433static void test_utf8 ()
2434{
2435
2436 /* Check that pp_quoted_string leaves valid UTF-8 alone. */
2437 {
2438 pretty_printer pp;
2439 const char *s = "\xf0\x9f\x98\x82";
2440 pp_quoted_string (&pp, s);
2441 ASSERT_STREQ (pp_formatted_text (&pp), s);
2442 }
2443
2444 /* Check that pp_quoted_string escapes non-UTF-8 nonprintable bytes. */
2445 {
2446 pretty_printer pp;
2447 pp_quoted_string (&pp, "\xf0!\x9f\x98\x82");
2448 ASSERT_STREQ (pp_formatted_text (&pp),
2449 "\\xf0!\\x9f\\x98\\x82");
2450 }
2451
2452 /* Check that pp_character will line-wrap at the beginning of a UTF-8
2453 sequence, but not in the middle. */
2454 {
2455 pretty_printer pp (3);
2456 const char s[] = "---\xf0\x9f\x98\x82";
2457 for (int i = 0; i != sizeof (s) - 1; ++i)
2458 pp_character (&pp, s[i]);
2459 pp_newline (&pp);
2460 for (int i = 1; i != sizeof (s) - 1; ++i)
2461 pp_character (&pp, s[i]);
2462 pp_character (&pp, '-');
2463 ASSERT_STREQ (pp_formatted_text (&pp),
2464 "---\n"
2465 "\xf0\x9f\x98\x82\n"
2466 "--\xf0\x9f\x98\x82\n"
2467 "-");
2468 }
2469
2470}
2471
4ccab56d
DM
2472/* Run all of the selftests within this file. */
2473
2474void
2475pretty_print_c_tests ()
2476{
2477 test_basic_printing ();
2478 test_pp_format ();
553a316b 2479 test_prefixes_and_wrapping ();
d2608235 2480 test_urls ();
ddd0fd17 2481 test_utf8 ();
4ccab56d
DM
2482}
2483
2484} // namespace selftest
2485
2486#endif /* CHECKING_P */