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
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
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
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
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
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
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
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 
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 
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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 
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 
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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