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