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