1 /* TUI display registers in window. 2 3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software 4 Foundation, Inc. 5 6 Contributed by Hewlett-Packard Company. 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 2 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, write to the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, 23 Boston, MA 02111-1307, USA. */ 24 25 #include "defs.h" 26 #include "tui/tui.h" 27 #include "tui/tui-data.h" 28 #include "symtab.h" 29 #include "gdbtypes.h" 30 #include "gdbcmd.h" 31 #include "frame.h" 32 #include "regcache.h" 33 #include "inferior.h" 34 #include "target.h" 35 #include "gdb_string.h" 36 #include "tui/tui-layout.h" 37 #include "tui/tui-win.h" 38 #include "tui/tui-windata.h" 39 #include "tui/tui-wingeneral.h" 40 #include "tui/tui-file.h" 41 #include "reggroups.h" 42 43 #include "gdb_curses.h" 44 45 46 /***************************************** 47 ** STATIC LOCAL FUNCTIONS FORWARD DECLS ** 48 ******************************************/ 49 static void 50 tui_display_register (struct tui_data_element *data, 51 struct tui_gen_win_info *win_info); 52 53 static enum tui_status 54 tui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group, 55 struct frame_info *frame, int refresh_values_only); 56 57 static enum tui_status 58 tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame, 59 struct tui_data_element *data, int regnum, int *changedp); 60 static void tui_register_format 61 (struct gdbarch *, struct frame_info *, struct tui_data_element*, int); 62 static void tui_scroll_regs_forward_command (char *, int); 63 static void tui_scroll_regs_backward_command (char *, int); 64 65 66 67 /***************************************** 68 ** PUBLIC FUNCTIONS ** 69 ******************************************/ 70 71 /* Answer the number of the last line in the regs display. If there 72 are no registers (-1) is returned. */ 73 int 74 tui_last_regs_line_no (void) 75 { 76 int num_lines = (-1); 77 78 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 79 { 80 num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count / 81 TUI_DATA_WIN->detail.data_display_info.regs_column_count); 82 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count % 83 TUI_DATA_WIN->detail.data_display_info.regs_column_count) 84 num_lines++; 85 } 86 return num_lines; 87 } 88 89 90 /* Answer the line number that the register element at element_no is 91 on. If element_no is greater than the number of register elements 92 there are, -1 is returned. */ 93 int 94 tui_line_from_reg_element_no (int element_no) 95 { 96 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count) 97 { 98 int i, line = (-1); 99 100 i = 1; 101 while (line == (-1)) 102 { 103 if (element_no < 104 (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i)) 105 line = i - 1; 106 else 107 i++; 108 } 109 110 return line; 111 } 112 else 113 return (-1); 114 } 115 116 117 /* Answer the index of the first element in line_no. If line_no is past 118 the register area (-1) is returned. */ 119 int 120 tui_first_reg_element_no_inline (int line_no) 121 { 122 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) 123 <= TUI_DATA_WIN->detail.data_display_info.regs_content_count) 124 return ((line_no + 1) * 125 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 126 TUI_DATA_WIN->detail.data_display_info.regs_column_count; 127 else 128 return (-1); 129 } 130 131 132 /* Answer the index of the last element in line_no. If line_no is 133 past the register area (-1) is returned. */ 134 int 135 tui_last_reg_element_no_in_line (int line_no) 136 { 137 if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <= 138 TUI_DATA_WIN->detail.data_display_info.regs_content_count) 139 return ((line_no + 1) * 140 TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1; 141 else 142 return (-1); 143 } 144 145 /* Show the registers of the given group in the data window 146 and refresh the window. */ 147 void 148 tui_show_registers (struct reggroup *group) 149 { 150 enum tui_status ret = TUI_FAILURE; 151 struct tui_data_info *display_info; 152 153 /* Make sure the curses mode is enabled. */ 154 tui_enable (); 155 156 /* Make sure the register window is visible. If not, select an 157 appropriate layout. */ 158 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible) 159 tui_set_layout_for_display_command (DATA_NAME); 160 161 display_info = &TUI_DATA_WIN->detail.data_display_info; 162 if (group == 0) 163 group = general_reggroup; 164 165 /* Say that registers should be displayed, even if there is a problem. */ 166 display_info->display_regs = TRUE; 167 168 if (target_has_registers && target_has_stack && target_has_memory) 169 { 170 ret = tui_show_register_group (current_gdbarch, group, 171 get_current_frame (), 172 group == display_info->current_group); 173 } 174 if (ret == TUI_FAILURE) 175 { 176 display_info->current_group = 0; 177 tui_erase_data_content (NO_REGS_STRING); 178 } 179 else 180 { 181 int i; 182 183 /* Clear all notation of changed values */ 184 for (i = 0; i < display_info->regs_content_count; i++) 185 { 186 struct tui_gen_win_info *data_item_win; 187 struct tui_win_element *win; 188 189 data_item_win = &display_info->regs_content[i] 190 ->which_element.data_window; 191 win = (struct tui_win_element *) data_item_win->content[0]; 192 win->which_element.data.highlight = FALSE; 193 } 194 display_info->current_group = group; 195 tui_display_all_data (); 196 } 197 } 198 199 200 /* Set the data window to display the registers of the register group 201 using the given frame. Values are refreshed only when refresh_values_only 202 is TRUE. */ 203 204 static enum tui_status 205 tui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group, 206 struct frame_info *frame, int refresh_values_only) 207 { 208 enum tui_status ret = TUI_FAILURE; 209 int nr_regs; 210 int allocated_here = FALSE; 211 int regnum, pos; 212 char title[80]; 213 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; 214 215 /* Make a new title showing which group we display. */ 216 snprintf (title, sizeof (title) - 1, "Register group: %s", 217 reggroup_name (group)); 218 xfree (TUI_DATA_WIN->generic.title); 219 TUI_DATA_WIN->generic.title = xstrdup (title); 220 221 /* See how many registers must be displayed. */ 222 nr_regs = 0; 223 for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) 224 { 225 /* Must be in the group and have a name. */ 226 if (gdbarch_register_reggroup_p (gdbarch, regnum, group) 227 && gdbarch_register_name (gdbarch, regnum) != 0) 228 nr_regs++; 229 } 230 231 if (display_info->regs_content_count > 0 && !refresh_values_only) 232 { 233 tui_free_data_content (display_info->regs_content, 234 display_info->regs_content_count); 235 display_info->regs_content_count = 0; 236 } 237 238 if (display_info->regs_content_count <= 0) 239 { 240 display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN); 241 allocated_here = TRUE; 242 refresh_values_only = FALSE; 243 } 244 245 if (display_info->regs_content != (tui_win_content) NULL) 246 { 247 if (!refresh_values_only || allocated_here) 248 { 249 TUI_DATA_WIN->generic.content = (void*) NULL; 250 TUI_DATA_WIN->generic.content_size = 0; 251 tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs); 252 display_info->regs_content 253 = (tui_win_content) TUI_DATA_WIN->generic.content; 254 display_info->regs_content_count = nr_regs; 255 } 256 257 /* Now set the register names and values */ 258 pos = 0; 259 for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++) 260 { 261 struct tui_gen_win_info *data_item_win; 262 struct tui_data_element *data; 263 const char *name; 264 265 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) 266 continue; 267 268 name = gdbarch_register_name (gdbarch, regnum); 269 if (name == 0) 270 continue; 271 272 data_item_win = 273 &display_info->regs_content[pos]->which_element.data_window; 274 data = 275 &((struct tui_win_element *) data_item_win->content[0])->which_element.data; 276 if (data) 277 { 278 if (!refresh_values_only) 279 { 280 data->item_no = regnum; 281 data->name = name; 282 data->highlight = FALSE; 283 } 284 if (data->value == (void*) NULL) 285 data->value = (void*) xmalloc (MAX_REGISTER_SIZE); 286 287 tui_get_register (gdbarch, frame, data, regnum, 0); 288 } 289 pos++; 290 } 291 292 TUI_DATA_WIN->generic.content_size = 293 display_info->regs_content_count + display_info->data_content_count; 294 ret = TUI_SUCCESS; 295 } 296 297 return ret; 298 } 299 300 /* Function to display the registers in the content from 301 'start_element_no' until the end of the register content or the end 302 of the display height. No checking for displaying past the end of 303 the registers is done here. */ 304 void 305 tui_display_registers_from (int start_element_no) 306 { 307 struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; 308 309 if (display_info->regs_content != (tui_win_content) NULL && 310 display_info->regs_content_count > 0) 311 { 312 int i = start_element_no; 313 int j, value_chars_wide, item_win_width, cur_y; 314 315 int max_len = 0; 316 for (i = 0; i < display_info->regs_content_count; i++) 317 { 318 struct tui_data_element *data; 319 struct tui_gen_win_info *data_item_win; 320 char *p; 321 int len; 322 323 data_item_win = &display_info->regs_content[i]->which_element.data_window; 324 data = &((struct tui_win_element *) 325 data_item_win->content[0])->which_element.data; 326 len = 0; 327 p = data->content; 328 if (p != 0) 329 while (*p) 330 { 331 if (*p++ == '\t') 332 len = 8 * ((len / 8) + 1); 333 else 334 len++; 335 } 336 337 if (len > max_len) 338 max_len = len; 339 } 340 item_win_width = max_len + 1; 341 i = start_element_no; 342 343 display_info->regs_column_count = 344 (TUI_DATA_WIN->generic.width - 2) / item_win_width; 345 if (display_info->regs_column_count == 0) 346 display_info->regs_column_count = 1; 347 item_win_width = 348 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count; 349 350 /* 351 ** Now create each data "sub" window, and write the display into it. 352 */ 353 cur_y = 1; 354 while (i < display_info->regs_content_count && 355 cur_y <= TUI_DATA_WIN->generic.viewport_height) 356 { 357 for (j = 0; 358 (j < display_info->regs_column_count && 359 i < display_info->regs_content_count); j++) 360 { 361 struct tui_gen_win_info * data_item_win; 362 struct tui_data_element * data_element_ptr; 363 364 /* create the window if necessary */ 365 data_item_win = &display_info->regs_content[i] 366 ->which_element.data_window; 367 data_element_ptr = &((struct tui_win_element *) 368 data_item_win->content[0])->which_element.data; 369 if (data_item_win->handle != (WINDOW*) NULL 370 && (data_item_win->height != 1 371 || data_item_win->width != item_win_width 372 || data_item_win->origin.x != (item_win_width * j) + 1 373 || data_item_win->origin.y != cur_y)) 374 { 375 tui_delete_win (data_item_win->handle); 376 data_item_win->handle = 0; 377 } 378 379 if (data_item_win->handle == (WINDOW *) NULL) 380 { 381 data_item_win->height = 1; 382 data_item_win->width = item_win_width; 383 data_item_win->origin.x = (item_win_width * j) + 1; 384 data_item_win->origin.y = cur_y; 385 tui_make_window (data_item_win, DONT_BOX_WINDOW); 386 scrollok (data_item_win->handle, FALSE); 387 } 388 touchwin (data_item_win->handle); 389 390 /* Get the printable representation of the register 391 and display it. */ 392 tui_display_register (data_element_ptr, data_item_win); 393 i++; /* next register */ 394 } 395 cur_y++; /* next row; */ 396 } 397 } 398 } 399 400 401 /* Function to display the registers in the content from 402 'start_element_no' on 'start_line_no' until the end of the register 403 content or the end of the display height. This function checks 404 that we won't display off the end of the register display. */ 405 void 406 tui_display_reg_element_at_line (int start_element_no, int start_line_no) 407 { 408 if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL && 409 TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 410 { 411 int element_no = start_element_no; 412 413 if (start_element_no != 0 && start_line_no != 0) 414 { 415 int last_line_no, first_line_on_last_page; 416 417 last_line_no = tui_last_regs_line_no (); 418 first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2); 419 if (first_line_on_last_page < 0) 420 first_line_on_last_page = 0; 421 /* 422 ** If there is no other data displayed except registers, 423 ** and the element_no causes us to scroll past the end of the 424 ** registers, adjust what element to really start the display at. 425 */ 426 if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 && 427 start_line_no > first_line_on_last_page) 428 element_no = tui_first_reg_element_no_inline (first_line_on_last_page); 429 } 430 tui_display_registers_from (element_no); 431 } 432 } 433 434 435 436 /* Function to display the registers starting at line line_no in the 437 data window. Answers the line number that the display actually 438 started from. If nothing is displayed (-1) is returned. */ 439 int 440 tui_display_registers_from_line (int line_no, int force_display) 441 { 442 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) 443 { 444 int line, element_no; 445 446 if (line_no < 0) 447 line = 0; 448 else if (force_display) 449 { /* 450 ** If we must display regs (force_display is true), then make 451 ** sure that we don't display off the end of the registers. 452 */ 453 if (line_no >= tui_last_regs_line_no ()) 454 { 455 if ((line = tui_line_from_reg_element_no ( 456 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0) 457 line = 0; 458 } 459 else 460 line = line_no; 461 } 462 else 463 line = line_no; 464 465 element_no = tui_first_reg_element_no_inline (line); 466 if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count) 467 tui_display_reg_element_at_line (element_no, line); 468 else 469 line = (-1); 470 471 return line; 472 } 473 474 return (-1); /* nothing was displayed */ 475 } 476 477 478 /* This function check all displayed registers for changes in values, 479 given a particular frame. If the values have changed, they are 480 updated with the new value and highlighted. */ 481 void 482 tui_check_register_values (struct frame_info *frame) 483 { 484 if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible) 485 { 486 struct tui_data_info *display_info 487 = &TUI_DATA_WIN->detail.data_display_info; 488 489 if (display_info->regs_content_count <= 0 && display_info->display_regs) 490 tui_show_registers (display_info->current_group); 491 else 492 { 493 int i, j; 494 495 for (i = 0; (i < display_info->regs_content_count); i++) 496 { 497 struct tui_data_element *data; 498 struct tui_gen_win_info *data_item_win_ptr; 499 int was_hilighted; 500 501 data_item_win_ptr = &display_info->regs_content[i]-> 502 which_element.data_window; 503 data = &((struct tui_win_element *) 504 data_item_win_ptr->content[0])->which_element.data; 505 was_hilighted = data->highlight; 506 507 tui_get_register (current_gdbarch, frame, data, 508 data->item_no, &data->highlight); 509 510 if (data->highlight || was_hilighted) 511 { 512 tui_display_register (data, data_item_win_ptr); 513 } 514 } 515 } 516 } 517 } 518 519 /* Display a register in a window. If hilite is TRUE, 520 then the value will be displayed in reverse video */ 521 static void 522 tui_display_register (struct tui_data_element *data, 523 struct tui_gen_win_info *win_info) 524 { 525 if (win_info->handle != (WINDOW *) NULL) 526 { 527 int i; 528 529 if (data->highlight) 530 wstandout (win_info->handle); 531 532 wmove (win_info->handle, 0, 0); 533 for (i = 1; i < win_info->width; i++) 534 waddch (win_info->handle, ' '); 535 wmove (win_info->handle, 0, 0); 536 if (data->content) 537 waddstr (win_info->handle, data->content); 538 539 if (data->highlight) 540 wstandend (win_info->handle); 541 tui_refresh_win (win_info); 542 } 543 } 544 545 static void 546 tui_reg_next_command (char *arg, int from_tty) 547 { 548 if (TUI_DATA_WIN != 0) 549 { 550 struct reggroup *group 551 = TUI_DATA_WIN->detail.data_display_info.current_group; 552 553 group = reggroup_next (current_gdbarch, group); 554 if (group == 0) 555 group = reggroup_next (current_gdbarch, 0); 556 557 if (group) 558 tui_show_registers (group); 559 } 560 } 561 562 static void 563 tui_reg_float_command (char *arg, int from_tty) 564 { 565 tui_show_registers (float_reggroup); 566 } 567 568 static void 569 tui_reg_general_command (char *arg, int from_tty) 570 { 571 tui_show_registers (general_reggroup); 572 } 573 574 static void 575 tui_reg_system_command (char *arg, int from_tty) 576 { 577 tui_show_registers (system_reggroup); 578 } 579 580 static struct cmd_list_element *tuireglist; 581 582 static void 583 tui_reg_command (char *args, int from_tty) 584 { 585 printf_unfiltered ("\"tui reg\" must be followed by the name of a " 586 "tui reg command.\n"); 587 help_list (tuireglist, "tui reg ", -1, gdb_stdout); 588 } 589 590 void 591 _initialize_tui_regs (void) 592 { 593 struct cmd_list_element **tuicmd; 594 595 tuicmd = tui_get_cmd_list (); 596 597 add_prefix_cmd ("reg", class_tui, tui_reg_command, 598 "TUI commands to control the register window.", 599 &tuireglist, "tui reg ", 0, 600 tuicmd); 601 602 add_cmd ("float", class_tui, tui_reg_float_command, 603 "Display only floating point registers\n", 604 &tuireglist); 605 add_cmd ("general", class_tui, tui_reg_general_command, 606 "Display only general registers\n", 607 &tuireglist); 608 add_cmd ("system", class_tui, tui_reg_system_command, 609 "Display only system registers\n", 610 &tuireglist); 611 add_cmd ("next", class_tui, tui_reg_next_command, 612 "Display next register group\n", 613 &tuireglist); 614 615 if (xdb_commands) 616 { 617 add_com ("fr", class_tui, tui_reg_float_command, 618 "Display only floating point registers\n"); 619 add_com ("gr", class_tui, tui_reg_general_command, 620 "Display only general registers\n"); 621 add_com ("sr", class_tui, tui_reg_system_command, 622 "Display only special registers\n"); 623 add_com ("+r", class_tui, tui_scroll_regs_forward_command, 624 "Scroll the registers window forward\n"); 625 add_com ("-r", class_tui, tui_scroll_regs_backward_command, 626 "Scroll the register window backward\n"); 627 } 628 } 629 630 631 /***************************************** 632 ** STATIC LOCAL FUNCTIONS ** 633 ******************************************/ 634 635 extern int pagination_enabled; 636 637 static void 638 tui_restore_gdbout (void *ui) 639 { 640 ui_file_delete (gdb_stdout); 641 gdb_stdout = (struct ui_file*) ui; 642 pagination_enabled = 1; 643 } 644 645 /* Get the register from the frame and make a printable representation 646 of it in the data element. */ 647 static void 648 tui_register_format (struct gdbarch *gdbarch, struct frame_info *frame, 649 struct tui_data_element *data_element, int regnum) 650 { 651 struct ui_file *stream; 652 struct ui_file *old_stdout; 653 const char *name; 654 struct cleanup *cleanups; 655 char *p, *s; 656 int pos; 657 struct type *type = gdbarch_register_type (gdbarch, regnum); 658 659 name = gdbarch_register_name (gdbarch, regnum); 660 if (name == 0) 661 { 662 return; 663 } 664 665 pagination_enabled = 0; 666 old_stdout = gdb_stdout; 667 stream = tui_sfileopen (256); 668 gdb_stdout = stream; 669 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout); 670 if (TYPE_VECTOR (type) != 0 && 0) 671 { 672 char buf[MAX_REGISTER_SIZE]; 673 int len; 674 675 len = register_size (current_gdbarch, regnum); 676 fprintf_filtered (stream, "%-14s ", name); 677 get_frame_register (frame, regnum, buf); 678 print_scalar_formatted (buf, type, 'f', len, stream); 679 } 680 else 681 { 682 gdbarch_print_registers_info (current_gdbarch, stream, 683 frame, regnum, 1); 684 } 685 686 /* Save formatted output in the buffer. */ 687 p = tui_file_get_strbuf (stream); 688 689 /* Remove the possible \n. */ 690 s = strrchr (p, '\n'); 691 if (s && s[1] == 0) 692 *s = 0; 693 694 xfree (data_element->content); 695 data_element->content = xstrdup (p); 696 do_cleanups (cleanups); 697 } 698 699 /* Get the register value from the given frame and format it for 700 the display. When changep is set, check if the new register value 701 has changed with respect to the previous call. */ 702 static enum tui_status 703 tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame, 704 struct tui_data_element *data, int regnum, int *changedp) 705 { 706 enum tui_status ret = TUI_FAILURE; 707 708 if (changedp) 709 *changedp = FALSE; 710 if (target_has_registers) 711 { 712 char buf[MAX_REGISTER_SIZE]; 713 714 get_frame_register (frame, regnum, buf); 715 /* NOTE: cagney/2003-03-13: This is bogus. It is refering to 716 the register cache and not the frame which could have pulled 717 the register value off the stack. */ 718 if (register_cached (regnum) >= 0) 719 { 720 if (changedp) 721 { 722 int size = register_size (gdbarch, regnum); 723 char *old = (char*) data->value; 724 int i; 725 726 for (i = 0; i < size; i++) 727 if (buf[i] != old[i]) 728 { 729 *changedp = TRUE; 730 old[i] = buf[i]; 731 } 732 } 733 734 /* Reformat the data content if the value changed. */ 735 if (changedp == 0 || *changedp == TRUE) 736 tui_register_format (gdbarch, frame, data, regnum); 737 ret = TUI_SUCCESS; 738 } 739 } 740 return ret; 741 } 742 743 static void 744 tui_scroll_regs_forward_command (char *arg, int from_tty) 745 { 746 tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1); 747 } 748 749 750 static void 751 tui_scroll_regs_backward_command (char *arg, int from_tty) 752 { 753 tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1); 754 } 755