1/* Output generating routines for GDB. 2 3 Copyright (C) 1999-2023 Free Software Foundation, Inc. 4 5 Contributed by Cygnus Solutions. 6 Written by Fernando Nasser for Cygnus. 7 8 This file is part of GDB. 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 3 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 22 23#include "defs.h" 24#include "expression.h" /* For language.h */ 25#include "language.h" 26#include "ui-out.h" 27#include "gdbsupport/format.h" 28#include "cli/cli-style.h" 29#include "diagnostics.h" 30 31#include <vector> 32#include <memory> 33#include <string> 34 35namespace { 36 37/* A header of a ui_out_table. */ 38 39class ui_out_hdr 40{ 41 public: 42 43 explicit ui_out_hdr (int number, int min_width, ui_align alignment, 44 const std::string &name, const std::string &header) 45 : m_number (number), 46 m_min_width (min_width), 47 m_alignment (alignment), 48 m_name (name), 49 m_header (header) 50 { 51 } 52 53 int number () const 54 { 55 return m_number; 56 } 57 58 int min_width () const 59 { 60 return m_min_width; 61 } 62 63 ui_align alignment () const 64 { 65 return m_alignment; 66 } 67 68 const std::string &header () const 69 { 70 return m_header; 71 } 72 73 const std::string &name () const 74 { 75 return m_name; 76 } 77 78 private: 79 80 /* The number of the table column this header represents, 1-based. */ 81 int m_number; 82 83 /* Minimal column width in characters. May or may not be applicable, 84 depending on the actual implementation of ui_out. */ 85 int m_min_width; 86 87 /* Alignment of the content in the column. May or may not be applicable, 88 depending on the actual implementation of ui_out. */ 89 ui_align m_alignment; 90 91 /* Internal column name, used to internally refer to the column. */ 92 std::string m_name; 93 94 /* Printed header text of the column. */ 95 std::string m_header; 96}; 97 98} // namespace 99 100/* A level of nesting (either a list or a tuple) in a ui_out output. */ 101 102class ui_out_level 103{ 104 public: 105 106 explicit ui_out_level (ui_out_type type) 107 : m_type (type), 108 m_field_count (0) 109 { 110 } 111 112 ui_out_type type () const 113 { 114 return m_type; 115 } 116 117 int field_count () const 118 { 119 return m_field_count; 120 } 121 122 void inc_field_count () 123 { 124 m_field_count++; 125 } 126 127 private: 128 129 /* The type of this level. */ 130 ui_out_type m_type; 131 132 /* Count each field; the first element is for non-list fields. */ 133 int m_field_count; 134}; 135 136/* Tables are special. Maintain a separate structure that tracks 137 their state. At present an output can only contain a single table 138 but that restriction might eventually be lifted. */ 139 140class ui_out_table 141{ 142 public: 143 144 /* States (steps) of a table generation. */ 145 146 enum class state 147 { 148 /* We are generating the table headers. */ 149 HEADERS, 150 151 /* We are generating the table body. */ 152 BODY, 153 }; 154 155 explicit ui_out_table (int entry_level, int nr_cols, const std::string &id) 156 : m_state (state::HEADERS), 157 m_entry_level (entry_level), 158 m_nr_cols (nr_cols), 159 m_id (id) 160 { 161 } 162 163 /* Start building the body of the table. */ 164 165 void start_body (); 166 167 /* Add a new header to the table. */ 168 169 void append_header (int width, ui_align alignment, 170 const std::string &col_name, const std::string &col_hdr); 171 172 void start_row (); 173 174 /* Extract the format information for the next header and advance 175 the header iterator. Return false if there was no next header. */ 176 177 bool get_next_header (int *colno, int *width, ui_align *alignment, 178 const char **col_hdr); 179 180 bool query_field (int colno, int *width, int *alignment, 181 const char **col_name) const; 182 183 state current_state () const; 184 185 int entry_level () const; 186 187 private: 188 189 state m_state; 190 191 /* The level at which each entry of the table is to be found. A row 192 (a tuple) is made up of entries. Consequently ENTRY_LEVEL is one 193 above that of the table. */ 194 int m_entry_level; 195 196 /* Number of table columns (as specified in the table_begin call). */ 197 int m_nr_cols; 198 199 /* String identifying the table (as specified in the table_begin 200 call). */ 201 std::string m_id; 202 203 /* Pointers to the column headers. */ 204 std::vector<std::unique_ptr<ui_out_hdr>> m_headers; 205 206 /* Iterator over the headers vector, used when printing successive fields. */ 207 std::vector<std::unique_ptr<ui_out_hdr>>::const_iterator m_headers_iterator; 208}; 209 210/* See ui-out.h. */ 211 212void ui_out_table::start_body () 213{ 214 if (m_state != state::HEADERS) 215 internal_error (_("extra table_body call not allowed; there must be only " 216 "one table_body after a table_begin and before a " 217 "table_end.")); 218 219 /* Check if the number of defined headers matches the number of expected 220 columns. */ 221 if (m_headers.size () != m_nr_cols) 222 internal_error (_("number of headers differ from number of table " 223 "columns.")); 224 225 m_state = state::BODY; 226 m_headers_iterator = m_headers.begin (); 227} 228 229/* See ui-out.h. */ 230 231void ui_out_table::append_header (int width, ui_align alignment, 232 const std::string &col_name, 233 const std::string &col_hdr) 234{ 235 if (m_state != state::HEADERS) 236 internal_error (_("table header must be specified after table_begin and " 237 "before table_body.")); 238 239 std::unique_ptr<ui_out_hdr> header (new ui_out_hdr (m_headers.size () + 1, 240 width, alignment, 241 col_name, col_hdr)); 242 243 m_headers.push_back (std::move (header)); 244} 245 246/* See ui-out.h. */ 247 248void ui_out_table::start_row () 249{ 250 m_headers_iterator = m_headers.begin (); 251} 252 253/* See ui-out.h. */ 254 255bool ui_out_table::get_next_header (int *colno, int *width, ui_align *alignment, 256 const char **col_hdr) 257{ 258 /* There may be no headers at all or we may have used all columns. */ 259 if (m_headers_iterator == m_headers.end ()) 260 return false; 261 262 ui_out_hdr *hdr = m_headers_iterator->get (); 263 264 *colno = hdr->number (); 265 *width = hdr->min_width (); 266 *alignment = hdr->alignment (); 267 *col_hdr = hdr->header ().c_str (); 268 269 /* Advance the header pointer to the next entry. */ 270 m_headers_iterator++; 271 272 return true; 273} 274 275/* See ui-out.h. */ 276 277bool ui_out_table::query_field (int colno, int *width, int *alignment, 278 const char **col_name) const 279{ 280 /* Column numbers are 1-based, so convert to 0-based index. */ 281 int index = colno - 1; 282 283 if (index >= 0 && index < m_headers.size ()) 284 { 285 ui_out_hdr *hdr = m_headers[index].get (); 286 287 gdb_assert (colno == hdr->number ()); 288 289 *width = hdr->min_width (); 290 *alignment = hdr->alignment (); 291 *col_name = hdr->name ().c_str (); 292 293 return true; 294 } 295 else 296 return false; 297} 298 299/* See ui-out.h. */ 300 301ui_out_table::state ui_out_table::current_state () const 302{ 303 return m_state; 304} 305 306/* See ui-out.h. */ 307 308int ui_out_table::entry_level () const 309{ 310 return m_entry_level; 311} 312 313int 314ui_out::level () const 315{ 316 return m_levels.size (); 317} 318 319/* The current (inner most) level. */ 320 321ui_out_level * 322ui_out::current_level () const 323{ 324 return m_levels.back ().get (); 325} 326 327/* Create a new level, of TYPE. */ 328void 329ui_out::push_level (ui_out_type type) 330{ 331 std::unique_ptr<ui_out_level> level (new ui_out_level (type)); 332 333 m_levels.push_back (std::move (level)); 334} 335 336/* Discard the current level. TYPE is the type of the level being 337 discarded. */ 338void 339ui_out::pop_level (ui_out_type type) 340{ 341 /* We had better not underflow the buffer. */ 342 gdb_assert (m_levels.size () > 0); 343 gdb_assert (current_level ()->type () == type); 344 345 m_levels.pop_back (); 346} 347 348/* Mark beginning of a table. */ 349 350void 351ui_out::table_begin (int nr_cols, int nr_rows, const std::string &tblid) 352{ 353 if (m_table_up != nullptr) 354 internal_error (_("tables cannot be nested; table_begin found before \ 355previous table_end.")); 356 357 m_table_up.reset (new ui_out_table (level () + 1, nr_cols, tblid)); 358 359 do_table_begin (nr_cols, nr_rows, tblid.c_str ()); 360} 361 362void 363ui_out::table_header (int width, ui_align alignment, 364 const std::string &col_name, const std::string &col_hdr) 365{ 366 if (m_table_up == nullptr) 367 internal_error (_("table_header outside a table is not valid; it must be \ 368after a table_begin and before a table_body.")); 369 370 m_table_up->append_header (width, alignment, col_name, col_hdr); 371 372 do_table_header (width, alignment, col_name, col_hdr); 373} 374 375void 376ui_out::table_body () 377{ 378 if (m_table_up == nullptr) 379 internal_error (_("table_body outside a table is not valid; it must be " 380 "after a table_begin and before a table_end.")); 381 382 m_table_up->start_body (); 383 384 do_table_body (); 385} 386 387void 388ui_out::table_end () 389{ 390 if (m_table_up == nullptr) 391 internal_error (_("misplaced table_end or missing table_begin.")); 392 393 do_table_end (); 394 395 m_table_up = nullptr; 396} 397 398void 399ui_out::begin (ui_out_type type, const char *id) 400{ 401 /* Be careful to verify the ``field'' before the new tuple/list is 402 pushed onto the stack. That way the containing list/table/row is 403 verified and not the newly created tuple/list. This verification 404 is needed (at least) for the case where a table row entry 405 contains either a tuple/list. For that case bookkeeping such as 406 updating the column count or advancing to the next heading still 407 needs to be performed. */ 408 { 409 int fldno; 410 int width; 411 ui_align align; 412 413 verify_field (&fldno, &width, &align); 414 } 415 416 push_level (type); 417 418 /* If the push puts us at the same level as a table row entry, we've 419 got a new table row. Put the header pointer back to the start. */ 420 if (m_table_up != nullptr 421 && m_table_up->current_state () == ui_out_table::state::BODY 422 && m_table_up->entry_level () == level ()) 423 m_table_up->start_row (); 424 425 do_begin (type, id); 426} 427 428void 429ui_out::end (ui_out_type type) 430{ 431 pop_level (type); 432 433 do_end (type); 434} 435 436void 437ui_out::field_signed (const char *fldname, LONGEST value) 438{ 439 int fldno; 440 int width; 441 ui_align align; 442 443 verify_field (&fldno, &width, &align); 444 445 do_field_signed (fldno, width, align, fldname, value); 446} 447 448void 449ui_out::field_fmt_signed (int input_width, ui_align input_align, 450 const char *fldname, LONGEST value) 451{ 452 int fldno; 453 int width; 454 ui_align align; 455 456 verify_field (&fldno, &width, &align); 457 458 do_field_signed (fldno, input_width, input_align, fldname, value); 459} 460 461/* See ui-out.h. */ 462 463void 464ui_out::field_unsigned (const char *fldname, ULONGEST value) 465{ 466 int fldno; 467 int width; 468 ui_align align; 469 470 verify_field (&fldno, &width, &align); 471 472 do_field_unsigned (fldno, width, align, fldname, value); 473} 474 475/* Documented in ui-out.h. */ 476 477void 478ui_out::field_core_addr (const char *fldname, struct gdbarch *gdbarch, 479 CORE_ADDR address) 480{ 481 field_string (fldname, print_core_address (gdbarch, address), 482 address_style.style ()); 483} 484 485void 486ui_out::field_stream (const char *fldname, string_file &stream, 487 const ui_file_style &style) 488{ 489 if (!stream.empty ()) 490 field_string (fldname, stream.c_str (), style); 491 else 492 field_skip (fldname); 493 stream.clear (); 494} 495 496/* Used to omit a field. */ 497 498void 499ui_out::field_skip (const char *fldname) 500{ 501 int fldno; 502 int width; 503 ui_align align; 504 505 verify_field (&fldno, &width, &align); 506 507 do_field_skip (fldno, width, align, fldname); 508} 509 510void 511ui_out::field_string (const char *fldname, const char *string, 512 const ui_file_style &style) 513{ 514 int fldno; 515 int width; 516 ui_align align; 517 518 verify_field (&fldno, &width, &align); 519 520 do_field_string (fldno, width, align, fldname, string, style); 521} 522 523/* VARARGS */ 524void 525ui_out::field_fmt (const char *fldname, const char *format, ...) 526{ 527 va_list args; 528 int fldno; 529 int width; 530 ui_align align; 531 532 verify_field (&fldno, &width, &align); 533 534 va_start (args, format); 535 536 do_field_fmt (fldno, width, align, fldname, ui_file_style (), format, args); 537 538 va_end (args); 539} 540 541void 542ui_out::field_fmt (const char *fldname, const ui_file_style &style, 543 const char *format, ...) 544{ 545 va_list args; 546 int fldno; 547 int width; 548 ui_align align; 549 550 verify_field (&fldno, &width, &align); 551 552 va_start (args, format); 553 554 do_field_fmt (fldno, width, align, fldname, style, format, args); 555 556 va_end (args); 557} 558 559void 560ui_out::spaces (int numspaces) 561{ 562 do_spaces (numspaces); 563} 564 565void 566ui_out::text (const char *string) 567{ 568 do_text (string); 569} 570 571void 572ui_out::call_do_message (const ui_file_style &style, const char *format, 573 ...) 574{ 575 va_list args; 576 577 va_start (args, format); 578 579 /* Since call_do_message is only used as a helper of vmessage, silence the 580 warning here once instead of at all call sites in vmessage, if we were 581 to put a "format" attribute on call_do_message. */ 582 DIAGNOSTIC_PUSH 583 DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL 584 do_message (style, format, args); 585 DIAGNOSTIC_POP 586 587 va_end (args); 588} 589 590void 591ui_out::vmessage (const ui_file_style &in_style, const char *format, 592 va_list args) 593{ 594 format_pieces fpieces (&format, true); 595 596 ui_file_style style = in_style; 597 598 for (auto &&piece : fpieces) 599 { 600 const char *current_substring = piece.string; 601 602 gdb_assert (piece.n_int_args >= 0 && piece.n_int_args <= 2); 603 int intvals[2] = { 0, 0 }; 604 for (int i = 0; i < piece.n_int_args; ++i) 605 intvals[i] = va_arg (args, int); 606 607 /* The only ones we support for now. */ 608 gdb_assert (piece.n_int_args == 0 609 || piece.argclass == string_arg 610 || piece.argclass == int_arg 611 || piece.argclass == long_arg); 612 613 switch (piece.argclass) 614 { 615 case string_arg: 616 { 617 const char *str = va_arg (args, const char *); 618 switch (piece.n_int_args) 619 { 620 case 0: 621 call_do_message (style, current_substring, str); 622 break; 623 case 1: 624 call_do_message (style, current_substring, intvals[0], str); 625 break; 626 case 2: 627 call_do_message (style, current_substring, 628 intvals[0], intvals[1], str); 629 break; 630 } 631 } 632 break; 633 case wide_string_arg: 634 gdb_assert_not_reached ("wide_string_arg not supported in vmessage"); 635 break; 636 case wide_char_arg: 637 gdb_assert_not_reached ("wide_char_arg not supported in vmessage"); 638 break; 639 case long_long_arg: 640 call_do_message (style, current_substring, va_arg (args, long long)); 641 break; 642 case int_arg: 643 { 644 int val = va_arg (args, int); 645 switch (piece.n_int_args) 646 { 647 case 0: 648 call_do_message (style, current_substring, val); 649 break; 650 case 1: 651 call_do_message (style, current_substring, intvals[0], val); 652 break; 653 case 2: 654 call_do_message (style, current_substring, 655 intvals[0], intvals[1], val); 656 break; 657 } 658 } 659 break; 660 case long_arg: 661 { 662 long val = va_arg (args, long); 663 switch (piece.n_int_args) 664 { 665 case 0: 666 call_do_message (style, current_substring, val); 667 break; 668 case 1: 669 call_do_message (style, current_substring, intvals[0], val); 670 break; 671 case 2: 672 call_do_message (style, current_substring, 673 intvals[0], intvals[1], val); 674 break; 675 } 676 } 677 break; 678 case size_t_arg: 679 { 680 size_t val = va_arg (args, size_t); 681 switch (piece.n_int_args) 682 { 683 case 0: 684 call_do_message (style, current_substring, val); 685 break; 686 case 1: 687 call_do_message (style, current_substring, intvals[0], val); 688 break; 689 case 2: 690 call_do_message (style, current_substring, 691 intvals[0], intvals[1], val); 692 break; 693 } 694 } 695 break; 696 case double_arg: 697 call_do_message (style, current_substring, va_arg (args, double)); 698 break; 699 case long_double_arg: 700 gdb_assert_not_reached ("long_double_arg not supported in vmessage"); 701 break; 702 case dec32float_arg: 703 gdb_assert_not_reached ("dec32float_arg not supported in vmessage"); 704 break; 705 case dec64float_arg: 706 gdb_assert_not_reached ("dec64float_arg not supported in vmessage"); 707 break; 708 case dec128float_arg: 709 gdb_assert_not_reached ("dec128float_arg not supported in vmessage"); 710 break; 711 case ptr_arg: 712 switch (current_substring[2]) 713 { 714 case 'F': 715 { 716 gdb_assert (!test_flags (disallow_ui_out_field)); 717 base_field_s *bf = va_arg (args, base_field_s *); 718 switch (bf->kind) 719 { 720 case field_kind::FIELD_SIGNED: 721 { 722 auto *f = (signed_field_s *) bf; 723 field_signed (f->name, f->val); 724 } 725 break; 726 case field_kind::FIELD_STRING: 727 { 728 auto *f = (string_field_s *) bf; 729 field_string (f->name, f->str); 730 } 731 break; 732 } 733 } 734 break; 735 case 's': 736 { 737 styled_string_s *ss = va_arg (args, styled_string_s *); 738 call_do_message (ss->style, "%s", ss->str); 739 } 740 break; 741 case '[': 742 style = *va_arg (args, const ui_file_style *); 743 break; 744 case ']': 745 { 746 void *arg = va_arg (args, void *); 747 gdb_assert (arg == nullptr); 748 749 style = {}; 750 } 751 break; 752 default: 753 call_do_message (style, current_substring, va_arg (args, void *)); 754 break; 755 } 756 break; 757 case literal_piece: 758 /* Print a portion of the format string that has no 759 directives. Note that this will not include any ordinary 760 %-specs, but it might include "%%". That is why we use 761 call_do_message here. Also, we pass a dummy argument 762 because some platforms have modified GCC to include 763 -Wformat-security by default, which will warn here if 764 there is no argument. */ 765 call_do_message (style, current_substring, 0); 766 break; 767 default: 768 internal_error (_("failed internal consistency check")); 769 } 770 } 771} 772 773void 774ui_out::message (const char *format, ...) 775{ 776 va_list args; 777 va_start (args, format); 778 779 vmessage (ui_file_style (), format, args); 780 781 va_end (args); 782} 783 784void 785ui_out::wrap_hint (int indent) 786{ 787 do_wrap_hint (indent); 788} 789 790void 791ui_out::flush () 792{ 793 do_flush (); 794} 795 796void 797ui_out::redirect (ui_file *outstream) 798{ 799 do_redirect (outstream); 800} 801 802/* Test the flags against the mask given. */ 803ui_out_flags 804ui_out::test_flags (ui_out_flags mask) 805{ 806 return m_flags & mask; 807} 808 809bool 810ui_out::is_mi_like_p () const 811{ 812 return do_is_mi_like_p (); 813} 814 815/* Verify that the field/tuple/list is correctly positioned. Return 816 the field number and corresponding alignment (if 817 available/applicable). */ 818 819void 820ui_out::verify_field (int *fldno, int *width, ui_align *align) 821{ 822 ui_out_level *current = current_level (); 823 const char *text; 824 825 if (m_table_up != nullptr 826 && m_table_up->current_state () != ui_out_table::state::BODY) 827 { 828 internal_error (_("table_body missing; table fields must be \ 829specified after table_body and inside a list.")); 830 } 831 832 current->inc_field_count (); 833 834 if (m_table_up != nullptr 835 && m_table_up->current_state () == ui_out_table::state::BODY 836 && m_table_up->entry_level () == level () 837 && m_table_up->get_next_header (fldno, width, align, &text)) 838 { 839 if (*fldno != current->field_count ()) 840 internal_error (_("ui-out internal error in handling headers.")); 841 } 842 else 843 { 844 *width = 0; 845 *align = ui_noalign; 846 *fldno = current->field_count (); 847 } 848} 849 850/* Access table field parameters. */ 851 852bool 853ui_out::query_table_field (int colno, int *width, int *alignment, 854 const char **col_name) 855{ 856 if (m_table_up == nullptr) 857 return false; 858 859 return m_table_up->query_field (colno, width, alignment, col_name); 860} 861 862/* The constructor. */ 863 864ui_out::ui_out (ui_out_flags flags) 865: m_flags (flags) 866{ 867 /* Create the ui-out level #1, the default level. */ 868 push_level (ui_out_type_tuple); 869} 870 871ui_out::~ui_out () 872{ 873} 874