1 /* Various declarations for language-independent pretty-print subroutines.
2    Copyright (C) 2003-2019 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,enum range_display_kind range_display_kind)708 text_info::set_location (unsigned int idx, location_t loc,
709 			 enum range_display_kind range_display_kind)
710 {
711   gcc_checking_assert (m_richloc);
712   m_richloc->set_range (idx, loc, range_display_kind);
713 }
714 
715 location_t
get_location(unsigned int index_of_location)716 text_info::get_location (unsigned int index_of_location) const
717 {
718   gcc_checking_assert (m_richloc);
719 
720   if (index_of_location == 0)
721     return m_richloc->get_loc ();
722   else
723     return UNKNOWN_LOCATION;
724 }
725 
726 // Default construct an output buffer.
727 
output_buffer()728 output_buffer::output_buffer ()
729   : formatted_obstack (),
730     chunk_obstack (),
731     obstack (&formatted_obstack),
732     cur_chunk_array (),
733     stream (stderr),
734     line_length (),
735     digit_buffer (),
736     flush_p (true)
737 {
738   obstack_init (&formatted_obstack);
739   obstack_init (&chunk_obstack);
740 }
741 
742 // Release resources owned by an output buffer at the end of lifetime.
743 
~output_buffer()744 output_buffer::~output_buffer ()
745 {
746   obstack_free (&chunk_obstack, NULL);
747   obstack_free (&formatted_obstack, NULL);
748 }
749 
750 
751 /* Format an integer given by va_arg (ARG, type-specifier T) where
752    type-specifier is a precision modifier as indicated by PREC.  F is
753    a string used to construct the appropriate format-specifier.  */
754 #define pp_integer_with_precision(PP, ARG, PREC, T, F)       \
755   do                                                         \
756     switch (PREC)                                            \
757       {                                                      \
758       case 0:                                                \
759         pp_scalar (PP, "%" F, va_arg (ARG, T));              \
760         break;                                               \
761                                                              \
762       case 1:                                                \
763         pp_scalar (PP, "%l" F, va_arg (ARG, long T));        \
764         break;                                               \
765                                                              \
766       case 2:                                                \
767         pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T));  \
768         break;                                               \
769                                                              \
770       default:                                               \
771         break;                                               \
772       }                                                      \
773   while (0)
774 
775 
776 /* Subroutine of pp_set_maximum_length.  Set up PRETTY-PRINTER's
777    internal maximum characters per line.  */
778 static void
pp_set_real_maximum_length(pretty_printer * pp)779 pp_set_real_maximum_length (pretty_printer *pp)
780 {
781   /* If we're told not to wrap lines then do the obvious thing.  In case
782      we'll emit prefix only once per message, it is appropriate
783      not to increase unnecessarily the line-length cut-off.  */
784   if (!pp_is_wrapping_line (pp)
785       || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_ONCE
786       || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
787     pp->maximum_length = pp_line_cutoff (pp);
788   else
789     {
790       int prefix_length = pp->prefix ? strlen (pp->prefix) : 0;
791       /* If the prefix is ridiculously too long, output at least
792          32 characters.  */
793       if (pp_line_cutoff (pp) - prefix_length < 32)
794 	pp->maximum_length = pp_line_cutoff (pp) + 32;
795       else
796 	pp->maximum_length = pp_line_cutoff (pp);
797     }
798 }
799 
800 /* Clear PRETTY-PRINTER's output state.  */
801 static inline void
pp_clear_state(pretty_printer * pp)802 pp_clear_state (pretty_printer *pp)
803 {
804   pp->emitted_prefix = false;
805   pp_indentation (pp) = 0;
806 }
807 
808 /* Print X to PP in decimal.  */
809 template<unsigned int N, typename T>
810 void
pp_wide_integer(pretty_printer * pp,const poly_int_pod<N,T> & x)811 pp_wide_integer (pretty_printer *pp, const poly_int_pod<N, T> &x)
812 {
813   if (x.is_constant ())
814     pp_wide_integer (pp, x.coeffs[0]);
815   else
816     {
817       pp_left_bracket (pp);
818       for (unsigned int i = 0; i < N; ++i)
819 	{
820 	  if (i != 0)
821 	    pp_comma (pp);
822 	  pp_wide_integer (pp, x.coeffs[i]);
823 	}
824       pp_right_bracket (pp);
825     }
826 }
827 
828 template void pp_wide_integer (pretty_printer *, const poly_uint16_pod &);
829 template void pp_wide_integer (pretty_printer *, const poly_int64_pod &);
830 template void pp_wide_integer (pretty_printer *, const poly_uint64_pod &);
831 
832 /* Flush the formatted text of PRETTY-PRINTER onto the attached stream.  */
833 void
pp_write_text_to_stream(pretty_printer * pp)834 pp_write_text_to_stream (pretty_printer *pp)
835 {
836   const char *text = pp_formatted_text (pp);
837 #ifdef __MINGW32__
838   mingw_ansi_fputs (text, pp_buffer (pp)->stream);
839 #else
840   fputs (text, pp_buffer (pp)->stream);
841 #endif
842   pp_clear_output_area (pp);
843 }
844 
845 /* As pp_write_text_to_stream, but for GraphViz label output.
846 
847    Flush the formatted text of pretty-printer PP onto the attached stream.
848    Replace characters in PPF that have special meaning in a GraphViz .dot
849    file.
850 
851    This routine is not very fast, but it doesn't have to be as this is only
852    be used by routines dumping intermediate representations in graph form.  */
853 
854 void
pp_write_text_as_dot_label_to_stream(pretty_printer * pp,bool for_record)855 pp_write_text_as_dot_label_to_stream (pretty_printer *pp, bool for_record)
856 {
857   const char *text = pp_formatted_text (pp);
858   const char *p = text;
859   FILE *fp = pp_buffer (pp)->stream;
860 
861   for (;*p; p++)
862     {
863       bool escape_char;
864       switch (*p)
865 	{
866 	/* Print newlines as a left-aligned newline.  */
867 	case '\n':
868 	  fputs ("\\l", fp);
869 	  escape_char = true;
870 	  break;
871 
872 	/* The following characters are only special for record-shape nodes.  */
873 	case '|':
874 	case '{':
875 	case '}':
876 	case '<':
877 	case '>':
878 	case ' ':
879 	  escape_char = for_record;
880 	  break;
881 
882 	/* The following characters always have to be escaped
883 	   for use in labels.  */
884 	case '\\':
885 	  /* There is a bug in some (f.i. 2.36.0) versions of graphiz
886 	     ( http://www.graphviz.org/mantisbt/view.php?id=2524 ) related to
887 	     backslash as last char in label.  Let's avoid triggering it.  */
888 	  gcc_assert (*(p + 1) != '\0');
889 	  /* Fall through.  */
890 	case '"':
891 	  escape_char = true;
892 	  break;
893 
894 	default:
895 	  escape_char = false;
896 	  break;
897 	}
898 
899       if (escape_char)
900 	fputc ('\\', fp);
901 
902       fputc (*p, fp);
903     }
904 
905   pp_clear_output_area (pp);
906 }
907 
908 /* Wrap a text delimited by START and END into PRETTY-PRINTER.  */
909 static void
pp_wrap_text(pretty_printer * pp,const char * start,const char * end)910 pp_wrap_text (pretty_printer *pp, const char *start, const char *end)
911 {
912   bool wrapping_line = pp_is_wrapping_line (pp);
913 
914   while (start != end)
915     {
916       /* Dump anything bordered by whitespaces.  */
917       {
918 	const char *p = start;
919 	while (p != end && !ISBLANK (*p) && *p != '\n')
920 	  ++p;
921 	if (wrapping_line
922             && p - start >= pp_remaining_character_count_for_line (pp))
923 	  pp_newline (pp);
924 	pp_append_text (pp, start, p);
925 	start = p;
926       }
927 
928       if (start != end && ISBLANK (*start))
929 	{
930 	  pp_space (pp);
931 	  ++start;
932 	}
933       if (start != end && *start == '\n')
934 	{
935 	  pp_newline (pp);
936 	  ++start;
937 	}
938     }
939 }
940 
941 /* Same as pp_wrap_text but wrap text only when in line-wrapping mode.  */
942 static inline void
pp_maybe_wrap_text(pretty_printer * pp,const char * start,const char * end)943 pp_maybe_wrap_text (pretty_printer *pp, const char *start, const char *end)
944 {
945   if (pp_is_wrapping_line (pp))
946     pp_wrap_text (pp, start, end);
947   else
948     pp_append_text (pp, start, end);
949 }
950 
951 /* Append to the output area of PRETTY-PRINTER a string specified by its
952    STARTing character and LENGTH.  */
953 static inline void
pp_append_r(pretty_printer * pp,const char * start,int length)954 pp_append_r (pretty_printer *pp, const char *start, int length)
955 {
956   output_buffer_append_r (pp_buffer (pp), start, length);
957 }
958 
959 /* Insert enough spaces into the output area of PRETTY-PRINTER to bring
960    the column position to the current indentation level, assuming that a
961    newline has just been written to the buffer.  */
962 void
pp_indent(pretty_printer * pp)963 pp_indent (pretty_printer *pp)
964 {
965   int n = pp_indentation (pp);
966   int i;
967 
968   for (i = 0; i < n; ++i)
969     pp_space (pp);
970 }
971 
972 /* The following format specifiers are recognized as being client independent:
973    %d, %i: (signed) integer in base ten.
974    %u: unsigned integer in base ten.
975    %o: unsigned integer in base eight.
976    %x: unsigned integer in base sixteen.
977    %ld, %li, %lo, %lu, %lx: long versions of the above.
978    %lld, %lli, %llo, %llu, %llx: long long versions.
979    %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
980    %f: double
981    %c: character.
982    %s: string.
983    %p: pointer (printed in a host-dependent manner).
984    %r: if pp_show_color(pp), switch to color identified by const char *.
985    %R: if pp_show_color(pp), reset color.
986    %m: strerror(text->err_no) - does not consume a value from args_ptr.
987    %%: '%'.
988    %<: opening quote.
989    %>: closing quote.
990    %': apostrophe (should only be used in untranslated messages;
991        translations should use appropriate punctuation directly).
992    %.*s: a substring the length of which is specified by an argument
993 	 integer.
994    %Ns: likewise, but length specified as constant in the format string.
995    Flag 'q': quote formatted text (must come immediately after '%').
996    %Z: Requires two arguments - array of int, and len. Prints elements
997    of the array.
998 
999    Arguments can be used sequentially, or through %N$ resp. *N$
1000    notation Nth argument after the format string.  If %N$ / *N$
1001    notation is used, it must be used for all arguments, except %m, %%,
1002    %<, %> and %', which may not have a number, as they do not consume
1003    an argument.  When %M$.*N$s is used, M must be N + 1.  (This may
1004    also be written %M$.*s, provided N is not otherwise used.)  The
1005    format string must have conversion specifiers with argument numbers
1006    1 up to highest argument; each argument may only be used once.
1007    A format string can have at most 30 arguments.  */
1008 
1009 /* Formatting phases 1 and 2: render TEXT->format_spec plus
1010    TEXT->args_ptr into a series of chunks in pp_buffer (PP)->args[].
1011    Phase 3 is in pp_output_formatted_text.  */
1012 
1013 void
pp_format(pretty_printer * pp,text_info * text)1014 pp_format (pretty_printer *pp, text_info *text)
1015 {
1016   output_buffer *buffer = pp_buffer (pp);
1017   const char *p;
1018   const char **args;
1019   struct chunk_info *new_chunk_array;
1020 
1021   unsigned int curarg = 0, chunk = 0, argno;
1022   pp_wrapping_mode_t old_wrapping_mode;
1023   bool any_unnumbered = false, any_numbered = false;
1024   const char **formatters[PP_NL_ARGMAX];
1025 
1026   /* Allocate a new chunk structure.  */
1027   new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
1028   new_chunk_array->prev = buffer->cur_chunk_array;
1029   buffer->cur_chunk_array = new_chunk_array;
1030   args = new_chunk_array->args;
1031 
1032   /* Formatting phase 1: split up TEXT->format_spec into chunks in
1033      pp_buffer (PP)->args[].  Even-numbered chunks are to be output
1034      verbatim, odd-numbered chunks are format specifiers.
1035      %m, %%, %<, %>, and %' are replaced with the appropriate text at
1036      this point.  */
1037 
1038   memset (formatters, 0, sizeof formatters);
1039 
1040   for (p = text->format_spec; *p; )
1041     {
1042       while (*p != '\0' && *p != '%')
1043 	{
1044 	  obstack_1grow (&buffer->chunk_obstack, *p);
1045 	  p++;
1046 	}
1047 
1048       if (*p == '\0')
1049 	break;
1050 
1051       switch (*++p)
1052 	{
1053 	case '\0':
1054 	  gcc_unreachable ();
1055 
1056 	case '%':
1057 	  obstack_1grow (&buffer->chunk_obstack, '%');
1058 	  p++;
1059 	  continue;
1060 
1061 	case '<':
1062 	  {
1063 	    obstack_grow (&buffer->chunk_obstack,
1064 			  open_quote, strlen (open_quote));
1065 	    const char *colorstr
1066 	      = colorize_start (pp_show_color (pp), "quote");
1067 	    obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
1068 	    p++;
1069 	    continue;
1070 	  }
1071 
1072 	case '>':
1073 	  {
1074 	    const char *colorstr = colorize_stop (pp_show_color (pp));
1075 	    obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
1076 	  }
1077 	  /* FALLTHRU */
1078 	case '\'':
1079 	  obstack_grow (&buffer->chunk_obstack,
1080 			close_quote, strlen (close_quote));
1081 	  p++;
1082 	  continue;
1083 
1084 	case 'R':
1085 	  {
1086 	    const char *colorstr = colorize_stop (pp_show_color (pp));
1087 	    obstack_grow (&buffer->chunk_obstack, colorstr,
1088 			  strlen (colorstr));
1089 	    p++;
1090 	    continue;
1091 	  }
1092 
1093 	case 'm':
1094 	  {
1095 	    const char *errstr = xstrerror (text->err_no);
1096 	    obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
1097 	  }
1098 	  p++;
1099 	  continue;
1100 
1101 	default:
1102 	  /* Handled in phase 2.  Terminate the plain chunk here.  */
1103 	  obstack_1grow (&buffer->chunk_obstack, '\0');
1104 	  gcc_assert (chunk < PP_NL_ARGMAX * 2);
1105 	  args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1106 	  break;
1107 	}
1108 
1109       if (ISDIGIT (*p))
1110 	{
1111 	  char *end;
1112 	  argno = strtoul (p, &end, 10) - 1;
1113 	  p = end;
1114 	  gcc_assert (*p == '$');
1115 	  p++;
1116 
1117 	  any_numbered = true;
1118 	  gcc_assert (!any_unnumbered);
1119 	}
1120       else
1121 	{
1122 	  argno = curarg++;
1123 	  any_unnumbered = true;
1124 	  gcc_assert (!any_numbered);
1125 	}
1126       gcc_assert (argno < PP_NL_ARGMAX);
1127       gcc_assert (!formatters[argno]);
1128       formatters[argno] = &args[chunk];
1129       do
1130 	{
1131 	  obstack_1grow (&buffer->chunk_obstack, *p);
1132 	  p++;
1133 	}
1134       while (strchr ("qwl+#", p[-1]));
1135 
1136       if (p[-1] == '.')
1137 	{
1138 	  /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
1139 	     (where M == N + 1).  */
1140 	  if (ISDIGIT (*p))
1141 	    {
1142 	      do
1143 		{
1144 		  obstack_1grow (&buffer->chunk_obstack, *p);
1145 		  p++;
1146 		}
1147 	      while (ISDIGIT (p[-1]));
1148 	      gcc_assert (p[-1] == 's');
1149 	    }
1150 	  else
1151 	    {
1152 	      gcc_assert (*p == '*');
1153 	      obstack_1grow (&buffer->chunk_obstack, '*');
1154 	      p++;
1155 
1156 	      if (ISDIGIT (*p))
1157 		{
1158 		  char *end;
1159 		  unsigned int argno2 = strtoul (p, &end, 10) - 1;
1160 		  p = end;
1161 		  gcc_assert (argno2 == argno - 1);
1162 		  gcc_assert (!any_unnumbered);
1163 		  gcc_assert (*p == '$');
1164 
1165 		  p++;
1166 		  formatters[argno2] = formatters[argno];
1167 		}
1168 	      else
1169 		{
1170 		  gcc_assert (!any_numbered);
1171 		  formatters[argno+1] = formatters[argno];
1172 		  curarg++;
1173 		}
1174 	      gcc_assert (*p == 's');
1175 	      obstack_1grow (&buffer->chunk_obstack, 's');
1176 	      p++;
1177 	    }
1178 	}
1179       if (*p == '\0')
1180 	break;
1181 
1182       obstack_1grow (&buffer->chunk_obstack, '\0');
1183       gcc_assert (chunk < PP_NL_ARGMAX * 2);
1184       args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1185     }
1186 
1187   obstack_1grow (&buffer->chunk_obstack, '\0');
1188   gcc_assert (chunk < PP_NL_ARGMAX * 2);
1189   args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
1190   args[chunk] = 0;
1191 
1192   /* Set output to the argument obstack, and switch line-wrapping and
1193      prefixing off.  */
1194   buffer->obstack = &buffer->chunk_obstack;
1195   old_wrapping_mode = pp_set_verbatim_wrapping (pp);
1196 
1197   /* Second phase.  Replace each formatter with the formatted text it
1198      corresponds to.  */
1199 
1200   for (argno = 0; formatters[argno]; argno++)
1201     {
1202       int precision = 0;
1203       bool wide = false;
1204       bool plus = false;
1205       bool hash = false;
1206       bool quote = false;
1207 
1208       /* We do not attempt to enforce any ordering on the modifier
1209 	 characters.  */
1210 
1211       for (p = *formatters[argno];; p++)
1212 	{
1213 	  switch (*p)
1214 	    {
1215 	    case 'q':
1216 	      gcc_assert (!quote);
1217 	      quote = true;
1218 	      continue;
1219 
1220 	    case '+':
1221 	      gcc_assert (!plus);
1222 	      plus = true;
1223 	      continue;
1224 
1225 	    case '#':
1226 	      gcc_assert (!hash);
1227 	      hash = true;
1228 	      continue;
1229 
1230 	    case 'w':
1231 	      gcc_assert (!wide);
1232 	      wide = true;
1233 	      continue;
1234 
1235 	    case 'l':
1236 	      /* We don't support precision beyond that of "long long".  */
1237 	      gcc_assert (precision < 2);
1238 	      precision++;
1239 	      continue;
1240 	    }
1241 	  break;
1242 	}
1243 
1244       gcc_assert (!wide || precision == 0);
1245 
1246       if (quote)
1247 	pp_begin_quote (pp, pp_show_color (pp));
1248 
1249       switch (*p)
1250 	{
1251 	case 'r':
1252 	  pp_string (pp, colorize_start (pp_show_color (pp),
1253 					 va_arg (*text->args_ptr,
1254 						 const char *)));
1255 	  break;
1256 
1257 	case 'c':
1258 	  {
1259 	    /* When quoting, print alphanumeric, punctuation, and the space
1260 	       character unchanged, and all others in hexadecimal with the
1261 	       "\x" prefix.  Otherwise print them all unchanged.  */
1262 	    int chr = va_arg (*text->args_ptr, int);
1263 	    if (ISPRINT (chr) || !quote)
1264 	      pp_character (pp, chr);
1265 	    else
1266 	      {
1267 		const char str [2] = { chr, '\0' };
1268 		pp_quoted_string (pp, str, 1);
1269 	      }
1270 	    break;
1271 	  }
1272 
1273 	case 'd':
1274 	case 'i':
1275 	  if (wide)
1276 	    pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
1277 	  else
1278 	    pp_integer_with_precision
1279 	      (pp, *text->args_ptr, precision, int, "d");
1280 	  break;
1281 
1282 	case 'o':
1283 	  if (wide)
1284 	    pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
1285 		       va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1286 	  else
1287 	    pp_integer_with_precision
1288 	      (pp, *text->args_ptr, precision, unsigned, "o");
1289 	  break;
1290 
1291 	case 's':
1292 	  if (quote)
1293 	    pp_quoted_string (pp, va_arg (*text->args_ptr, const char *));
1294 	  else
1295 	    pp_string (pp, va_arg (*text->args_ptr, const char *));
1296 	  break;
1297 
1298 	case 'p':
1299 	  pp_pointer (pp, va_arg (*text->args_ptr, void *));
1300 	  break;
1301 
1302 	case 'u':
1303 	  if (wide)
1304 	    pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
1305 		       va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1306 	  else
1307 	    pp_integer_with_precision
1308 	      (pp, *text->args_ptr, precision, unsigned, "u");
1309 	  break;
1310 
1311 	case 'f':
1312 	  pp_double (pp, va_arg (*text->args_ptr, double));
1313 	  break;
1314 
1315 	case 'Z':
1316 	  {
1317 	    int *v = va_arg (*text->args_ptr, int *);
1318 	    unsigned len = va_arg (*text->args_ptr, unsigned);
1319 
1320 	    for (unsigned i = 0; i < len; ++i)
1321 	      {
1322 		pp_scalar (pp, "%i", v[i]);
1323 		if (i < len - 1)
1324 		  {
1325 		    pp_comma (pp);
1326 		    pp_space (pp);
1327 		  }
1328 	      }
1329 	    break;
1330 	 }
1331 
1332 	case 'x':
1333 	  if (wide)
1334 	    pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
1335 		       va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
1336 	  else
1337 	    pp_integer_with_precision
1338 	      (pp, *text->args_ptr, precision, unsigned, "x");
1339 	  break;
1340 
1341 	case '.':
1342 	  {
1343 	    int n;
1344 	    const char *s;
1345 
1346 	    /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
1347 	       (where M == N + 1).  The format string should be verified
1348 	       already from the first phase.  */
1349 	    p++;
1350 	    if (ISDIGIT (*p))
1351 	      {
1352 		char *end;
1353 		n = strtoul (p, &end, 10);
1354 		p = end;
1355 		gcc_assert (*p == 's');
1356 	      }
1357 	    else
1358 	      {
1359 		gcc_assert (*p == '*');
1360 		p++;
1361 		gcc_assert (*p == 's');
1362 		n = va_arg (*text->args_ptr, int);
1363 
1364 		/* This consumes a second entry in the formatters array.  */
1365 		gcc_assert (formatters[argno] == formatters[argno+1]);
1366 		argno++;
1367 	      }
1368 
1369 	    s = va_arg (*text->args_ptr, const char *);
1370 
1371 	    /* Append the lesser of precision and strlen (s) characters
1372 	       from the array (which need not be a nul-terminated string).
1373 	       Negative precision is treated as if it were omitted.  */
1374 	    size_t len = n < 0 ? strlen (s) : strnlen (s, n);
1375 
1376 	    pp_append_text (pp, s, s + len);
1377 	  }
1378 	  break;
1379 
1380 	default:
1381 	  {
1382 	    bool ok;
1383 
1384 	    /* Call the format decoder.
1385 	       Pass the address of "quote" so that format decoders can
1386 	       potentially disable printing of the closing quote
1387 	       (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family
1388 	       of frontends).  */
1389 	    gcc_assert (pp_format_decoder (pp));
1390 	    ok = pp_format_decoder (pp) (pp, text, p,
1391 					 precision, wide, plus, hash, &quote,
1392 					 formatters[argno]);
1393 	    gcc_assert (ok);
1394 	  }
1395 	}
1396 
1397       if (quote)
1398 	pp_end_quote (pp, pp_show_color (pp));
1399 
1400       obstack_1grow (&buffer->chunk_obstack, '\0');
1401       *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
1402     }
1403 
1404   if (CHECKING_P)
1405     for (; argno < PP_NL_ARGMAX; argno++)
1406       gcc_assert (!formatters[argno]);
1407 
1408   /* If the client supplied a postprocessing object, call its "handle"
1409      hook here.  */
1410   if (pp->m_format_postprocessor)
1411     pp->m_format_postprocessor->handle (pp);
1412 
1413   /* Revert to normal obstack and wrapping mode.  */
1414   buffer->obstack = &buffer->formatted_obstack;
1415   buffer->line_length = 0;
1416   pp_wrapping_mode (pp) = old_wrapping_mode;
1417   pp_clear_state (pp);
1418 }
1419 
1420 /* Format of a message pointed to by TEXT.  */
1421 void
pp_output_formatted_text(pretty_printer * pp)1422 pp_output_formatted_text (pretty_printer *pp)
1423 {
1424   unsigned int chunk;
1425   output_buffer *buffer = pp_buffer (pp);
1426   struct chunk_info *chunk_array = buffer->cur_chunk_array;
1427   const char **args = chunk_array->args;
1428 
1429   gcc_assert (buffer->obstack == &buffer->formatted_obstack);
1430   gcc_assert (buffer->line_length == 0);
1431 
1432   /* This is a third phase, first 2 phases done in pp_format_args.
1433      Now we actually print it.  */
1434   for (chunk = 0; args[chunk]; chunk++)
1435     pp_string (pp, args[chunk]);
1436 
1437   /* Deallocate the chunk structure and everything after it (i.e. the
1438      associated series of formatted strings).  */
1439   buffer->cur_chunk_array = chunk_array->prev;
1440   obstack_free (&buffer->chunk_obstack, chunk_array);
1441 }
1442 
1443 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
1444    settings needed by BUFFER for a verbatim formatting.  */
1445 void
pp_format_verbatim(pretty_printer * pp,text_info * text)1446 pp_format_verbatim (pretty_printer *pp, text_info *text)
1447 {
1448   /* Set verbatim mode.  */
1449   pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
1450 
1451   /* Do the actual formatting.  */
1452   pp_format (pp, text);
1453   pp_output_formatted_text (pp);
1454 
1455   /* Restore previous settings.  */
1456   pp_wrapping_mode (pp) = oldmode;
1457 }
1458 
1459 /* Flush the content of BUFFER onto the attached stream.  This
1460    function does nothing unless pp->output_buffer->flush_p.  */
1461 void
pp_flush(pretty_printer * pp)1462 pp_flush (pretty_printer *pp)
1463 {
1464   pp_clear_state (pp);
1465   if (!pp->buffer->flush_p)
1466     return;
1467   pp_write_text_to_stream (pp);
1468   fflush (pp_buffer (pp)->stream);
1469 }
1470 
1471 /* Flush the content of BUFFER onto the attached stream independently
1472    of the value of pp->output_buffer->flush_p.  */
1473 void
pp_really_flush(pretty_printer * pp)1474 pp_really_flush (pretty_printer *pp)
1475 {
1476   pp_clear_state (pp);
1477   pp_write_text_to_stream (pp);
1478   fflush (pp_buffer (pp)->stream);
1479 }
1480 
1481 /* Sets the number of maximum characters per line PRETTY-PRINTER can
1482    output in line-wrapping mode.  A LENGTH value 0 suppresses
1483    line-wrapping.  */
1484 void
pp_set_line_maximum_length(pretty_printer * pp,int length)1485 pp_set_line_maximum_length (pretty_printer *pp, int length)
1486 {
1487   pp_line_cutoff (pp) = length;
1488   pp_set_real_maximum_length (pp);
1489 }
1490 
1491 /* Clear PRETTY-PRINTER output area text info.  */
1492 void
pp_clear_output_area(pretty_printer * pp)1493 pp_clear_output_area (pretty_printer *pp)
1494 {
1495   obstack_free (pp_buffer (pp)->obstack,
1496                 obstack_base (pp_buffer (pp)->obstack));
1497   pp_buffer (pp)->line_length = 0;
1498 }
1499 
1500 /* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which
1501    will eventually be free-ed.  */
1502 
1503 void
pp_set_prefix(pretty_printer * pp,char * prefix)1504 pp_set_prefix (pretty_printer *pp, char *prefix)
1505 {
1506   free (pp->prefix);
1507   pp->prefix = prefix;
1508   pp_set_real_maximum_length (pp);
1509   pp->emitted_prefix = false;
1510   pp_indentation (pp) = 0;
1511 }
1512 
1513 /* Take ownership of PP's prefix, setting it to NULL.
1514    This allows clients to save, overide, and then restore an existing
1515    prefix, without it being free-ed.  */
1516 
1517 char *
pp_take_prefix(pretty_printer * pp)1518 pp_take_prefix (pretty_printer *pp)
1519 {
1520   char *result = pp->prefix;
1521   pp->prefix = NULL;
1522   return result;
1523 }
1524 
1525 /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string.  */
1526 void
pp_destroy_prefix(pretty_printer * pp)1527 pp_destroy_prefix (pretty_printer *pp)
1528 {
1529   if (pp->prefix != NULL)
1530     {
1531       free (pp->prefix);
1532       pp->prefix = NULL;
1533     }
1534 }
1535 
1536 /* Write out PRETTY-PRINTER's prefix.  */
1537 void
pp_emit_prefix(pretty_printer * pp)1538 pp_emit_prefix (pretty_printer *pp)
1539 {
1540   if (pp->prefix != NULL)
1541     {
1542       switch (pp_prefixing_rule (pp))
1543 	{
1544 	default:
1545 	case DIAGNOSTICS_SHOW_PREFIX_NEVER:
1546 	  break;
1547 
1548 	case DIAGNOSTICS_SHOW_PREFIX_ONCE:
1549 	  if (pp->emitted_prefix)
1550 	    {
1551 	      pp_indent (pp);
1552 	      break;
1553 	    }
1554 	  pp_indentation (pp) += 3;
1555 	  /* Fall through.  */
1556 
1557 	case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
1558 	  {
1559 	    int prefix_length = strlen (pp->prefix);
1560 	    pp_append_r (pp, pp->prefix, prefix_length);
1561 	    pp->emitted_prefix = true;
1562 	  }
1563 	  break;
1564 	}
1565     }
1566 }
1567 
1568 /* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line.  */
1569 
pretty_printer(int maximum_length)1570 pretty_printer::pretty_printer (int maximum_length)
1571   : buffer (new (XCNEW (output_buffer)) output_buffer ()),
1572     prefix (),
1573     padding (pp_none),
1574     maximum_length (),
1575     indent_skip (),
1576     wrapping (),
1577     format_decoder (),
1578     m_format_postprocessor (NULL),
1579     emitted_prefix (),
1580     need_newline (),
1581     translate_identifiers (true),
1582     show_color ()
1583 {
1584   pp_line_cutoff (this) = maximum_length;
1585   /* By default, we emit prefixes once per message.  */
1586   pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
1587   pp_set_prefix (this, NULL);
1588 }
1589 
~pretty_printer()1590 pretty_printer::~pretty_printer ()
1591 {
1592   if (m_format_postprocessor)
1593     delete m_format_postprocessor;
1594   buffer->~output_buffer ();
1595   XDELETE (buffer);
1596   free (prefix);
1597 }
1598 
1599 /* Append a string delimited by START and END to the output area of
1600    PRETTY-PRINTER.  No line wrapping is done.  However, if beginning a
1601    new line then emit PRETTY-PRINTER's prefix and skip any leading
1602    whitespace if appropriate.  The caller must ensure that it is
1603    safe to do so.  */
1604 void
pp_append_text(pretty_printer * pp,const char * start,const char * end)1605 pp_append_text (pretty_printer *pp, const char *start, const char *end)
1606 {
1607   /* Emit prefix and skip whitespace if we're starting a new line.  */
1608   if (pp_buffer (pp)->line_length == 0)
1609     {
1610       pp_emit_prefix (pp);
1611       if (pp_is_wrapping_line (pp))
1612 	while (start != end && *start == ' ')
1613 	  ++start;
1614     }
1615   pp_append_r (pp, start, end - start);
1616 }
1617 
1618 /* Finishes constructing a NULL-terminated character string representing
1619    the PRETTY-PRINTED text.  */
1620 const char *
pp_formatted_text(pretty_printer * pp)1621 pp_formatted_text (pretty_printer *pp)
1622 {
1623   return output_buffer_formatted_text (pp_buffer (pp));
1624 }
1625 
1626 /*  Return a pointer to the last character emitted in PRETTY-PRINTER's
1627     output area.  A NULL pointer means no character available.  */
1628 const char *
pp_last_position_in_text(const pretty_printer * pp)1629 pp_last_position_in_text (const pretty_printer *pp)
1630 {
1631   return output_buffer_last_position_in_text (pp_buffer (pp));
1632 }
1633 
1634 /* Return the amount of characters PRETTY-PRINTER can accept to
1635    make a full line.  Meaningful only in line-wrapping mode.  */
1636 int
pp_remaining_character_count_for_line(pretty_printer * pp)1637 pp_remaining_character_count_for_line (pretty_printer *pp)
1638 {
1639   return pp->maximum_length - pp_buffer (pp)->line_length;
1640 }
1641 
1642 
1643 /* Format a message into BUFFER a la printf.  */
1644 void
pp_printf(pretty_printer * pp,const char * msg,...)1645 pp_printf (pretty_printer *pp, const char *msg, ...)
1646 {
1647   text_info text;
1648   va_list ap;
1649 
1650   va_start (ap, msg);
1651   text.err_no = errno;
1652   text.args_ptr = &ap;
1653   text.format_spec = msg;
1654   pp_format (pp, &text);
1655   pp_output_formatted_text (pp);
1656   va_end (ap);
1657 }
1658 
1659 
1660 /* Output MESSAGE verbatim into BUFFER.  */
1661 void
pp_verbatim(pretty_printer * pp,const char * msg,...)1662 pp_verbatim (pretty_printer *pp, const char *msg, ...)
1663 {
1664   text_info text;
1665   va_list ap;
1666 
1667   va_start (ap, msg);
1668   text.err_no = errno;
1669   text.args_ptr = &ap;
1670   text.format_spec = msg;
1671   pp_format_verbatim (pp, &text);
1672   va_end (ap);
1673 }
1674 
1675 
1676 
1677 /* Have PRETTY-PRINTER start a new line.  */
1678 void
pp_newline(pretty_printer * pp)1679 pp_newline (pretty_printer *pp)
1680 {
1681   obstack_1grow (pp_buffer (pp)->obstack, '\n');
1682   pp_needs_newline (pp) = false;
1683   pp_buffer (pp)->line_length = 0;
1684 }
1685 
1686 /* Have PRETTY-PRINTER add a CHARACTER.  */
1687 void
pp_character(pretty_printer * pp,int c)1688 pp_character (pretty_printer *pp, int c)
1689 {
1690   if (pp_is_wrapping_line (pp)
1691       && pp_remaining_character_count_for_line (pp) <= 0)
1692     {
1693       pp_newline (pp);
1694       if (ISSPACE (c))
1695         return;
1696     }
1697   obstack_1grow (pp_buffer (pp)->obstack, c);
1698   ++pp_buffer (pp)->line_length;
1699 }
1700 
1701 /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
1702    be line-wrapped if in appropriate mode.  */
1703 void
pp_string(pretty_printer * pp,const char * str)1704 pp_string (pretty_printer *pp, const char *str)
1705 {
1706   gcc_checking_assert (str);
1707   pp_maybe_wrap_text (pp, str, str + strlen (str));
1708 }
1709 
1710 /* Append the leading N characters of STRING to the output area of
1711    PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
1712    Setting N = -1 is as if N were set to strlen (STRING).  The STRING
1713    may be line-wrapped if in appropriate mode.  */
1714 static void
pp_quoted_string(pretty_printer * pp,const char * str,size_t n)1715 pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
1716 {
1717   gcc_checking_assert (str);
1718 
1719   const char *last = str;
1720   const char *ps;
1721 
1722   /* Compute the length if not specified.  */
1723   if (n == (size_t) -1)
1724     n = strlen (str);
1725 
1726   for (ps = str; n; ++ps, --n)
1727     {
1728       if (ISPRINT (*ps))
1729 	  continue;
1730 
1731       if (last < ps)
1732 	pp_maybe_wrap_text (pp, last, ps - 1);
1733 
1734       /* Append the hexadecimal value of the character.  Allocate a buffer
1735 	 that's large enough for a 32-bit char plus the hex prefix.  */
1736       char buf [11];
1737       int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
1738       pp_maybe_wrap_text (pp, buf, buf + n);
1739       last = ps + 1;
1740     }
1741 
1742   pp_maybe_wrap_text (pp, last, ps);
1743 }
1744 
1745 /* Maybe print out a whitespace if needed.  */
1746 
1747 void
pp_maybe_space(pretty_printer * pp)1748 pp_maybe_space (pretty_printer *pp)
1749 {
1750   if (pp->padding != pp_none)
1751     {
1752       pp_space (pp);
1753       pp->padding = pp_none;
1754     }
1755 }
1756 
1757 // Add a newline to the pretty printer PP and flush formatted text.
1758 
1759 void
pp_newline_and_flush(pretty_printer * pp)1760 pp_newline_and_flush (pretty_printer *pp)
1761 {
1762   pp_newline (pp);
1763   pp_flush (pp);
1764   pp_needs_newline (pp) = false;
1765 }
1766 
1767 // Add a newline to the pretty printer PP, followed by indentation.
1768 
1769 void
pp_newline_and_indent(pretty_printer * pp,int n)1770 pp_newline_and_indent (pretty_printer *pp, int n)
1771 {
1772   pp_indentation (pp) += n;
1773   pp_newline (pp);
1774   pp_indent (pp);
1775   pp_needs_newline (pp) = false;
1776 }
1777 
1778 // Add separator C, followed by a single whitespace.
1779 
1780 void
pp_separate_with(pretty_printer * pp,char c)1781 pp_separate_with (pretty_printer *pp, char c)
1782 {
1783   pp_character (pp, c);
1784   pp_space (pp);
1785 }
1786 
1787 /* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
1788    using the "quote" color.  */
1789 
1790 void
pp_begin_quote(pretty_printer * pp,bool show_color)1791 pp_begin_quote (pretty_printer *pp, bool show_color)
1792 {
1793   pp_string (pp, open_quote);
1794   pp_string (pp, colorize_start (show_color, "quote"));
1795 }
1796 
1797 /* If SHOW_COLOR is true, stop colorizing.
1798    Add a localized close quote.  */
1799 
1800 void
pp_end_quote(pretty_printer * pp,bool show_color)1801 pp_end_quote (pretty_printer *pp, bool show_color)
1802 {
1803   pp_string (pp, colorize_stop (show_color));
1804   pp_string (pp, close_quote);
1805 }
1806 
1807 
1808 /* The string starting at P has LEN (at least 1) bytes left; if they
1809    start with a valid UTF-8 sequence, return the length of that
1810    sequence and set *VALUE to the value of that sequence, and
1811    otherwise return 0 and set *VALUE to (unsigned int) -1.  */
1812 
1813 static int
decode_utf8_char(const unsigned char * p,size_t len,unsigned int * value)1814 decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
1815 {
1816   unsigned int t = *p;
1817 
1818   if (len == 0)
1819     abort ();
1820   if (t & 0x80)
1821     {
1822       size_t utf8_len = 0;
1823       unsigned int ch;
1824       size_t i;
1825       for (t = *p; t & 0x80; t <<= 1)
1826 	utf8_len++;
1827 
1828       if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
1829 	{
1830 	  *value = (unsigned int) -1;
1831 	  return 0;
1832 	}
1833       ch = *p & ((1 << (7 - utf8_len)) - 1);
1834       for (i = 1; i < utf8_len; i++)
1835 	{
1836 	  unsigned int u = p[i];
1837 	  if ((u & 0xC0) != 0x80)
1838 	    {
1839 	      *value = (unsigned int) -1;
1840 	      return 0;
1841 	    }
1842 	  ch = (ch << 6) | (u & 0x3F);
1843 	}
1844       if (   (ch <=      0x7F && utf8_len > 1)
1845 	  || (ch <=     0x7FF && utf8_len > 2)
1846 	  || (ch <=    0xFFFF && utf8_len > 3)
1847 	  || (ch <=  0x1FFFFF && utf8_len > 4)
1848 	  || (ch <= 0x3FFFFFF && utf8_len > 5)
1849 	  || (ch >= 0xD800 && ch <= 0xDFFF))
1850 	{
1851 	  *value = (unsigned int) -1;
1852 	  return 0;
1853 	}
1854       *value = ch;
1855       return utf8_len;
1856     }
1857   else
1858     {
1859       *value = t;
1860       return 1;
1861     }
1862 }
1863 
1864 /* Allocator for identifier_to_locale and corresponding function to
1865    free memory.  */
1866 
1867 void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
1868 void (*identifier_to_locale_free) (void *) = free;
1869 
1870 /* Given IDENT, an identifier in the internal encoding, return a
1871    version of IDENT suitable for diagnostics in the locale character
1872    set: either IDENT itself, or a string, allocated using
1873    identifier_to_locale_alloc, converted to the locale character set
1874    and using escape sequences if not representable in the locale
1875    character set or containing control characters or invalid byte
1876    sequences.  Existing backslashes in IDENT are not doubled, so the
1877    result may not uniquely specify the contents of an arbitrary byte
1878    sequence identifier.  */
1879 
1880 const char *
identifier_to_locale(const char * ident)1881 identifier_to_locale (const char *ident)
1882 {
1883   const unsigned char *uid = (const unsigned char *) ident;
1884   size_t idlen = strlen (ident);
1885   bool valid_printable_utf8 = true;
1886   bool all_ascii = true;
1887   size_t i;
1888 
1889   for (i = 0; i < idlen;)
1890     {
1891       unsigned int c;
1892       size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
1893       if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
1894 	{
1895 	  valid_printable_utf8 = false;
1896 	  break;
1897 	}
1898       if (utf8_len > 1)
1899 	all_ascii = false;
1900       i += utf8_len;
1901     }
1902 
1903   /* If IDENT contains invalid UTF-8 sequences (which may occur with
1904      attributes putting arbitrary byte sequences in identifiers), or
1905      control characters, we use octal escape sequences for all bytes
1906      outside printable ASCII.  */
1907   if (!valid_printable_utf8)
1908     {
1909       char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
1910       char *p = ret;
1911       for (i = 0; i < idlen; i++)
1912 	{
1913 	  if (uid[i] > 0x1F && uid[i] < 0x7F)
1914 	    *p++ = uid[i];
1915 	  else
1916 	    {
1917 	      sprintf (p, "\\%03o", uid[i]);
1918 	      p += 4;
1919 	    }
1920 	}
1921       *p = 0;
1922       return ret;
1923     }
1924 
1925   /* Otherwise, if it is valid printable ASCII, or printable UTF-8
1926      with the locale character set being UTF-8, IDENT is used.  */
1927   if (all_ascii || locale_utf8)
1928     return ident;
1929 
1930   /* Otherwise IDENT is converted to the locale character set if
1931      possible.  */
1932 #if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
1933   if (locale_encoding != NULL)
1934     {
1935       iconv_t cd = iconv_open (locale_encoding, "UTF-8");
1936       bool conversion_ok = true;
1937       char *ret = NULL;
1938       if (cd != (iconv_t) -1)
1939 	{
1940 	  size_t ret_alloc = 4 * idlen + 1;
1941 	  for (;;)
1942 	    {
1943 	      /* Repeat the whole conversion process as needed with
1944 		 larger buffers so non-reversible transformations can
1945 		 always be detected.  */
1946 	      ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
1947 	      char *outbuf;
1948 	      size_t inbytesleft = idlen;
1949 	      size_t outbytesleft = ret_alloc - 1;
1950 	      size_t iconv_ret;
1951 
1952 	      ret = (char *) identifier_to_locale_alloc (ret_alloc);
1953 	      outbuf = ret;
1954 
1955 	      if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
1956 		{
1957 		  conversion_ok = false;
1958 		  break;
1959 		}
1960 
1961 	      iconv_ret = iconv (cd, &inbuf, &inbytesleft,
1962 				 &outbuf, &outbytesleft);
1963 	      if (iconv_ret == (size_t) -1 || inbytesleft != 0)
1964 		{
1965 		  if (errno == E2BIG)
1966 		    {
1967 		      ret_alloc *= 2;
1968 		      identifier_to_locale_free (ret);
1969 		      ret = NULL;
1970 		      continue;
1971 		    }
1972 		  else
1973 		    {
1974 		      conversion_ok = false;
1975 		      break;
1976 		    }
1977 		}
1978 	      else if (iconv_ret != 0)
1979 		{
1980 		  conversion_ok = false;
1981 		  break;
1982 		}
1983 	      /* Return to initial shift state.  */
1984 	      if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
1985 		{
1986 		  if (errno == E2BIG)
1987 		    {
1988 		      ret_alloc *= 2;
1989 		      identifier_to_locale_free (ret);
1990 		      ret = NULL;
1991 		      continue;
1992 		    }
1993 		  else
1994 		    {
1995 		      conversion_ok = false;
1996 		      break;
1997 		    }
1998 		}
1999 	      *outbuf = 0;
2000 	      break;
2001 	    }
2002 	  iconv_close (cd);
2003 	  if (conversion_ok)
2004 	    return ret;
2005 	}
2006     }
2007 #endif
2008 
2009   /* Otherwise, convert non-ASCII characters in IDENT to UCNs.  */
2010   {
2011     char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
2012     char *p = ret;
2013     for (i = 0; i < idlen;)
2014       {
2015 	unsigned int c;
2016 	size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
2017 	if (utf8_len == 1)
2018 	  *p++ = uid[i];
2019 	else
2020 	  {
2021 	    sprintf (p, "\\U%08x", c);
2022 	    p += 10;
2023 	  }
2024 	i += utf8_len;
2025       }
2026     *p = 0;
2027     return ret;
2028   }
2029 }
2030 
2031 #if CHECKING_P
2032 
2033 namespace selftest {
2034 
2035 /* Smoketest for pretty_printer.  */
2036 
2037 static void
test_basic_printing()2038 test_basic_printing ()
2039 {
2040   pretty_printer pp;
2041   pp_string (&pp, "hello");
2042   pp_space (&pp);
2043   pp_string (&pp, "world");
2044 
2045   ASSERT_STREQ ("hello world", pp_formatted_text (&pp));
2046 }
2047 
2048 /* Helper function for testing pp_format.
2049    Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2050    prints EXPECTED, assuming that pp_show_color is SHOW_COLOR.  */
2051 
2052 static void
assert_pp_format_va(const location & loc,const char * expected,bool show_color,const char * fmt,va_list * ap)2053 assert_pp_format_va (const location &loc, const char *expected,
2054 		     bool show_color, const char *fmt, va_list *ap)
2055 {
2056   pretty_printer pp;
2057   text_info ti;
2058   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2059 
2060   ti.format_spec = fmt;
2061   ti.args_ptr = ap;
2062   ti.err_no = 0;
2063   ti.x_data = NULL;
2064   ti.m_richloc = &rich_loc;
2065 
2066   pp_show_color (&pp) = show_color;
2067   pp_format (&pp, &ti);
2068   pp_output_formatted_text (&pp);
2069   ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
2070 }
2071 
2072 /* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
2073    prints EXPECTED, with show_color disabled.  */
2074 
2075 static void
assert_pp_format(const location & loc,const char * expected,const char * fmt,...)2076 assert_pp_format (const location &loc, const char *expected,
2077 		  const char *fmt, ...)
2078 {
2079   va_list ap;
2080 
2081   va_start (ap, fmt);
2082   assert_pp_format_va (loc, expected, false, fmt, &ap);
2083   va_end (ap);
2084 }
2085 
2086 /* As above, but with colorization enabled.  */
2087 
2088 static void
assert_pp_format_colored(const location & loc,const char * expected,const char * fmt,...)2089 assert_pp_format_colored (const location &loc, const char *expected,
2090 			  const char *fmt, ...)
2091 {
2092   /* The tests of colorization assume the default color scheme.
2093      If GCC_COLORS is set, then the colors have potentially been
2094      overridden; skip the test.  */
2095   if (getenv ("GCC_COLORS"))
2096     return;
2097 
2098   va_list ap;
2099 
2100   va_start (ap, fmt);
2101   assert_pp_format_va (loc, expected, true, fmt, &ap);
2102   va_end (ap);
2103 }
2104 
2105 /* Helper function for calling testing pp_format,
2106    by calling assert_pp_format with various numbers of arguments.
2107    These exist mostly to avoid having to write SELFTEST_LOCATION
2108    throughout test_pp_format.  */
2109 
2110 #define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1)		      \
2111   SELFTEST_BEGIN_STMT					      \
2112     assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2113 		      (ARG1));				      \
2114   SELFTEST_END_STMT
2115 
2116 #define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2)	      \
2117   SELFTEST_BEGIN_STMT					      \
2118     assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2119 		      (ARG1), (ARG2));			      \
2120   SELFTEST_END_STMT
2121 
2122 #define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3)   \
2123   SELFTEST_BEGIN_STMT					      \
2124     assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
2125                       (ARG1), (ARG2), (ARG3));		      \
2126   SELFTEST_END_STMT
2127 
2128 /* Verify that pp_format works, for various format codes.  */
2129 
2130 static void
test_pp_format()2131 test_pp_format ()
2132 {
2133   /* Avoid introducing locale-specific differences in the results
2134      by hardcoding open_quote and close_quote.  */
2135   auto_fix_quotes fix_quotes;
2136 
2137   /* Verify that plain text is passed through unchanged.  */
2138   assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted");
2139 
2140   /* Verify various individual format codes, in the order listed in the
2141      comment for pp_format above.  For each code, we append a second
2142      argument with a known bit pattern (0x12345678), to ensure that we
2143      are consuming arguments correctly.  */
2144   ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678);
2145   ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678);
2146   ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678);
2147   ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678);
2148   ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678);
2149   ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678);
2150   ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678);
2151   ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678);
2152   ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678);
2153   ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe,
2154 		      0x12345678);
2155   ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678);
2156   ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678);
2157   ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678);
2158   ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678);
2159   ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe,
2160 		      0x12345678);
2161   ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678);
2162   ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678);
2163   ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10,
2164 		      0x12345678);
2165   ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
2166   ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
2167 		      0x12345678);
2168   ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
2169   ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
2170   ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
2171 		      0x12345678);
2172 
2173   /* Not nul-terminated.  */
2174   char arr[5] = { '1', '2', '3', '4', '5' };
2175   ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678);
2176   ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678);
2177   ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678);
2178 
2179   /* We can't test for %p; the pointer is printed in an implementation-defined
2180      manner.  */
2181   ASSERT_PP_FORMAT_2 ("normal colored normal 12345678",
2182 		      "normal %rcolored%R normal %x",
2183 		      "error", 0x12345678);
2184   assert_pp_format_colored
2185     (SELFTEST_LOCATION,
2186      "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678",
2187      "normal %rcolored%R normal %x", "error", 0x12345678);
2188   /* TODO:
2189      %m: strerror(text->err_no) - does not consume a value from args_ptr.  */
2190   ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678);
2191   ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678);
2192   ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678);
2193   ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678);
2194   ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678);
2195   ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678);
2196 
2197   /* Verify flag 'q'.  */
2198   ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678);
2199   assert_pp_format_colored (SELFTEST_LOCATION,
2200 			    "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
2201 			    "foo", 0x12345678);
2202 
2203   /* Verify %Z.  */
2204   int v[] = { 1, 2, 3 };
2205   ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
2206 
2207   int v2[] = { 0 };
2208   ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
2209 
2210   /* Verify that combinations work, along with unformatted text.  */
2211   assert_pp_format (SELFTEST_LOCATION,
2212 		    "the quick brown fox jumps over the lazy dog",
2213 		    "the %s %s %s jumps over the %s %s",
2214 		    "quick", "brown", "fox", "lazy", "dog");
2215   assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7);
2216   assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10",
2217 		    "problem with %qs at line %i", "bar", 10);
2218 }
2219 
2220 /* A subclass of pretty_printer for use by test_prefixes_and_wrapping.  */
2221 
2222 class test_pretty_printer : public pretty_printer
2223 {
2224  public:
test_pretty_printer(enum diagnostic_prefixing_rule_t rule,int max_line_length)2225   test_pretty_printer (enum diagnostic_prefixing_rule_t rule,
2226 		       int max_line_length)
2227   {
2228     pp_set_prefix (this, xstrdup ("PREFIX: "));
2229     wrapping.rule = rule;
2230     pp_set_line_maximum_length (this, max_line_length);
2231   }
2232 };
2233 
2234 /* Verify that the various values of enum diagnostic_prefixing_rule_t work
2235    as expected, with and without line wrapping.  */
2236 
2237 static void
test_prefixes_and_wrapping()2238 test_prefixes_and_wrapping ()
2239 {
2240   /* Tests of the various prefixing rules, without wrapping.
2241      Newlines embedded in pp_string don't affect it; we have to
2242      explicitly call pp_newline.  */
2243   {
2244     test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 0);
2245     pp_string (&pp, "the quick brown fox");
2246     pp_newline (&pp);
2247     pp_string (&pp, "jumps over the lazy dog");
2248     pp_newline (&pp);
2249     ASSERT_STREQ (pp_formatted_text (&pp),
2250 		  "PREFIX: the quick brown fox\n"
2251 		  "   jumps over the lazy dog\n");
2252   }
2253   {
2254     test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 0);
2255     pp_string (&pp, "the quick brown fox");
2256     pp_newline (&pp);
2257     pp_string (&pp, "jumps over the lazy dog");
2258     pp_newline (&pp);
2259     ASSERT_STREQ (pp_formatted_text (&pp),
2260 		  "the quick brown fox\n"
2261 		  "jumps over the lazy dog\n");
2262   }
2263   {
2264     test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 0);
2265     pp_string (&pp, "the quick brown fox");
2266     pp_newline (&pp);
2267     pp_string (&pp, "jumps over the lazy dog");
2268     pp_newline (&pp);
2269     ASSERT_STREQ (pp_formatted_text (&pp),
2270 		  "PREFIX: the quick brown fox\n"
2271 		  "PREFIX: jumps over the lazy dog\n");
2272   }
2273 
2274   /* Tests of the various prefixing rules, with wrapping.  */
2275   {
2276     test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 20);
2277     pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2278     pp_newline (&pp);
2279     pp_string (&pp, "able was I ere I saw elba");
2280     pp_newline (&pp);
2281     ASSERT_STREQ (pp_formatted_text (&pp),
2282 		  "PREFIX: the quick \n"
2283 		  "   brown fox jumps \n"
2284 		  "   over the lazy \n"
2285 		  "   dog\n"
2286 		  "   able was I ere I \n"
2287 		  "   saw elba\n");
2288   }
2289   {
2290     test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 20);
2291     pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2292     pp_newline (&pp);
2293     pp_string (&pp, "able was I ere I saw elba");
2294     pp_newline (&pp);
2295     ASSERT_STREQ (pp_formatted_text (&pp),
2296 		  "the quick brown fox \n"
2297 		  "jumps over the lazy \n"
2298 		  "dog\n"
2299 		  "able was I ere I \n"
2300 		  "saw elba\n");
2301   }
2302   {
2303     test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 20);
2304     pp_string (&pp, "the quick brown fox jumps over the lazy dog");
2305     pp_newline (&pp);
2306     pp_string (&pp, "able was I ere I saw elba");
2307     pp_newline (&pp);
2308     ASSERT_STREQ (pp_formatted_text (&pp),
2309 		  "PREFIX: the quick brown fox jumps over the lazy dog\n"
2310 		  "PREFIX: able was I ere I saw elba\n");
2311   }
2312 
2313 }
2314 
2315 /* Run all of the selftests within this file.  */
2316 
2317 void
pretty_print_c_tests()2318 pretty_print_c_tests ()
2319 {
2320   test_basic_printing ();
2321   test_pp_format ();
2322   test_prefixes_and_wrapping ();
2323 }
2324 
2325 } // namespace selftest
2326 
2327 #endif /* CHECKING_P */
2328