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