Mercurial > hg > CbC > CbC_gcc
comparison gcc/pretty-print.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Various declarations for language-independent pretty-print subroutines. | 1 /* Various declarations for language-independent pretty-print subroutines. |
2 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 | 2 Copyright (C) 2003-2017 Free Software Foundation, Inc. |
3 Free Software Foundation, Inc. | |
4 Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net> | 3 Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net> |
5 | 4 |
6 This file is part of GCC. | 5 This file is part of GCC. |
7 | 6 |
8 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
22 #include "config.h" | 21 #include "config.h" |
23 #include "system.h" | 22 #include "system.h" |
24 #include "coretypes.h" | 23 #include "coretypes.h" |
25 #include "intl.h" | 24 #include "intl.h" |
26 #include "pretty-print.h" | 25 #include "pretty-print.h" |
26 #include "diagnostic-color.h" | |
27 #include "selftest.h" | |
27 | 28 |
28 #if HAVE_ICONV | 29 #if HAVE_ICONV |
29 #include <iconv.h> | 30 #include <iconv.h> |
30 #endif | 31 #endif |
31 | 32 |
32 /* A pointer to the formatted diagnostic message. */ | 33 #ifdef __MINGW32__ |
33 #define pp_formatted_text_data(PP) \ | 34 |
34 ((const char *) obstack_base (pp_base (PP)->buffer->obstack)) | 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 SetConsoleTextAttribute (h, attrib_add); | |
644 break; | |
645 } | |
646 } | |
647 | |
648 int | |
649 mingw_ansi_fputs (const char *str, FILE *fp) | |
650 { | |
651 const char *read = str; | |
652 HANDLE h; | |
653 DWORD mode; | |
654 int esc_code, prefix_len; | |
655 const char *esc_head, *esc_term; | |
656 | |
657 h = (HANDLE) _get_osfhandle (_fileno (fp)); | |
658 if (h == INVALID_HANDLE_VALUE) | |
659 return EOF; | |
660 | |
661 /* Don't mess up stdio functions with Windows APIs. */ | |
662 fflush (fp); | |
663 | |
664 if (GetConsoleMode (h, &mode)) | |
665 /* If it is a console, translate ANSI escape codes as needed. */ | |
666 for (;;) | |
667 { | |
668 if ((esc_code = find_esc_head (&prefix_len, &esc_head, read)) == 0) | |
669 { | |
670 /* Write all remaining characters, then exit. */ | |
671 write_all (h, read, strlen (read)); | |
672 break; | |
673 } | |
674 if (find_esc_terminator (&esc_term, esc_head) == 0) | |
675 /* Ignore incomplete escape sequences at the moment. | |
676 FIXME: The escape state shall be cached for further calls | |
677 to this function. */ | |
678 break; | |
679 write_all (h, read, esc_head - prefix_len - read); | |
680 eat_esc_sequence (h, esc_code, esc_head, esc_term); | |
681 read = esc_term + 1; | |
682 } | |
683 else | |
684 /* If it is not a console, write everything as-is. */ | |
685 write_all (h, read, strlen (read)); | |
686 | |
687 _close ((intptr_t) h); | |
688 return 1; | |
689 } | |
690 | |
691 #endif /* __MINGW32__ */ | |
692 | |
693 static void pp_quoted_string (pretty_printer *, const char *, size_t = -1); | |
694 | |
695 /* Overwrite the given location/range within this text_info's rich_location. | |
696 For use e.g. when implementing "+" in client format decoders. */ | |
697 | |
698 void | |
699 text_info::set_location (unsigned int idx, location_t loc, bool show_caret_p) | |
700 { | |
701 gcc_checking_assert (m_richloc); | |
702 m_richloc->set_range (line_table, idx, loc, show_caret_p); | |
703 } | |
704 | |
705 location_t | |
706 text_info::get_location (unsigned int index_of_location) const | |
707 { | |
708 gcc_checking_assert (m_richloc); | |
709 | |
710 if (index_of_location == 0) | |
711 return m_richloc->get_loc (); | |
712 else | |
713 return UNKNOWN_LOCATION; | |
714 } | |
715 | |
716 // Default construct an output buffer. | |
717 | |
718 output_buffer::output_buffer () | |
719 : formatted_obstack (), | |
720 chunk_obstack (), | |
721 obstack (&formatted_obstack), | |
722 cur_chunk_array (), | |
723 stream (stderr), | |
724 line_length (), | |
725 digit_buffer (), | |
726 flush_p (true) | |
727 { | |
728 obstack_init (&formatted_obstack); | |
729 obstack_init (&chunk_obstack); | |
730 } | |
731 | |
732 // Release resources owned by an output buffer at the end of lifetime. | |
733 | |
734 output_buffer::~output_buffer () | |
735 { | |
736 obstack_free (&chunk_obstack, NULL); | |
737 obstack_free (&formatted_obstack, NULL); | |
738 } | |
739 | |
35 | 740 |
36 /* Format an integer given by va_arg (ARG, type-specifier T) where | 741 /* Format an integer given by va_arg (ARG, type-specifier T) where |
37 type-specifier is a precision modifier as indicated by PREC. F is | 742 type-specifier is a precision modifier as indicated by PREC. F is |
38 a string used to construct the appropriate format-specifier. */ | 743 a string used to construct the appropriate format-specifier. */ |
39 #define pp_integer_with_precision(PP, ARG, PREC, T, F) \ | 744 #define pp_integer_with_precision(PP, ARG, PREC, T, F) \ |
93 /* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */ | 798 /* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */ |
94 void | 799 void |
95 pp_write_text_to_stream (pretty_printer *pp) | 800 pp_write_text_to_stream (pretty_printer *pp) |
96 { | 801 { |
97 const char *text = pp_formatted_text (pp); | 802 const char *text = pp_formatted_text (pp); |
98 fputs (text, pp->buffer->stream); | 803 #ifdef __MINGW32__ |
804 mingw_ansi_fputs (text, pp_buffer (pp)->stream); | |
805 #else | |
806 fputs (text, pp_buffer (pp)->stream); | |
807 #endif | |
808 pp_clear_output_area (pp); | |
809 } | |
810 | |
811 /* As pp_write_text_to_stream, but for GraphViz label output. | |
812 | |
813 Flush the formatted text of pretty-printer PP onto the attached stream. | |
814 Replace characters in PPF that have special meaning in a GraphViz .dot | |
815 file. | |
816 | |
817 This routine is not very fast, but it doesn't have to be as this is only | |
818 be used by routines dumping intermediate representations in graph form. */ | |
819 | |
820 void | |
821 pp_write_text_as_dot_label_to_stream (pretty_printer *pp, bool for_record) | |
822 { | |
823 const char *text = pp_formatted_text (pp); | |
824 const char *p = text; | |
825 FILE *fp = pp_buffer (pp)->stream; | |
826 | |
827 for (;*p; p++) | |
828 { | |
829 bool escape_char; | |
830 switch (*p) | |
831 { | |
832 /* Print newlines as a left-aligned newline. */ | |
833 case '\n': | |
834 fputs ("\\l", fp); | |
835 escape_char = true; | |
836 break; | |
837 | |
838 /* The following characters are only special for record-shape nodes. */ | |
839 case '|': | |
840 case '{': | |
841 case '}': | |
842 case '<': | |
843 case '>': | |
844 case ' ': | |
845 escape_char = for_record; | |
846 break; | |
847 | |
848 /* The following characters always have to be escaped | |
849 for use in labels. */ | |
850 case '\\': | |
851 /* There is a bug in some (f.i. 2.36.0) versions of graphiz | |
852 ( http://www.graphviz.org/mantisbt/view.php?id=2524 ) related to | |
853 backslash as last char in label. Let's avoid triggering it. */ | |
854 gcc_assert (*(p + 1) != '\0'); | |
855 /* Fall through. */ | |
856 case '"': | |
857 escape_char = true; | |
858 break; | |
859 | |
860 default: | |
861 escape_char = false; | |
862 break; | |
863 } | |
864 | |
865 if (escape_char) | |
866 fputc ('\\', fp); | |
867 | |
868 fputc (*p, fp); | |
869 } | |
870 | |
99 pp_clear_output_area (pp); | 871 pp_clear_output_area (pp); |
100 } | 872 } |
101 | 873 |
102 /* Wrap a text delimited by START and END into PRETTY-PRINTER. */ | 874 /* Wrap a text delimited by START and END into PRETTY-PRINTER. */ |
103 static void | 875 static void |
145 /* Append to the output area of PRETTY-PRINTER a string specified by its | 917 /* Append to the output area of PRETTY-PRINTER a string specified by its |
146 STARTing character and LENGTH. */ | 918 STARTing character and LENGTH. */ |
147 static inline void | 919 static inline void |
148 pp_append_r (pretty_printer *pp, const char *start, int length) | 920 pp_append_r (pretty_printer *pp, const char *start, int length) |
149 { | 921 { |
150 obstack_grow (pp->buffer->obstack, start, length); | 922 output_buffer_append_r (pp_buffer (pp), start, length); |
151 pp->buffer->line_length += length; | |
152 } | 923 } |
153 | 924 |
154 /* Insert enough spaces into the output area of PRETTY-PRINTER to bring | 925 /* Insert enough spaces into the output area of PRETTY-PRINTER to bring |
155 the column position to the current indentation level, assuming that a | 926 the column position to the current indentation level, assuming that a |
156 newline has just been written to the buffer. */ | 927 newline has just been written to the buffer. */ |
157 void | 928 void |
158 pp_base_indent (pretty_printer *pp) | 929 pp_indent (pretty_printer *pp) |
159 { | 930 { |
160 int n = pp_indentation (pp); | 931 int n = pp_indentation (pp); |
161 int i; | 932 int i; |
162 | 933 |
163 for (i = 0; i < n; ++i) | 934 for (i = 0; i < n; ++i) |
172 %ld, %li, %lo, %lu, %lx: long versions of the above. | 943 %ld, %li, %lo, %lu, %lx: long versions of the above. |
173 %lld, %lli, %llo, %llu, %llx: long long versions. | 944 %lld, %lli, %llo, %llu, %llx: long long versions. |
174 %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions. | 945 %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions. |
175 %c: character. | 946 %c: character. |
176 %s: string. | 947 %s: string. |
177 %p: pointer. | 948 %p: pointer (printed in a host-dependent manner). |
949 %r: if pp_show_color(pp), switch to color identified by const char *. | |
950 %R: if pp_show_color(pp), reset color. | |
178 %m: strerror(text->err_no) - does not consume a value from args_ptr. | 951 %m: strerror(text->err_no) - does not consume a value from args_ptr. |
179 %%: '%'. | 952 %%: '%'. |
180 %<: opening quote. | 953 %<: opening quote. |
181 %>: closing quote. | 954 %>: closing quote. |
182 %': apostrophe (should only be used in untranslated messages; | 955 %': apostrophe (should only be used in untranslated messages; |
183 translations should use appropriate punctuation directly). | 956 translations should use appropriate punctuation directly). |
184 %.*s: a substring the length of which is specified by an argument | 957 %.*s: a substring the length of which is specified by an argument |
185 integer. | 958 integer. |
186 %Ns: likewise, but length specified as constant in the format string. | 959 %Ns: likewise, but length specified as constant in the format string. |
187 Flag 'q': quote formatted text (must come immediately after '%'). | 960 Flag 'q': quote formatted text (must come immediately after '%'). |
961 %Z: Requires two arguments - array of int, and len. Prints elements | |
962 of the array. | |
188 | 963 |
189 Arguments can be used sequentially, or through %N$ resp. *N$ | 964 Arguments can be used sequentially, or through %N$ resp. *N$ |
190 notation Nth argument after the format string. If %N$ / *N$ | 965 notation Nth argument after the format string. If %N$ / *N$ |
191 notation is used, it must be used for all arguments, except %m, %%, | 966 notation is used, it must be used for all arguments, except %m, %%, |
192 %<, %> and %', which may not have a number, as they do not consume | 967 %<, %> and %', which may not have a number, as they do not consume |
195 format string must have conversion specifiers with argument numbers | 970 format string must have conversion specifiers with argument numbers |
196 1 up to highest argument; each argument may only be used once. | 971 1 up to highest argument; each argument may only be used once. |
197 A format string can have at most 30 arguments. */ | 972 A format string can have at most 30 arguments. */ |
198 | 973 |
199 /* Formatting phases 1 and 2: render TEXT->format_spec plus | 974 /* Formatting phases 1 and 2: render TEXT->format_spec plus |
200 TEXT->args_ptr into a series of chunks in PP->buffer->args[]. | 975 TEXT->args_ptr into a series of chunks in pp_buffer (PP)->args[]. |
201 Phase 3 is in pp_base_format_text. */ | 976 Phase 3 is in pp_output_formatted_text. */ |
202 | 977 |
203 void | 978 void |
204 pp_base_format (pretty_printer *pp, text_info *text) | 979 pp_format (pretty_printer *pp, text_info *text) |
205 { | 980 { |
206 output_buffer *buffer = pp->buffer; | 981 output_buffer *buffer = pp_buffer (pp); |
207 const char *p; | 982 const char *p; |
208 const char **args; | 983 const char **args; |
209 struct chunk_info *new_chunk_array; | 984 struct chunk_info *new_chunk_array; |
210 | 985 |
211 unsigned int curarg = 0, chunk = 0, argno; | 986 unsigned int curarg = 0, chunk = 0, argno; |
218 new_chunk_array->prev = buffer->cur_chunk_array; | 993 new_chunk_array->prev = buffer->cur_chunk_array; |
219 buffer->cur_chunk_array = new_chunk_array; | 994 buffer->cur_chunk_array = new_chunk_array; |
220 args = new_chunk_array->args; | 995 args = new_chunk_array->args; |
221 | 996 |
222 /* Formatting phase 1: split up TEXT->format_spec into chunks in | 997 /* Formatting phase 1: split up TEXT->format_spec into chunks in |
223 PP->buffer->args[]. Even-numbered chunks are to be output | 998 pp_buffer (PP)->args[]. Even-numbered chunks are to be output |
224 verbatim, odd-numbered chunks are format specifiers. | 999 verbatim, odd-numbered chunks are format specifiers. |
225 %m, %%, %<, %>, and %' are replaced with the appropriate text at | 1000 %m, %%, %<, %>, and %' are replaced with the appropriate text at |
226 this point. */ | 1001 this point. */ |
227 | 1002 |
228 memset (formatters, 0, sizeof formatters); | 1003 memset (formatters, 0, sizeof formatters); |
247 obstack_1grow (&buffer->chunk_obstack, '%'); | 1022 obstack_1grow (&buffer->chunk_obstack, '%'); |
248 p++; | 1023 p++; |
249 continue; | 1024 continue; |
250 | 1025 |
251 case '<': | 1026 case '<': |
252 obstack_grow (&buffer->chunk_obstack, | 1027 { |
253 open_quote, strlen (open_quote)); | 1028 obstack_grow (&buffer->chunk_obstack, |
254 p++; | 1029 open_quote, strlen (open_quote)); |
255 continue; | 1030 const char *colorstr |
1031 = colorize_start (pp_show_color (pp), "quote"); | |
1032 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr)); | |
1033 p++; | |
1034 continue; | |
1035 } | |
256 | 1036 |
257 case '>': | 1037 case '>': |
1038 { | |
1039 const char *colorstr = colorize_stop (pp_show_color (pp)); | |
1040 obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr)); | |
1041 } | |
1042 /* FALLTHRU */ | |
258 case '\'': | 1043 case '\'': |
259 obstack_grow (&buffer->chunk_obstack, | 1044 obstack_grow (&buffer->chunk_obstack, |
260 close_quote, strlen (close_quote)); | 1045 close_quote, strlen (close_quote)); |
261 p++; | 1046 p++; |
262 continue; | 1047 continue; |
1048 | |
1049 case 'R': | |
1050 { | |
1051 const char *colorstr = colorize_stop (pp_show_color (pp)); | |
1052 obstack_grow (&buffer->chunk_obstack, colorstr, | |
1053 strlen (colorstr)); | |
1054 p++; | |
1055 continue; | |
1056 } | |
263 | 1057 |
264 case 'm': | 1058 case 'm': |
265 { | 1059 { |
266 const char *errstr = xstrerror (text->err_no); | 1060 const char *errstr = xstrerror (text->err_no); |
267 obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr)); | 1061 obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr)); |
413 } | 1207 } |
414 | 1208 |
415 gcc_assert (!wide || precision == 0); | 1209 gcc_assert (!wide || precision == 0); |
416 | 1210 |
417 if (quote) | 1211 if (quote) |
418 pp_string (pp, open_quote); | 1212 { |
1213 pp_string (pp, open_quote); | |
1214 pp_string (pp, colorize_start (pp_show_color (pp), "quote")); | |
1215 } | |
419 | 1216 |
420 switch (*p) | 1217 switch (*p) |
421 { | 1218 { |
1219 case 'r': | |
1220 pp_string (pp, colorize_start (pp_show_color (pp), | |
1221 va_arg (*text->args_ptr, | |
1222 const char *))); | |
1223 break; | |
1224 | |
422 case 'c': | 1225 case 'c': |
423 pp_character (pp, va_arg (*text->args_ptr, int)); | 1226 { |
424 break; | 1227 /* When quoting, print alphanumeric, punctuation, and the space |
1228 character unchanged, and all others in hexadecimal with the | |
1229 "\x" prefix. Otherwise print them all unchanged. */ | |
1230 int chr = va_arg (*text->args_ptr, int); | |
1231 if (ISPRINT (chr) || !quote) | |
1232 pp_character (pp, chr); | |
1233 else | |
1234 { | |
1235 const char str [2] = { chr, '\0' }; | |
1236 pp_quoted_string (pp, str, 1); | |
1237 } | |
1238 break; | |
1239 } | |
425 | 1240 |
426 case 'd': | 1241 case 'd': |
427 case 'i': | 1242 case 'i': |
428 if (wide) | 1243 if (wide) |
429 pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT)); | 1244 pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT)); |
440 pp_integer_with_precision | 1255 pp_integer_with_precision |
441 (pp, *text->args_ptr, precision, unsigned, "o"); | 1256 (pp, *text->args_ptr, precision, unsigned, "o"); |
442 break; | 1257 break; |
443 | 1258 |
444 case 's': | 1259 case 's': |
445 pp_string (pp, va_arg (*text->args_ptr, const char *)); | 1260 if (quote) |
1261 pp_quoted_string (pp, va_arg (*text->args_ptr, const char *)); | |
1262 else | |
1263 pp_string (pp, va_arg (*text->args_ptr, const char *)); | |
446 break; | 1264 break; |
447 | 1265 |
448 case 'p': | 1266 case 'p': |
449 pp_pointer (pp, va_arg (*text->args_ptr, void *)); | 1267 pp_pointer (pp, va_arg (*text->args_ptr, void *)); |
450 break; | 1268 break; |
455 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT)); | 1273 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT)); |
456 else | 1274 else |
457 pp_integer_with_precision | 1275 pp_integer_with_precision |
458 (pp, *text->args_ptr, precision, unsigned, "u"); | 1276 (pp, *text->args_ptr, precision, unsigned, "u"); |
459 break; | 1277 break; |
1278 | |
1279 case 'Z': | |
1280 { | |
1281 int *v = va_arg (*text->args_ptr, int *); | |
1282 unsigned len = va_arg (*text->args_ptr, unsigned); | |
1283 | |
1284 for (unsigned i = 0; i < len; ++i) | |
1285 { | |
1286 pp_scalar (pp, "%i", v[i]); | |
1287 if (i < len - 1) | |
1288 { | |
1289 pp_comma (pp); | |
1290 pp_space (pp); | |
1291 } | |
1292 } | |
1293 break; | |
1294 } | |
460 | 1295 |
461 case 'x': | 1296 case 'x': |
462 if (wide) | 1297 if (wide) |
463 pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX, | 1298 pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX, |
464 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT)); | 1299 va_arg (*text->args_ptr, unsigned HOST_WIDE_INT)); |
494 gcc_assert (formatters[argno] == formatters[argno+1]); | 1329 gcc_assert (formatters[argno] == formatters[argno+1]); |
495 argno++; | 1330 argno++; |
496 } | 1331 } |
497 | 1332 |
498 s = va_arg (*text->args_ptr, const char *); | 1333 s = va_arg (*text->args_ptr, const char *); |
499 pp_append_text (pp, s, s + n); | 1334 |
1335 /* Append the lesser of precision and strlen (s) characters | |
1336 from the array (which need not be a nul-terminated string). | |
1337 Negative precision is treated as if it were omitted. */ | |
1338 size_t len = n < 0 ? strlen (s) : strnlen (s, n); | |
1339 | |
1340 pp_append_text (pp, s, s + len); | |
500 } | 1341 } |
501 break; | 1342 break; |
502 | 1343 |
503 default: | 1344 default: |
504 { | 1345 { |
505 bool ok; | 1346 bool ok; |
506 | 1347 |
507 gcc_assert (pp_format_decoder (pp)); | 1348 gcc_assert (pp_format_decoder (pp)); |
508 ok = pp_format_decoder (pp) (pp, text, p, | 1349 ok = pp_format_decoder (pp) (pp, text, p, |
509 precision, wide, plus, hash); | 1350 precision, wide, plus, hash, quote, |
1351 formatters[argno]); | |
510 gcc_assert (ok); | 1352 gcc_assert (ok); |
511 } | 1353 } |
512 } | 1354 } |
513 | 1355 |
514 if (quote) | 1356 if (quote) |
515 pp_string (pp, close_quote); | 1357 { |
1358 pp_string (pp, colorize_stop (pp_show_color (pp))); | |
1359 pp_string (pp, close_quote); | |
1360 } | |
516 | 1361 |
517 obstack_1grow (&buffer->chunk_obstack, '\0'); | 1362 obstack_1grow (&buffer->chunk_obstack, '\0'); |
518 *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *); | 1363 *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *); |
519 } | 1364 } |
520 | 1365 |
521 #ifdef ENABLE_CHECKING | 1366 if (CHECKING_P) |
522 for (; argno < PP_NL_ARGMAX; argno++) | 1367 for (; argno < PP_NL_ARGMAX; argno++) |
523 gcc_assert (!formatters[argno]); | 1368 gcc_assert (!formatters[argno]); |
524 #endif | 1369 |
1370 /* If the client supplied a postprocessing object, call its "handle" | |
1371 hook here. */ | |
1372 if (pp->m_format_postprocessor) | |
1373 pp->m_format_postprocessor->handle (pp); | |
525 | 1374 |
526 /* Revert to normal obstack and wrapping mode. */ | 1375 /* Revert to normal obstack and wrapping mode. */ |
527 buffer->obstack = &buffer->formatted_obstack; | 1376 buffer->obstack = &buffer->formatted_obstack; |
528 buffer->line_length = 0; | 1377 buffer->line_length = 0; |
529 pp_wrapping_mode (pp) = old_wrapping_mode; | 1378 pp_wrapping_mode (pp) = old_wrapping_mode; |
530 pp_clear_state (pp); | 1379 pp_clear_state (pp); |
531 } | 1380 } |
532 | 1381 |
533 /* Format of a message pointed to by TEXT. */ | 1382 /* Format of a message pointed to by TEXT. */ |
534 void | 1383 void |
535 pp_base_output_formatted_text (pretty_printer *pp) | 1384 pp_output_formatted_text (pretty_printer *pp) |
536 { | 1385 { |
537 unsigned int chunk; | 1386 unsigned int chunk; |
538 output_buffer *buffer = pp_buffer (pp); | 1387 output_buffer *buffer = pp_buffer (pp); |
539 struct chunk_info *chunk_array = buffer->cur_chunk_array; | 1388 struct chunk_info *chunk_array = buffer->cur_chunk_array; |
540 const char **args = chunk_array->args; | 1389 const char **args = chunk_array->args; |
541 | 1390 |
542 gcc_assert (buffer->obstack == &buffer->formatted_obstack); | 1391 gcc_assert (buffer->obstack == &buffer->formatted_obstack); |
543 gcc_assert (buffer->line_length == 0); | 1392 gcc_assert (buffer->line_length == 0); |
544 | 1393 |
545 /* This is a third phase, first 2 phases done in pp_base_format_args. | 1394 /* This is a third phase, first 2 phases done in pp_format_args. |
546 Now we actually print it. */ | 1395 Now we actually print it. */ |
547 for (chunk = 0; args[chunk]; chunk++) | 1396 for (chunk = 0; args[chunk]; chunk++) |
548 pp_string (pp, args[chunk]); | 1397 pp_string (pp, args[chunk]); |
549 | 1398 |
550 /* Deallocate the chunk structure and everything after it (i.e. the | 1399 /* Deallocate the chunk structure and everything after it (i.e. the |
554 } | 1403 } |
555 | 1404 |
556 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate | 1405 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate |
557 settings needed by BUFFER for a verbatim formatting. */ | 1406 settings needed by BUFFER for a verbatim formatting. */ |
558 void | 1407 void |
559 pp_base_format_verbatim (pretty_printer *pp, text_info *text) | 1408 pp_format_verbatim (pretty_printer *pp, text_info *text) |
560 { | 1409 { |
561 /* Set verbatim mode. */ | 1410 /* Set verbatim mode. */ |
562 pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp); | 1411 pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp); |
563 | 1412 |
564 /* Do the actual formatting. */ | 1413 /* Do the actual formatting. */ |
567 | 1416 |
568 /* Restore previous settings. */ | 1417 /* Restore previous settings. */ |
569 pp_wrapping_mode (pp) = oldmode; | 1418 pp_wrapping_mode (pp) = oldmode; |
570 } | 1419 } |
571 | 1420 |
572 /* Flush the content of BUFFER onto the attached stream. */ | 1421 /* Flush the content of BUFFER onto the attached stream. This |
573 void | 1422 function does nothing unless pp->output_buffer->flush_p. */ |
574 pp_base_flush (pretty_printer *pp) | 1423 void |
575 { | 1424 pp_flush (pretty_printer *pp) |
1425 { | |
1426 pp_clear_state (pp); | |
1427 if (!pp->buffer->flush_p) | |
1428 return; | |
576 pp_write_text_to_stream (pp); | 1429 pp_write_text_to_stream (pp); |
1430 fflush (pp_buffer (pp)->stream); | |
1431 } | |
1432 | |
1433 /* Flush the content of BUFFER onto the attached stream independently | |
1434 of the value of pp->output_buffer->flush_p. */ | |
1435 void | |
1436 pp_really_flush (pretty_printer *pp) | |
1437 { | |
577 pp_clear_state (pp); | 1438 pp_clear_state (pp); |
578 fputc ('\n', pp->buffer->stream); | 1439 pp_write_text_to_stream (pp); |
579 fflush (pp->buffer->stream); | 1440 fflush (pp_buffer (pp)->stream); |
580 pp_needs_newline (pp) = false; | |
581 } | 1441 } |
582 | 1442 |
583 /* Sets the number of maximum characters per line PRETTY-PRINTER can | 1443 /* Sets the number of maximum characters per line PRETTY-PRINTER can |
584 output in line-wrapping mode. A LENGTH value 0 suppresses | 1444 output in line-wrapping mode. A LENGTH value 0 suppresses |
585 line-wrapping. */ | 1445 line-wrapping. */ |
586 void | 1446 void |
587 pp_base_set_line_maximum_length (pretty_printer *pp, int length) | 1447 pp_set_line_maximum_length (pretty_printer *pp, int length) |
588 { | 1448 { |
589 pp_line_cutoff (pp) = length; | 1449 pp_line_cutoff (pp) = length; |
590 pp_set_real_maximum_length (pp); | 1450 pp_set_real_maximum_length (pp); |
591 } | 1451 } |
592 | 1452 |
593 /* Clear PRETTY-PRINTER output area text info. */ | 1453 /* Clear PRETTY-PRINTER output area text info. */ |
594 void | 1454 void |
595 pp_base_clear_output_area (pretty_printer *pp) | 1455 pp_clear_output_area (pretty_printer *pp) |
596 { | 1456 { |
597 obstack_free (pp->buffer->obstack, obstack_base (pp->buffer->obstack)); | 1457 obstack_free (pp_buffer (pp)->obstack, |
598 pp->buffer->line_length = 0; | 1458 obstack_base (pp_buffer (pp)->obstack)); |
1459 pp_buffer (pp)->line_length = 0; | |
599 } | 1460 } |
600 | 1461 |
601 /* Set PREFIX for PRETTY-PRINTER. */ | 1462 /* Set PREFIX for PRETTY-PRINTER. */ |
602 void | 1463 void |
603 pp_base_set_prefix (pretty_printer *pp, const char *prefix) | 1464 pp_set_prefix (pretty_printer *pp, const char *prefix) |
604 { | 1465 { |
605 pp->prefix = prefix; | 1466 pp->prefix = prefix; |
606 pp_set_real_maximum_length (pp); | 1467 pp_set_real_maximum_length (pp); |
607 pp->emitted_prefix = false; | 1468 pp->emitted_prefix = false; |
608 pp_indentation (pp) = 0; | 1469 pp_indentation (pp) = 0; |
609 } | 1470 } |
610 | 1471 |
611 /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */ | 1472 /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */ |
612 void | 1473 void |
613 pp_base_destroy_prefix (pretty_printer *pp) | 1474 pp_destroy_prefix (pretty_printer *pp) |
614 { | 1475 { |
615 if (pp->prefix != NULL) | 1476 if (pp->prefix != NULL) |
616 { | 1477 { |
617 free (CONST_CAST (char *, pp->prefix)); | 1478 free (CONST_CAST (char *, pp->prefix)); |
618 pp->prefix = NULL; | 1479 pp->prefix = NULL; |
619 } | 1480 } |
620 } | 1481 } |
621 | 1482 |
622 /* Write out PRETTY-PRINTER's prefix. */ | 1483 /* Write out PRETTY-PRINTER's prefix. */ |
623 void | 1484 void |
624 pp_base_emit_prefix (pretty_printer *pp) | 1485 pp_emit_prefix (pretty_printer *pp) |
625 { | 1486 { |
626 if (pp->prefix != NULL) | 1487 if (pp->prefix != NULL) |
627 { | 1488 { |
628 switch (pp_prefixing_rule (pp)) | 1489 switch (pp_prefixing_rule (pp)) |
629 { | 1490 { |
632 break; | 1493 break; |
633 | 1494 |
634 case DIAGNOSTICS_SHOW_PREFIX_ONCE: | 1495 case DIAGNOSTICS_SHOW_PREFIX_ONCE: |
635 if (pp->emitted_prefix) | 1496 if (pp->emitted_prefix) |
636 { | 1497 { |
637 pp_base_indent (pp); | 1498 pp_indent (pp); |
638 break; | 1499 break; |
639 } | 1500 } |
640 pp_indentation (pp) += 3; | 1501 pp_indentation (pp) += 3; |
641 /* Fall through. */ | 1502 /* Fall through. */ |
642 | 1503 |
651 } | 1512 } |
652 } | 1513 } |
653 | 1514 |
654 /* Construct a PRETTY-PRINTER with PREFIX and of MAXIMUM_LENGTH | 1515 /* Construct a PRETTY-PRINTER with PREFIX and of MAXIMUM_LENGTH |
655 characters per line. */ | 1516 characters per line. */ |
656 void | 1517 |
657 pp_construct (pretty_printer *pp, const char *prefix, int maximum_length) | 1518 pretty_printer::pretty_printer (const char *p, int l) |
658 { | 1519 : buffer (new (XCNEW (output_buffer)) output_buffer ()), |
659 memset (pp, 0, sizeof (pretty_printer)); | 1520 prefix (), |
660 pp->buffer = XCNEW (output_buffer); | 1521 padding (pp_none), |
661 obstack_init (&pp->buffer->chunk_obstack); | 1522 maximum_length (), |
662 obstack_init (&pp->buffer->formatted_obstack); | 1523 indent_skip (), |
663 pp->buffer->obstack = &pp->buffer->formatted_obstack; | 1524 wrapping (), |
664 pp->buffer->stream = stderr; | 1525 format_decoder (), |
665 pp_line_cutoff (pp) = maximum_length; | 1526 m_format_postprocessor (NULL), |
666 pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_ONCE; | 1527 emitted_prefix (), |
667 pp_set_prefix (pp, prefix); | 1528 need_newline (), |
668 pp_translate_identifiers (pp) = true; | 1529 translate_identifiers (true), |
1530 show_color () | |
1531 { | |
1532 pp_line_cutoff (this) = l; | |
1533 /* By default, we emit prefixes once per message. */ | |
1534 pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE; | |
1535 pp_set_prefix (this, p); | |
1536 } | |
1537 | |
1538 pretty_printer::~pretty_printer () | |
1539 { | |
1540 if (m_format_postprocessor) | |
1541 delete m_format_postprocessor; | |
1542 buffer->~output_buffer (); | |
1543 XDELETE (buffer); | |
669 } | 1544 } |
670 | 1545 |
671 /* Append a string delimited by START and END to the output area of | 1546 /* Append a string delimited by START and END to the output area of |
672 PRETTY-PRINTER. No line wrapping is done. However, if beginning a | 1547 PRETTY-PRINTER. No line wrapping is done. However, if beginning a |
673 new line then emit PRETTY-PRINTER's prefix and skip any leading | 1548 new line then emit PRETTY-PRINTER's prefix and skip any leading |
674 whitespace if appropriate. The caller must ensure that it is | 1549 whitespace if appropriate. The caller must ensure that it is |
675 safe to do so. */ | 1550 safe to do so. */ |
676 void | 1551 void |
677 pp_base_append_text (pretty_printer *pp, const char *start, const char *end) | 1552 pp_append_text (pretty_printer *pp, const char *start, const char *end) |
678 { | 1553 { |
679 /* Emit prefix and skip whitespace if we're starting a new line. */ | 1554 /* Emit prefix and skip whitespace if we're starting a new line. */ |
680 if (pp->buffer->line_length == 0) | 1555 if (pp_buffer (pp)->line_length == 0) |
681 { | 1556 { |
682 pp_emit_prefix (pp); | 1557 pp_emit_prefix (pp); |
683 if (pp_is_wrapping_line (pp)) | 1558 if (pp_is_wrapping_line (pp)) |
684 while (start != end && *start == ' ') | 1559 while (start != end && *start == ' ') |
685 ++start; | 1560 ++start; |
688 } | 1563 } |
689 | 1564 |
690 /* Finishes constructing a NULL-terminated character string representing | 1565 /* Finishes constructing a NULL-terminated character string representing |
691 the PRETTY-PRINTED text. */ | 1566 the PRETTY-PRINTED text. */ |
692 const char * | 1567 const char * |
693 pp_base_formatted_text (pretty_printer *pp) | 1568 pp_formatted_text (pretty_printer *pp) |
694 { | 1569 { |
695 obstack_1grow (pp->buffer->obstack, '\0'); | 1570 return output_buffer_formatted_text (pp_buffer (pp)); |
696 return pp_formatted_text_data (pp); | |
697 } | 1571 } |
698 | 1572 |
699 /* Return a pointer to the last character emitted in PRETTY-PRINTER's | 1573 /* Return a pointer to the last character emitted in PRETTY-PRINTER's |
700 output area. A NULL pointer means no character available. */ | 1574 output area. A NULL pointer means no character available. */ |
701 const char * | 1575 const char * |
702 pp_base_last_position_in_text (const pretty_printer *pp) | 1576 pp_last_position_in_text (const pretty_printer *pp) |
703 { | 1577 { |
704 const char *p = NULL; | 1578 return output_buffer_last_position_in_text (pp_buffer (pp)); |
705 struct obstack *text = pp->buffer->obstack; | |
706 | |
707 if (obstack_base (text) != obstack_next_free (text)) | |
708 p = ((const char *) obstack_next_free (text)) - 1; | |
709 return p; | |
710 } | 1579 } |
711 | 1580 |
712 /* Return the amount of characters PRETTY-PRINTER can accept to | 1581 /* Return the amount of characters PRETTY-PRINTER can accept to |
713 make a full line. Meaningful only in line-wrapping mode. */ | 1582 make a full line. Meaningful only in line-wrapping mode. */ |
714 int | 1583 int |
715 pp_base_remaining_character_count_for_line (pretty_printer *pp) | 1584 pp_remaining_character_count_for_line (pretty_printer *pp) |
716 { | 1585 { |
717 return pp->maximum_length - pp->buffer->line_length; | 1586 return pp->maximum_length - pp_buffer (pp)->line_length; |
718 } | 1587 } |
719 | 1588 |
720 | 1589 |
721 /* Format a message into BUFFER a la printf. */ | 1590 /* Format a message into BUFFER a la printf. */ |
722 void | 1591 void |
727 | 1596 |
728 va_start (ap, msg); | 1597 va_start (ap, msg); |
729 text.err_no = errno; | 1598 text.err_no = errno; |
730 text.args_ptr = ≈ | 1599 text.args_ptr = ≈ |
731 text.format_spec = msg; | 1600 text.format_spec = msg; |
732 text.locus = NULL; | |
733 pp_format (pp, &text); | 1601 pp_format (pp, &text); |
734 pp_output_formatted_text (pp); | 1602 pp_output_formatted_text (pp); |
735 va_end (ap); | 1603 va_end (ap); |
736 } | 1604 } |
737 | 1605 |
745 | 1613 |
746 va_start (ap, msg); | 1614 va_start (ap, msg); |
747 text.err_no = errno; | 1615 text.err_no = errno; |
748 text.args_ptr = ≈ | 1616 text.args_ptr = ≈ |
749 text.format_spec = msg; | 1617 text.format_spec = msg; |
750 text.locus = NULL; | |
751 pp_format_verbatim (pp, &text); | 1618 pp_format_verbatim (pp, &text); |
752 va_end (ap); | 1619 va_end (ap); |
753 } | 1620 } |
754 | 1621 |
755 | 1622 |
756 | 1623 |
757 /* Have PRETTY-PRINTER start a new line. */ | 1624 /* Have PRETTY-PRINTER start a new line. */ |
758 void | 1625 void |
759 pp_base_newline (pretty_printer *pp) | 1626 pp_newline (pretty_printer *pp) |
760 { | 1627 { |
761 obstack_1grow (pp->buffer->obstack, '\n'); | 1628 obstack_1grow (pp_buffer (pp)->obstack, '\n'); |
762 pp->buffer->line_length = 0; | 1629 pp_needs_newline (pp) = false; |
1630 pp_buffer (pp)->line_length = 0; | |
763 } | 1631 } |
764 | 1632 |
765 /* Have PRETTY-PRINTER add a CHARACTER. */ | 1633 /* Have PRETTY-PRINTER add a CHARACTER. */ |
766 void | 1634 void |
767 pp_base_character (pretty_printer *pp, int c) | 1635 pp_character (pretty_printer *pp, int c) |
768 { | 1636 { |
769 if (pp_is_wrapping_line (pp) | 1637 if (pp_is_wrapping_line (pp) |
770 && pp_remaining_character_count_for_line (pp) <= 0) | 1638 && pp_remaining_character_count_for_line (pp) <= 0) |
771 { | 1639 { |
772 pp_newline (pp); | 1640 pp_newline (pp); |
773 if (ISSPACE (c)) | 1641 if (ISSPACE (c)) |
774 return; | 1642 return; |
775 } | 1643 } |
776 obstack_1grow (pp->buffer->obstack, c); | 1644 obstack_1grow (pp_buffer (pp)->obstack, c); |
777 ++pp->buffer->line_length; | 1645 ++pp_buffer (pp)->line_length; |
778 } | 1646 } |
779 | 1647 |
780 /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may | 1648 /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may |
781 be line-wrapped if in appropriate mode. */ | 1649 be line-wrapped if in appropriate mode. */ |
782 void | 1650 void |
783 pp_base_string (pretty_printer *pp, const char *str) | 1651 pp_string (pretty_printer *pp, const char *str) |
784 { | 1652 { |
785 pp_maybe_wrap_text (pp, str, str + (str ? strlen (str) : 0)); | 1653 gcc_checking_assert (str); |
1654 pp_maybe_wrap_text (pp, str, str + strlen (str)); | |
1655 } | |
1656 | |
1657 /* Append the leading N characters of STRING to the output area of | |
1658 PRETTY-PRINTER, quoting in hexadecimal non-printable characters. | |
1659 Setting N = -1 is as if N were set to strlen (STRING). The STRING | |
1660 may be line-wrapped if in appropriate mode. */ | |
1661 static void | |
1662 pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */) | |
1663 { | |
1664 gcc_checking_assert (str); | |
1665 | |
1666 const char *last = str; | |
1667 const char *ps; | |
1668 | |
1669 /* Compute the length if not specified. */ | |
1670 if (n == (size_t) -1) | |
1671 n = strlen (str); | |
1672 | |
1673 for (ps = str; n; ++ps, --n) | |
1674 { | |
1675 if (ISPRINT (*ps)) | |
1676 continue; | |
1677 | |
1678 if (last < ps) | |
1679 pp_maybe_wrap_text (pp, last, ps - 1); | |
1680 | |
1681 /* Append the hexadecimal value of the character. Allocate a buffer | |
1682 that's large enough for a 32-bit char plus the hex prefix. */ | |
1683 char buf [11]; | |
1684 int n = sprintf (buf, "\\x%02x", (unsigned char)*ps); | |
1685 pp_maybe_wrap_text (pp, buf, buf + n); | |
1686 last = ps + 1; | |
1687 } | |
1688 | |
1689 pp_maybe_wrap_text (pp, last, ps); | |
786 } | 1690 } |
787 | 1691 |
788 /* Maybe print out a whitespace if needed. */ | 1692 /* Maybe print out a whitespace if needed. */ |
789 | 1693 |
790 void | 1694 void |
791 pp_base_maybe_space (pretty_printer *pp) | 1695 pp_maybe_space (pretty_printer *pp) |
792 { | 1696 { |
793 if (pp_base (pp)->padding != pp_none) | 1697 if (pp->padding != pp_none) |
794 { | 1698 { |
795 pp_space (pp); | 1699 pp_space (pp); |
796 pp_base (pp)->padding = pp_none; | 1700 pp->padding = pp_none; |
797 } | 1701 } |
798 } | 1702 } |
1703 | |
1704 // Add a newline to the pretty printer PP and flush formatted text. | |
1705 | |
1706 void | |
1707 pp_newline_and_flush (pretty_printer *pp) | |
1708 { | |
1709 pp_newline (pp); | |
1710 pp_flush (pp); | |
1711 pp_needs_newline (pp) = false; | |
1712 } | |
1713 | |
1714 // Add a newline to the pretty printer PP, followed by indentation. | |
1715 | |
1716 void | |
1717 pp_newline_and_indent (pretty_printer *pp, int n) | |
1718 { | |
1719 pp_indentation (pp) += n; | |
1720 pp_newline (pp); | |
1721 pp_indent (pp); | |
1722 pp_needs_newline (pp) = false; | |
1723 } | |
1724 | |
1725 // Add separator C, followed by a single whitespace. | |
1726 | |
1727 void | |
1728 pp_separate_with (pretty_printer *pp, char c) | |
1729 { | |
1730 pp_character (pp, c); | |
1731 pp_space (pp); | |
1732 } | |
1733 | |
799 | 1734 |
800 /* The string starting at P has LEN (at least 1) bytes left; if they | 1735 /* The string starting at P has LEN (at least 1) bytes left; if they |
801 start with a valid UTF-8 sequence, return the length of that | 1736 start with a valid UTF-8 sequence, return the length of that |
802 sequence and set *VALUE to the value of that sequence, and | 1737 sequence and set *VALUE to the value of that sequence, and |
803 otherwise return 0 and set *VALUE to (unsigned int) -1. */ | 1738 otherwise return 0 and set *VALUE to (unsigned int) -1. */ |
1017 } | 1952 } |
1018 *p = 0; | 1953 *p = 0; |
1019 return ret; | 1954 return ret; |
1020 } | 1955 } |
1021 } | 1956 } |
1957 | |
1958 #if CHECKING_P | |
1959 | |
1960 namespace selftest { | |
1961 | |
1962 /* Smoketest for pretty_printer. */ | |
1963 | |
1964 static void | |
1965 test_basic_printing () | |
1966 { | |
1967 pretty_printer pp; | |
1968 pp_string (&pp, "hello"); | |
1969 pp_space (&pp); | |
1970 pp_string (&pp, "world"); | |
1971 | |
1972 ASSERT_STREQ ("hello world", pp_formatted_text (&pp)); | |
1973 } | |
1974 | |
1975 /* Helper function for testing pp_format. | |
1976 Verify that pp_format (FMT, ...) followed by pp_output_formatted_text | |
1977 prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */ | |
1978 | |
1979 static void | |
1980 assert_pp_format_va (const location &loc, const char *expected, | |
1981 bool show_color, const char *fmt, va_list *ap) | |
1982 { | |
1983 pretty_printer pp; | |
1984 text_info ti; | |
1985 rich_location rich_loc (line_table, UNKNOWN_LOCATION); | |
1986 | |
1987 ti.format_spec = fmt; | |
1988 ti.args_ptr = ap; | |
1989 ti.err_no = 0; | |
1990 ti.x_data = NULL; | |
1991 ti.m_richloc = &rich_loc; | |
1992 | |
1993 pp_show_color (&pp) = show_color; | |
1994 pp_format (&pp, &ti); | |
1995 pp_output_formatted_text (&pp); | |
1996 ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp)); | |
1997 } | |
1998 | |
1999 /* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text | |
2000 prints EXPECTED, with show_color disabled. */ | |
2001 | |
2002 static void | |
2003 assert_pp_format (const location &loc, const char *expected, | |
2004 const char *fmt, ...) | |
2005 { | |
2006 va_list ap; | |
2007 | |
2008 va_start (ap, fmt); | |
2009 assert_pp_format_va (loc, expected, false, fmt, &ap); | |
2010 va_end (ap); | |
2011 } | |
2012 | |
2013 /* As above, but with colorization enabled. */ | |
2014 | |
2015 static void | |
2016 assert_pp_format_colored (const location &loc, const char *expected, | |
2017 const char *fmt, ...) | |
2018 { | |
2019 /* The tests of colorization assume the default color scheme. | |
2020 If GCC_COLORS is set, then the colors have potentially been | |
2021 overridden; skip the test. */ | |
2022 if (getenv ("GCC_COLORS")) | |
2023 return; | |
2024 | |
2025 va_list ap; | |
2026 | |
2027 va_start (ap, fmt); | |
2028 assert_pp_format_va (loc, expected, true, fmt, &ap); | |
2029 va_end (ap); | |
2030 } | |
2031 | |
2032 /* Helper function for calling testing pp_format, | |
2033 by calling assert_pp_format with various numbers of arguments. | |
2034 These exist mostly to avoid having to write SELFTEST_LOCATION | |
2035 throughout test_pp_format. */ | |
2036 | |
2037 #define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \ | |
2038 SELFTEST_BEGIN_STMT \ | |
2039 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \ | |
2040 (ARG1)); \ | |
2041 SELFTEST_END_STMT | |
2042 | |
2043 #define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \ | |
2044 SELFTEST_BEGIN_STMT \ | |
2045 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \ | |
2046 (ARG1), (ARG2)); \ | |
2047 SELFTEST_END_STMT | |
2048 | |
2049 #define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \ | |
2050 SELFTEST_BEGIN_STMT \ | |
2051 assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \ | |
2052 (ARG1), (ARG2), (ARG3)); \ | |
2053 SELFTEST_END_STMT | |
2054 | |
2055 /* Verify that pp_format works, for various format codes. */ | |
2056 | |
2057 static void | |
2058 test_pp_format () | |
2059 { | |
2060 /* Avoid introducing locale-specific differences in the results | |
2061 by hardcoding open_quote and close_quote. */ | |
2062 const char *old_open_quote = open_quote; | |
2063 const char *old_close_quote = close_quote; | |
2064 open_quote = "`"; | |
2065 close_quote = "'"; | |
2066 | |
2067 /* Verify that plain text is passed through unchanged. */ | |
2068 assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted"); | |
2069 | |
2070 /* Verify various individual format codes, in the order listed in the | |
2071 comment for pp_format above. For each code, we append a second | |
2072 argument with a known bit pattern (0x12345678), to ensure that we | |
2073 are consuming arguments correctly. */ | |
2074 ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678); | |
2075 ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678); | |
2076 ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678); | |
2077 ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678); | |
2078 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678); | |
2079 ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678); | |
2080 ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678); | |
2081 ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678); | |
2082 ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678); | |
2083 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe, | |
2084 0x12345678); | |
2085 ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678); | |
2086 ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678); | |
2087 ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678); | |
2088 ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678); | |
2089 ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe, | |
2090 0x12345678); | |
2091 ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678); | |
2092 ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678); | |
2093 ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10, | |
2094 0x12345678); | |
2095 ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678); | |
2096 ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe, | |
2097 0x12345678); | |
2098 ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678); | |
2099 ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world", | |
2100 0x12345678); | |
2101 | |
2102 /* Not nul-terminated. */ | |
2103 char arr[5] = { '1', '2', '3', '4', '5' }; | |
2104 ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678); | |
2105 ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678); | |
2106 ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678); | |
2107 | |
2108 /* We can't test for %p; the pointer is printed in an implementation-defined | |
2109 manner. */ | |
2110 ASSERT_PP_FORMAT_2 ("normal colored normal 12345678", | |
2111 "normal %rcolored%R normal %x", | |
2112 "error", 0x12345678); | |
2113 assert_pp_format_colored | |
2114 (SELFTEST_LOCATION, | |
2115 "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678", | |
2116 "normal %rcolored%R normal %x", "error", 0x12345678); | |
2117 /* TODO: | |
2118 %m: strerror(text->err_no) - does not consume a value from args_ptr. */ | |
2119 ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678); | |
2120 ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678); | |
2121 ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678); | |
2122 ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678); | |
2123 ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678); | |
2124 ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678); | |
2125 | |
2126 /* Verify flag 'q'. */ | |
2127 ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678); | |
2128 assert_pp_format_colored (SELFTEST_LOCATION, | |
2129 "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x", | |
2130 "foo", 0x12345678); | |
2131 | |
2132 /* Verify %Z. */ | |
2133 int v[] = { 1, 2, 3 }; | |
2134 ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678); | |
2135 | |
2136 int v2[] = { 0 }; | |
2137 ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678); | |
2138 | |
2139 /* Verify that combinations work, along with unformatted text. */ | |
2140 assert_pp_format (SELFTEST_LOCATION, | |
2141 "the quick brown fox jumps over the lazy dog", | |
2142 "the %s %s %s jumps over the %s %s", | |
2143 "quick", "brown", "fox", "lazy", "dog"); | |
2144 assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7); | |
2145 assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10", | |
2146 "problem with %qs at line %i", "bar", 10); | |
2147 | |
2148 /* Restore old values of open_quote and close_quote. */ | |
2149 open_quote = old_open_quote; | |
2150 close_quote = old_close_quote; | |
2151 } | |
2152 | |
2153 /* Run all of the selftests within this file. */ | |
2154 | |
2155 void | |
2156 pretty_print_c_tests () | |
2157 { | |
2158 test_basic_printing (); | |
2159 test_pp_format (); | |
2160 } | |
2161 | |
2162 } // namespace selftest | |
2163 | |
2164 #endif /* CHECKING_P */ |