1 /* Output generating routines for GDB. 2 3 Copyright (C) 1999-2015 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 28 /* table header structures */ 29 30 struct ui_out_hdr 31 { 32 int colno; 33 int width; 34 int alignment; 35 char *col_name; 36 char *colhdr; 37 struct ui_out_hdr *next; 38 }; 39 40 /* Maintain a stack so that the info applicable to the inner most list 41 is always available. Stack/nested level 0 is reserved for the 42 top-level result. */ 43 44 enum { MAX_UI_OUT_LEVELS = 8 }; 45 46 struct ui_out_level 47 { 48 /* Count each field; the first element is for non-list fields. */ 49 int field_count; 50 /* The type of this level. */ 51 enum ui_out_type type; 52 }; 53 54 /* Define uiout->level vector types and operations. */ 55 typedef struct ui_out_level *ui_out_level_p; 56 DEF_VEC_P (ui_out_level_p); 57 58 /* Tables are special. Maintain a separate structure that tracks 59 their state. At present an output can only contain a single table 60 but that restriction might eventually be lifted. */ 61 62 struct ui_out_table 63 { 64 /* If on, a table is being generated. */ 65 int flag; 66 67 /* If on, the body of a table is being generated. If off, the table 68 header is being generated. */ 69 int body_flag; 70 71 /* The level at which each entry of the table is to be found. A row 72 (a tuple) is made up of entries. Consequently ENTRY_LEVEL is one 73 above that of the table. */ 74 int entry_level; 75 76 /* Number of table columns (as specified in the table_begin call). */ 77 int columns; 78 79 /* String identifying the table (as specified in the table_begin 80 call). */ 81 char *id; 82 83 /* Points to the first table header (if any). */ 84 struct ui_out_hdr *header_first; 85 86 /* Points to the last table header (if any). */ 87 struct ui_out_hdr *header_last; 88 89 /* Points to header of NEXT column to format. */ 90 struct ui_out_hdr *header_next; 91 92 }; 93 94 95 /* The ui_out structure */ 96 /* Any change here requires a corresponding one in the initialization 97 of the default uiout, which is statically initialized. */ 98 99 struct ui_out 100 { 101 int flags; 102 /* Specific implementation of ui-out. */ 103 const struct ui_out_impl *impl; 104 void *data; 105 106 /* Current level. */ 107 int level; 108 109 /* Vector to store and track the ui-out levels. */ 110 VEC (ui_out_level_p) *levels; 111 112 /* A table, if any. At present only a single table is supported. */ 113 struct ui_out_table table; 114 }; 115 116 /* The current (inner most) level. */ 117 static struct ui_out_level * 118 current_level (struct ui_out *uiout) 119 { 120 return VEC_index (ui_out_level_p, uiout->levels, uiout->level); 121 } 122 123 /* Create a new level, of TYPE. Return the new level's index. */ 124 static int 125 push_level (struct ui_out *uiout, 126 enum ui_out_type type, 127 const char *id) 128 { 129 struct ui_out_level *current; 130 131 uiout->level++; 132 current = XNEW (struct ui_out_level); 133 current->field_count = 0; 134 current->type = type; 135 VEC_safe_push (ui_out_level_p, uiout->levels, current); 136 return uiout->level; 137 } 138 139 /* Discard the current level, return the discarded level's index. 140 TYPE is the type of the level being discarded. */ 141 static int 142 pop_level (struct ui_out *uiout, 143 enum ui_out_type type) 144 { 145 struct ui_out_level *current; 146 147 /* We had better not underflow the buffer. */ 148 gdb_assert (uiout->level > 0); 149 gdb_assert (current_level (uiout)->type == type); 150 current = VEC_pop (ui_out_level_p, uiout->levels); 151 xfree (current); 152 uiout->level--; 153 return uiout->level + 1; 154 } 155 156 157 /* These are the default implementation functions. */ 158 159 static void default_table_begin (struct ui_out *uiout, int nbrofcols, 160 int nr_rows, const char *tblid); 161 static void default_table_body (struct ui_out *uiout); 162 static void default_table_end (struct ui_out *uiout); 163 static void default_table_header (struct ui_out *uiout, int width, 164 enum ui_align alig, const char *col_name, 165 const char *colhdr); 166 static void default_begin (struct ui_out *uiout, 167 enum ui_out_type type, 168 int level, const char *id); 169 static void default_end (struct ui_out *uiout, 170 enum ui_out_type type, 171 int level); 172 static void default_field_int (struct ui_out *uiout, int fldno, int width, 173 enum ui_align alig, 174 const char *fldname, 175 int value); 176 static void default_field_skip (struct ui_out *uiout, int fldno, int width, 177 enum ui_align alig, 178 const char *fldname); 179 static void default_field_string (struct ui_out *uiout, int fldno, int width, 180 enum ui_align align, 181 const char *fldname, 182 const char *string); 183 static void default_field_fmt (struct ui_out *uiout, int fldno, 184 int width, enum ui_align align, 185 const char *fldname, 186 const char *format, 187 va_list args) ATTRIBUTE_PRINTF (6, 0); 188 static void default_spaces (struct ui_out *uiout, int numspaces); 189 static void default_text (struct ui_out *uiout, const char *string); 190 static void default_message (struct ui_out *uiout, int verbosity, 191 const char *format, 192 va_list args) ATTRIBUTE_PRINTF (3, 0); 193 static void default_wrap_hint (struct ui_out *uiout, char *identstring); 194 static void default_flush (struct ui_out *uiout); 195 static void default_data_destroy (struct ui_out *uiout); 196 197 /* This is the default ui-out implementation functions vector. */ 198 199 const struct ui_out_impl default_ui_out_impl = 200 { 201 default_table_begin, 202 default_table_body, 203 default_table_end, 204 default_table_header, 205 default_begin, 206 default_end, 207 default_field_int, 208 default_field_skip, 209 default_field_string, 210 default_field_fmt, 211 default_spaces, 212 default_text, 213 default_message, 214 default_wrap_hint, 215 default_flush, 216 NULL, 217 default_data_destroy, 218 0, /* Does not need MI hacks. */ 219 }; 220 221 /* The default ui_out */ 222 223 struct ui_out def_uiout = 224 { 225 0, /* flags */ 226 &default_ui_out_impl, /* impl */ 227 }; 228 229 /* Pointer to current ui_out */ 230 /* FIXME: This should not be a global, but something passed down from main.c 231 or top.c. */ 232 233 struct ui_out *current_uiout = &def_uiout; 234 235 /* These are the interfaces to implementation functions. */ 236 237 static void uo_table_begin (struct ui_out *uiout, int nbrofcols, 238 int nr_rows, const char *tblid); 239 static void uo_table_body (struct ui_out *uiout); 240 static void uo_table_end (struct ui_out *uiout); 241 static void uo_table_header (struct ui_out *uiout, int width, 242 enum ui_align align, const char *col_name, 243 const char *colhdr); 244 static void uo_begin (struct ui_out *uiout, 245 enum ui_out_type type, 246 int level, const char *id); 247 static void uo_end (struct ui_out *uiout, 248 enum ui_out_type type, 249 int level); 250 static void uo_field_int (struct ui_out *uiout, int fldno, int width, 251 enum ui_align align, const char *fldname, int value); 252 static void uo_field_skip (struct ui_out *uiout, int fldno, int width, 253 enum ui_align align, const char *fldname); 254 static void uo_field_fmt (struct ui_out *uiout, int fldno, int width, 255 enum ui_align align, const char *fldname, 256 const char *format, va_list args) 257 ATTRIBUTE_PRINTF (6, 0); 258 static void uo_spaces (struct ui_out *uiout, int numspaces); 259 static void uo_text (struct ui_out *uiout, const char *string); 260 static void uo_message (struct ui_out *uiout, int verbosity, 261 const char *format, va_list args) 262 ATTRIBUTE_PRINTF (3, 0); 263 static void uo_wrap_hint (struct ui_out *uiout, char *identstring); 264 static void uo_flush (struct ui_out *uiout); 265 static int uo_redirect (struct ui_out *uiout, struct ui_file *outstream); 266 static void uo_data_destroy (struct ui_out *uiout); 267 268 /* Prototypes for local functions */ 269 270 extern void _initialize_ui_out (void); 271 static void append_header_to_list (struct ui_out *uiout, int width, 272 int alignment, const char *col_name, 273 const char *colhdr); 274 static int get_next_header (struct ui_out *uiout, int *colno, int *width, 275 int *alignment, char **colhdr); 276 static void clear_header_list (struct ui_out *uiout); 277 static void clear_table (struct ui_out *uiout); 278 static void verify_field (struct ui_out *uiout, int *fldno, int *width, 279 int *align); 280 281 /* exported functions (ui_out API) */ 282 283 /* Mark beginning of a table. */ 284 285 static void 286 ui_out_table_begin (struct ui_out *uiout, int nbrofcols, 287 int nr_rows, 288 const char *tblid) 289 { 290 if (uiout->table.flag) 291 internal_error (__FILE__, __LINE__, 292 _("tables cannot be nested; table_begin found before \ 293 previous table_end.")); 294 295 uiout->table.flag = 1; 296 uiout->table.body_flag = 0; 297 uiout->table.entry_level = uiout->level + 1; 298 uiout->table.columns = nbrofcols; 299 if (tblid != NULL) 300 uiout->table.id = xstrdup (tblid); 301 else 302 uiout->table.id = NULL; 303 clear_header_list (uiout); 304 305 uo_table_begin (uiout, nbrofcols, nr_rows, uiout->table.id); 306 } 307 308 void 309 ui_out_table_body (struct ui_out *uiout) 310 { 311 if (!uiout->table.flag) 312 internal_error (__FILE__, __LINE__, 313 _("table_body outside a table is not valid; it must be \ 314 after a table_begin and before a table_end.")); 315 if (uiout->table.body_flag) 316 internal_error (__FILE__, __LINE__, 317 _("extra table_body call not allowed; there must be \ 318 only one table_body after a table_begin and before a table_end.")); 319 if (uiout->table.header_next->colno != uiout->table.columns) 320 internal_error (__FILE__, __LINE__, 321 _("number of headers differ from number of table \ 322 columns.")); 323 324 uiout->table.body_flag = 1; 325 uiout->table.header_next = uiout->table.header_first; 326 327 uo_table_body (uiout); 328 } 329 330 static void 331 ui_out_table_end (struct ui_out *uiout) 332 { 333 if (!uiout->table.flag) 334 internal_error (__FILE__, __LINE__, 335 _("misplaced table_end or missing table_begin.")); 336 337 uiout->table.entry_level = 0; 338 uiout->table.body_flag = 0; 339 uiout->table.flag = 0; 340 341 uo_table_end (uiout); 342 clear_table (uiout); 343 } 344 345 void 346 ui_out_table_header (struct ui_out *uiout, int width, enum ui_align alignment, 347 const char *col_name, 348 const char *colhdr) 349 { 350 if (!uiout->table.flag || uiout->table.body_flag) 351 internal_error (__FILE__, __LINE__, 352 _("table header must be specified after table_begin \ 353 and before table_body.")); 354 355 append_header_to_list (uiout, width, alignment, col_name, colhdr); 356 357 uo_table_header (uiout, width, alignment, col_name, colhdr); 358 } 359 360 static void 361 do_cleanup_table_end (void *data) 362 { 363 struct ui_out *ui_out = data; 364 365 ui_out_table_end (ui_out); 366 } 367 368 struct cleanup * 369 make_cleanup_ui_out_table_begin_end (struct ui_out *ui_out, int nr_cols, 370 int nr_rows, const char *tblid) 371 { 372 ui_out_table_begin (ui_out, nr_cols, nr_rows, tblid); 373 return make_cleanup (do_cleanup_table_end, ui_out); 374 } 375 376 void 377 ui_out_begin (struct ui_out *uiout, 378 enum ui_out_type type, 379 const char *id) 380 { 381 int new_level; 382 383 if (uiout->table.flag && !uiout->table.body_flag) 384 internal_error (__FILE__, __LINE__, 385 _("table header or table_body expected; lists must be \ 386 specified after table_body.")); 387 388 /* Be careful to verify the ``field'' before the new tuple/list is 389 pushed onto the stack. That way the containing list/table/row is 390 verified and not the newly created tuple/list. This verification 391 is needed (at least) for the case where a table row entry 392 contains either a tuple/list. For that case bookkeeping such as 393 updating the column count or advancing to the next heading still 394 needs to be performed. */ 395 { 396 int fldno; 397 int width; 398 int align; 399 400 verify_field (uiout, &fldno, &width, &align); 401 } 402 403 new_level = push_level (uiout, type, id); 404 405 /* If the push puts us at the same level as a table row entry, we've 406 got a new table row. Put the header pointer back to the start. */ 407 if (uiout->table.body_flag 408 && uiout->table.entry_level == new_level) 409 uiout->table.header_next = uiout->table.header_first; 410 411 uo_begin (uiout, type, new_level, id); 412 } 413 414 void 415 ui_out_end (struct ui_out *uiout, 416 enum ui_out_type type) 417 { 418 int old_level = pop_level (uiout, type); 419 420 uo_end (uiout, type, old_level); 421 } 422 423 struct ui_out_end_cleanup_data 424 { 425 struct ui_out *uiout; 426 enum ui_out_type type; 427 }; 428 429 static void 430 do_cleanup_end (void *data) 431 { 432 struct ui_out_end_cleanup_data *end_cleanup_data = data; 433 434 ui_out_end (end_cleanup_data->uiout, end_cleanup_data->type); 435 xfree (end_cleanup_data); 436 } 437 438 static struct cleanup * 439 make_cleanup_ui_out_end (struct ui_out *uiout, 440 enum ui_out_type type) 441 { 442 struct ui_out_end_cleanup_data *end_cleanup_data; 443 444 end_cleanup_data = XNEW (struct ui_out_end_cleanup_data); 445 end_cleanup_data->uiout = uiout; 446 end_cleanup_data->type = type; 447 return make_cleanup (do_cleanup_end, end_cleanup_data); 448 } 449 450 struct cleanup * 451 make_cleanup_ui_out_tuple_begin_end (struct ui_out *uiout, 452 const char *id) 453 { 454 ui_out_begin (uiout, ui_out_type_tuple, id); 455 return make_cleanup_ui_out_end (uiout, ui_out_type_tuple); 456 } 457 458 struct cleanup * 459 make_cleanup_ui_out_list_begin_end (struct ui_out *uiout, 460 const char *id) 461 { 462 ui_out_begin (uiout, ui_out_type_list, id); 463 return make_cleanup_ui_out_end (uiout, ui_out_type_list); 464 } 465 466 void 467 ui_out_field_int (struct ui_out *uiout, 468 const char *fldname, 469 int value) 470 { 471 int fldno; 472 int width; 473 int align; 474 475 verify_field (uiout, &fldno, &width, &align); 476 477 uo_field_int (uiout, fldno, width, align, fldname, value); 478 } 479 480 void 481 ui_out_field_fmt_int (struct ui_out *uiout, 482 int input_width, 483 enum ui_align input_align, 484 const char *fldname, 485 int value) 486 { 487 int fldno; 488 int width; 489 int align; 490 491 verify_field (uiout, &fldno, &width, &align); 492 493 uo_field_int (uiout, fldno, input_width, input_align, fldname, value); 494 } 495 496 /* Documented in ui-out.h. */ 497 498 void 499 ui_out_field_core_addr (struct ui_out *uiout, 500 const char *fldname, 501 struct gdbarch *gdbarch, 502 CORE_ADDR address) 503 { 504 ui_out_field_string (uiout, fldname, 505 print_core_address (gdbarch, address)); 506 } 507 508 void 509 ui_out_field_stream (struct ui_out *uiout, 510 const char *fldname, 511 struct ui_file *stream) 512 { 513 long length; 514 char *buffer = ui_file_xstrdup (stream, &length); 515 struct cleanup *old_cleanup = make_cleanup (xfree, buffer); 516 517 if (length > 0) 518 ui_out_field_string (uiout, fldname, buffer); 519 else 520 ui_out_field_skip (uiout, fldname); 521 ui_file_rewind (stream); 522 do_cleanups (old_cleanup); 523 } 524 525 /* Used to omit a field. */ 526 527 void 528 ui_out_field_skip (struct ui_out *uiout, 529 const char *fldname) 530 { 531 int fldno; 532 int width; 533 int align; 534 535 verify_field (uiout, &fldno, &width, &align); 536 537 uo_field_skip (uiout, fldno, width, align, fldname); 538 } 539 540 void 541 ui_out_field_string (struct ui_out *uiout, 542 const char *fldname, 543 const char *string) 544 { 545 int fldno; 546 int width; 547 int align; 548 549 verify_field (uiout, &fldno, &width, &align); 550 551 uo_field_string (uiout, fldno, width, align, fldname, string); 552 } 553 554 /* VARARGS */ 555 void 556 ui_out_field_fmt (struct ui_out *uiout, 557 const char *fldname, 558 const char *format, ...) 559 { 560 va_list args; 561 int fldno; 562 int width; 563 int align; 564 565 /* Will not align, but has to call anyway. */ 566 verify_field (uiout, &fldno, &width, &align); 567 568 va_start (args, format); 569 570 uo_field_fmt (uiout, fldno, width, align, fldname, format, args); 571 572 va_end (args); 573 } 574 575 void 576 ui_out_spaces (struct ui_out *uiout, int numspaces) 577 { 578 uo_spaces (uiout, numspaces); 579 } 580 581 void 582 ui_out_text (struct ui_out *uiout, 583 const char *string) 584 { 585 uo_text (uiout, string); 586 } 587 588 void 589 ui_out_message (struct ui_out *uiout, int verbosity, 590 const char *format,...) 591 { 592 va_list args; 593 594 va_start (args, format); 595 uo_message (uiout, verbosity, format, args); 596 va_end (args); 597 } 598 599 void 600 ui_out_wrap_hint (struct ui_out *uiout, char *identstring) 601 { 602 uo_wrap_hint (uiout, identstring); 603 } 604 605 void 606 ui_out_flush (struct ui_out *uiout) 607 { 608 uo_flush (uiout); 609 } 610 611 int 612 ui_out_redirect (struct ui_out *uiout, struct ui_file *outstream) 613 { 614 return uo_redirect (uiout, outstream); 615 } 616 617 /* Set the flags specified by the mask given. */ 618 int 619 ui_out_set_flags (struct ui_out *uiout, int mask) 620 { 621 int oldflags = uiout->flags; 622 623 uiout->flags |= mask; 624 return oldflags; 625 } 626 627 /* Clear the flags specified by the mask given. */ 628 int 629 ui_out_clear_flags (struct ui_out *uiout, int mask) 630 { 631 int oldflags = uiout->flags; 632 633 uiout->flags &= ~mask; 634 return oldflags; 635 } 636 637 /* Test the flags against the mask given. */ 638 int 639 ui_out_test_flags (struct ui_out *uiout, int mask) 640 { 641 return (uiout->flags & mask); 642 } 643 644 /* Obtain the current verbosity level (as stablished by the 645 'set verbositylevel' command. */ 646 647 int 648 ui_out_get_verblvl (struct ui_out *uiout) 649 { 650 /* FIXME: not implemented yet. */ 651 return 0; 652 } 653 654 int 655 ui_out_is_mi_like_p (struct ui_out *uiout) 656 { 657 return uiout->impl->is_mi_like_p; 658 } 659 660 /* Default gdb-out hook functions. */ 661 662 static void 663 default_table_begin (struct ui_out *uiout, int nbrofcols, 664 int nr_rows, 665 const char *tblid) 666 { 667 } 668 669 static void 670 default_table_body (struct ui_out *uiout) 671 { 672 } 673 674 static void 675 default_table_end (struct ui_out *uiout) 676 { 677 } 678 679 static void 680 default_table_header (struct ui_out *uiout, int width, enum ui_align alignment, 681 const char *col_name, 682 const char *colhdr) 683 { 684 } 685 686 static void 687 default_begin (struct ui_out *uiout, 688 enum ui_out_type type, 689 int level, 690 const char *id) 691 { 692 } 693 694 static void 695 default_end (struct ui_out *uiout, 696 enum ui_out_type type, 697 int level) 698 { 699 } 700 701 static void 702 default_field_int (struct ui_out *uiout, int fldno, int width, 703 enum ui_align align, 704 const char *fldname, int value) 705 { 706 } 707 708 static void 709 default_field_skip (struct ui_out *uiout, int fldno, int width, 710 enum ui_align align, const char *fldname) 711 { 712 } 713 714 static void 715 default_field_string (struct ui_out *uiout, 716 int fldno, 717 int width, 718 enum ui_align align, 719 const char *fldname, 720 const char *string) 721 { 722 } 723 724 static void 725 default_field_fmt (struct ui_out *uiout, int fldno, int width, 726 enum ui_align align, 727 const char *fldname, 728 const char *format, 729 va_list args) 730 { 731 } 732 733 static void 734 default_spaces (struct ui_out *uiout, int numspaces) 735 { 736 } 737 738 static void 739 default_text (struct ui_out *uiout, const char *string) 740 { 741 } 742 743 static void 744 default_message (struct ui_out *uiout, int verbosity, 745 const char *format, 746 va_list args) 747 { 748 } 749 750 static void 751 default_wrap_hint (struct ui_out *uiout, char *identstring) 752 { 753 } 754 755 static void 756 default_flush (struct ui_out *uiout) 757 { 758 } 759 760 static void 761 default_data_destroy (struct ui_out *uiout) 762 { 763 } 764 765 /* Interface to the implementation functions. */ 766 767 void 768 uo_table_begin (struct ui_out *uiout, int nbrofcols, 769 int nr_rows, 770 const char *tblid) 771 { 772 if (!uiout->impl->table_begin) 773 return; 774 uiout->impl->table_begin (uiout, nbrofcols, nr_rows, tblid); 775 } 776 777 void 778 uo_table_body (struct ui_out *uiout) 779 { 780 if (!uiout->impl->table_body) 781 return; 782 uiout->impl->table_body (uiout); 783 } 784 785 void 786 uo_table_end (struct ui_out *uiout) 787 { 788 if (!uiout->impl->table_end) 789 return; 790 uiout->impl->table_end (uiout); 791 } 792 793 void 794 uo_table_header (struct ui_out *uiout, int width, enum ui_align align, 795 const char *col_name, 796 const char *colhdr) 797 { 798 if (!uiout->impl->table_header) 799 return; 800 uiout->impl->table_header (uiout, width, align, col_name, colhdr); 801 } 802 803 /* Clear the table associated with UIOUT. */ 804 805 static void 806 clear_table (struct ui_out *uiout) 807 { 808 xfree (uiout->table.id); 809 uiout->table.id = NULL; 810 clear_header_list (uiout); 811 } 812 813 void 814 uo_begin (struct ui_out *uiout, 815 enum ui_out_type type, 816 int level, 817 const char *id) 818 { 819 if (uiout->impl->begin == NULL) 820 return; 821 uiout->impl->begin (uiout, type, level, id); 822 } 823 824 void 825 uo_end (struct ui_out *uiout, 826 enum ui_out_type type, 827 int level) 828 { 829 if (uiout->impl->end == NULL) 830 return; 831 uiout->impl->end (uiout, type, level); 832 } 833 834 void 835 uo_field_int (struct ui_out *uiout, int fldno, int width, enum ui_align align, 836 const char *fldname, 837 int value) 838 { 839 if (!uiout->impl->field_int) 840 return; 841 uiout->impl->field_int (uiout, fldno, width, align, fldname, value); 842 } 843 844 void 845 uo_field_skip (struct ui_out *uiout, int fldno, int width, enum ui_align align, 846 const char *fldname) 847 { 848 if (!uiout->impl->field_skip) 849 return; 850 uiout->impl->field_skip (uiout, fldno, width, align, fldname); 851 } 852 853 void 854 uo_field_string (struct ui_out *uiout, int fldno, int width, 855 enum ui_align align, 856 const char *fldname, 857 const char *string) 858 { 859 if (!uiout->impl->field_string) 860 return; 861 uiout->impl->field_string (uiout, fldno, width, align, fldname, string); 862 } 863 864 void 865 uo_field_fmt (struct ui_out *uiout, int fldno, int width, enum ui_align align, 866 const char *fldname, 867 const char *format, 868 va_list args) 869 { 870 if (!uiout->impl->field_fmt) 871 return; 872 uiout->impl->field_fmt (uiout, fldno, width, align, fldname, format, args); 873 } 874 875 void 876 uo_spaces (struct ui_out *uiout, int numspaces) 877 { 878 if (!uiout->impl->spaces) 879 return; 880 uiout->impl->spaces (uiout, numspaces); 881 } 882 883 void 884 uo_text (struct ui_out *uiout, 885 const char *string) 886 { 887 if (!uiout->impl->text) 888 return; 889 uiout->impl->text (uiout, string); 890 } 891 892 void 893 uo_message (struct ui_out *uiout, int verbosity, 894 const char *format, 895 va_list args) 896 { 897 if (!uiout->impl->message) 898 return; 899 uiout->impl->message (uiout, verbosity, format, args); 900 } 901 902 void 903 uo_wrap_hint (struct ui_out *uiout, char *identstring) 904 { 905 if (!uiout->impl->wrap_hint) 906 return; 907 uiout->impl->wrap_hint (uiout, identstring); 908 } 909 910 void 911 uo_flush (struct ui_out *uiout) 912 { 913 if (!uiout->impl->flush) 914 return; 915 uiout->impl->flush (uiout); 916 } 917 918 int 919 uo_redirect (struct ui_out *uiout, struct ui_file *outstream) 920 { 921 if (!uiout->impl->redirect) 922 return -1; 923 uiout->impl->redirect (uiout, outstream); 924 return 0; 925 } 926 927 void 928 uo_data_destroy (struct ui_out *uiout) 929 { 930 if (!uiout->impl->data_destroy) 931 return; 932 933 uiout->impl->data_destroy (uiout); 934 } 935 936 /* local functions */ 937 938 /* List of column headers manipulation routines. */ 939 940 static void 941 clear_header_list (struct ui_out *uiout) 942 { 943 while (uiout->table.header_first != NULL) 944 { 945 uiout->table.header_next = uiout->table.header_first; 946 uiout->table.header_first = uiout->table.header_first->next; 947 xfree (uiout->table.header_next->colhdr); 948 xfree (uiout->table.header_next->col_name); 949 xfree (uiout->table.header_next); 950 } 951 gdb_assert (uiout->table.header_first == NULL); 952 uiout->table.header_last = NULL; 953 uiout->table.header_next = NULL; 954 } 955 956 static void 957 append_header_to_list (struct ui_out *uiout, 958 int width, 959 int alignment, 960 const char *col_name, 961 const char *colhdr) 962 { 963 struct ui_out_hdr *temphdr; 964 965 temphdr = XNEW (struct ui_out_hdr); 966 temphdr->width = width; 967 temphdr->alignment = alignment; 968 /* We have to copy the column title as the original may be an 969 automatic. */ 970 if (colhdr != NULL) 971 temphdr->colhdr = xstrdup (colhdr); 972 else 973 temphdr->colhdr = NULL; 974 975 if (col_name != NULL) 976 temphdr->col_name = xstrdup (col_name); 977 else if (colhdr != NULL) 978 temphdr->col_name = xstrdup (colhdr); 979 else 980 temphdr->col_name = NULL; 981 982 temphdr->next = NULL; 983 if (uiout->table.header_first == NULL) 984 { 985 temphdr->colno = 1; 986 uiout->table.header_first = temphdr; 987 uiout->table.header_last = temphdr; 988 } 989 else 990 { 991 temphdr->colno = uiout->table.header_last->colno + 1; 992 uiout->table.header_last->next = temphdr; 993 uiout->table.header_last = temphdr; 994 } 995 uiout->table.header_next = uiout->table.header_last; 996 } 997 998 /* Extract the format information for the NEXT header and advance 999 the header pointer. Return 0 if there was no next header. */ 1000 1001 static int 1002 get_next_header (struct ui_out *uiout, 1003 int *colno, 1004 int *width, 1005 int *alignment, 1006 char **colhdr) 1007 { 1008 /* There may be no headers at all or we may have used all columns. */ 1009 if (uiout->table.header_next == NULL) 1010 return 0; 1011 *colno = uiout->table.header_next->colno; 1012 *width = uiout->table.header_next->width; 1013 *alignment = uiout->table.header_next->alignment; 1014 *colhdr = uiout->table.header_next->colhdr; 1015 /* Advance the header pointer to the next entry. */ 1016 uiout->table.header_next = uiout->table.header_next->next; 1017 return 1; 1018 } 1019 1020 1021 /* Verify that the field/tuple/list is correctly positioned. Return 1022 the field number and corresponding alignment (if 1023 available/applicable). */ 1024 1025 static void 1026 verify_field (struct ui_out *uiout, int *fldno, int *width, int *align) 1027 { 1028 struct ui_out_level *current = current_level (uiout); 1029 char *text; 1030 1031 if (uiout->table.flag) 1032 { 1033 if (!uiout->table.body_flag) 1034 internal_error (__FILE__, __LINE__, 1035 _("table_body missing; table fields must be \ 1036 specified after table_body and inside a list.")); 1037 /* NOTE: cagney/2001-12-08: There was a check here to ensure 1038 that this code was only executed when uiout->level was 1039 greater than zero. That no longer applies - this code is run 1040 before each table row tuple is started and at that point the 1041 level is zero. */ 1042 } 1043 1044 current->field_count += 1; 1045 1046 if (uiout->table.body_flag 1047 && uiout->table.entry_level == uiout->level 1048 && get_next_header (uiout, fldno, width, align, &text)) 1049 { 1050 if (*fldno != current->field_count) 1051 internal_error (__FILE__, __LINE__, 1052 _("ui-out internal error in handling headers.")); 1053 } 1054 else 1055 { 1056 *width = 0; 1057 *align = ui_noalign; 1058 *fldno = current->field_count; 1059 } 1060 } 1061 1062 1063 /* Access to ui-out members data. */ 1064 1065 void * 1066 ui_out_data (struct ui_out *uiout) 1067 { 1068 return uiout->data; 1069 } 1070 1071 /* Access table field parameters. */ 1072 int 1073 ui_out_query_field (struct ui_out *uiout, int colno, 1074 int *width, int *alignment, char **col_name) 1075 { 1076 struct ui_out_hdr *hdr; 1077 1078 if (!uiout->table.flag) 1079 return 0; 1080 1081 for (hdr = uiout->table.header_first; hdr; hdr = hdr->next) 1082 if (hdr->colno == colno) 1083 { 1084 *width = hdr->width; 1085 *alignment = hdr->alignment; 1086 *col_name = hdr->col_name; 1087 return 1; 1088 } 1089 1090 return 0; 1091 } 1092 1093 /* Initalize private members at startup. */ 1094 1095 struct ui_out * 1096 ui_out_new (const struct ui_out_impl *impl, void *data, 1097 int flags) 1098 { 1099 struct ui_out *uiout = XNEW (struct ui_out); 1100 struct ui_out_level *current = XNEW (struct ui_out_level); 1101 1102 uiout->data = data; 1103 uiout->impl = impl; 1104 uiout->flags = flags; 1105 uiout->table.flag = 0; 1106 uiout->table.body_flag = 0; 1107 uiout->level = 0; 1108 uiout->levels = NULL; 1109 1110 /* Create uiout->level 0, the default level. */ 1111 current->type = ui_out_type_tuple; 1112 current->field_count = 0; 1113 VEC_safe_push (ui_out_level_p, uiout->levels, current); 1114 1115 uiout->table.id = NULL; 1116 uiout->table.header_first = NULL; 1117 uiout->table.header_last = NULL; 1118 uiout->table.header_next = NULL; 1119 return uiout; 1120 } 1121 1122 /* Free UIOUT and the memory areas it references. */ 1123 1124 void 1125 ui_out_destroy (struct ui_out *uiout) 1126 { 1127 int i; 1128 struct ui_out_level *current; 1129 1130 /* Make sure that all levels are freed in the case where levels have 1131 been pushed, but not popped before the ui_out object is 1132 destroyed. */ 1133 for (i = 0; 1134 VEC_iterate (ui_out_level_p, uiout->levels, i, current); 1135 ++i) 1136 xfree (current); 1137 1138 VEC_free (ui_out_level_p, uiout->levels); 1139 uo_data_destroy (uiout); 1140 clear_table (uiout); 1141 xfree (uiout); 1142 } 1143 1144 /* Standard gdb initialization hook. */ 1145 1146 void 1147 _initialize_ui_out (void) 1148 { 1149 /* nothing needs to be done */ 1150 } 1151