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