1130803Smarcel/* TUI display locator. 2130803Smarcel 3130803Smarcel Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software 4130803Smarcel Foundation, Inc. 5130803Smarcel 6130803Smarcel Contributed by Hewlett-Packard Company. 7130803Smarcel 8130803Smarcel This file is part of GDB. 9130803Smarcel 10130803Smarcel This program is free software; you can redistribute it and/or modify 11130803Smarcel it under the terms of the GNU General Public License as published by 12130803Smarcel the Free Software Foundation; either version 2 of the License, or 13130803Smarcel (at your option) any later version. 14130803Smarcel 15130803Smarcel This program is distributed in the hope that it will be useful, 16130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 17130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18130803Smarcel GNU General Public License for more details. 19130803Smarcel 20130803Smarcel You should have received a copy of the GNU General Public License 21130803Smarcel along with this program; if not, write to the Free Software 22130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 23130803Smarcel Boston, MA 02111-1307, USA. */ 24130803Smarcel 25130803Smarcel#include "defs.h" 26130803Smarcel#include "symtab.h" 27130803Smarcel#include "breakpoint.h" 28130803Smarcel#include "frame.h" 29130803Smarcel#include "command.h" 30130803Smarcel#include "inferior.h" 31130803Smarcel#include "target.h" 32130803Smarcel#include "top.h" 33130803Smarcel#include "gdb_string.h" 34130803Smarcel#include "tui/tui.h" 35130803Smarcel#include "tui/tui-data.h" 36130803Smarcel#include "tui/tui-stack.h" 37130803Smarcel#include "tui/tui-wingeneral.h" 38130803Smarcel#include "tui/tui-source.h" 39130803Smarcel#include "tui/tui-winsource.h" 40130803Smarcel#include "tui/tui-file.h" 41130803Smarcel 42130803Smarcel#include "gdb_curses.h" 43130803Smarcel 44130803Smarcel/* Get a printable name for the function at the address. 45130803Smarcel The symbol name is demangled if demangling is turned on. 46130803Smarcel Returns a pointer to a static area holding the result. */ 47130803Smarcelstatic char* tui_get_function_from_frame (struct frame_info *fi); 48130803Smarcel 49130803Smarcel/* Set the filename portion of the locator. */ 50130803Smarcelstatic void tui_set_locator_filename (const char *filename); 51130803Smarcel 52130803Smarcel/* Update the locator, with the provided arguments. */ 53130803Smarcelstatic void tui_set_locator_info (const char *filename, const char *procname, 54130803Smarcel int lineno, CORE_ADDR addr); 55130803Smarcel 56130803Smarcelstatic void tui_update_command (char *, int); 57130803Smarcel 58130803Smarcel 59130803Smarcel/* Create the status line to display as much information as we 60130803Smarcel can on this single line: target name, process number, current 61130803Smarcel function, current line, current PC, SingleKey mode. */ 62130803Smarcelstatic char* 63130803Smarceltui_make_status_line (struct tui_locator_element* loc) 64130803Smarcel{ 65130803Smarcel char* string; 66130803Smarcel char line_buf[50], *pname; 67130803Smarcel char* buf; 68130803Smarcel int status_size; 69130803Smarcel int i, proc_width; 70130803Smarcel const char* pid_name; 71130803Smarcel const char* pc_buf; 72130803Smarcel int target_width; 73130803Smarcel int pid_width; 74130803Smarcel int line_width; 75130803Smarcel int pc_width; 76130803Smarcel struct ui_file *pc_out; 77130803Smarcel 78130803Smarcel if (ptid_equal (inferior_ptid, null_ptid)) 79130803Smarcel pid_name = "No process"; 80130803Smarcel else 81130803Smarcel pid_name = target_pid_to_str (inferior_ptid); 82130803Smarcel 83130803Smarcel target_width = strlen (target_shortname); 84130803Smarcel if (target_width > MAX_TARGET_WIDTH) 85130803Smarcel target_width = MAX_TARGET_WIDTH; 86130803Smarcel 87130803Smarcel pid_width = strlen (pid_name); 88130803Smarcel if (pid_width > MAX_PID_WIDTH) 89130803Smarcel pid_width = MAX_PID_WIDTH; 90130803Smarcel 91130803Smarcel status_size = tui_term_width (); 92130803Smarcel string = (char *) xmalloc (status_size + 1); 93130803Smarcel buf = (char*) alloca (status_size + 1); 94130803Smarcel 95130803Smarcel /* Translate line number and obtain its size. */ 96130803Smarcel if (loc->line_no > 0) 97130803Smarcel sprintf (line_buf, "%d", loc->line_no); 98130803Smarcel else 99130803Smarcel strcpy (line_buf, "??"); 100130803Smarcel line_width = strlen (line_buf); 101130803Smarcel if (line_width < MIN_LINE_WIDTH) 102130803Smarcel line_width = MIN_LINE_WIDTH; 103130803Smarcel 104130803Smarcel /* Translate PC address. */ 105130803Smarcel pc_out = tui_sfileopen (128); 106130803Smarcel print_address_numeric (loc->addr, 1, pc_out); 107130803Smarcel pc_buf = tui_file_get_strbuf (pc_out); 108130803Smarcel pc_width = strlen (pc_buf); 109130803Smarcel 110130803Smarcel /* First determine the amount of proc name width we have available. 111130803Smarcel The +1 are for a space separator between fields. 112130803Smarcel The -1 are to take into account the \0 counted by sizeof. */ 113130803Smarcel proc_width = (status_size 114130803Smarcel - (target_width + 1) 115130803Smarcel - (pid_width + 1) 116130803Smarcel - (sizeof (PROC_PREFIX) - 1 + 1) 117130803Smarcel - (sizeof (LINE_PREFIX) - 1 + line_width + 1) 118130803Smarcel - (sizeof (PC_PREFIX) - 1 + pc_width + 1) 119130803Smarcel - (tui_current_key_mode == TUI_SINGLE_KEY_MODE 120130803Smarcel ? (sizeof (SINGLE_KEY) - 1 + 1) 121130803Smarcel : 0)); 122130803Smarcel 123130803Smarcel /* If there is no room to print the function name, try by removing 124130803Smarcel some fields. */ 125130803Smarcel if (proc_width < MIN_PROC_WIDTH) 126130803Smarcel { 127130803Smarcel proc_width += target_width + 1; 128130803Smarcel target_width = 0; 129130803Smarcel if (proc_width < MIN_PROC_WIDTH) 130130803Smarcel { 131130803Smarcel proc_width += pid_width + 1; 132130803Smarcel pid_width = 0; 133130803Smarcel if (proc_width <= MIN_PROC_WIDTH) 134130803Smarcel { 135130803Smarcel proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1; 136130803Smarcel pc_width = 0; 137130803Smarcel if (proc_width < 0) 138130803Smarcel { 139130803Smarcel proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1; 140130803Smarcel line_width = 0; 141130803Smarcel if (proc_width < 0) 142130803Smarcel proc_width = 0; 143130803Smarcel } 144130803Smarcel } 145130803Smarcel } 146130803Smarcel } 147130803Smarcel 148130803Smarcel /* Now convert elements to string form */ 149130803Smarcel pname = loc->proc_name; 150130803Smarcel 151130803Smarcel /* Now create the locator line from the string version 152130803Smarcel of the elements. We could use sprintf() here but 153130803Smarcel that wouldn't ensure that we don't overrun the size 154130803Smarcel of the allocated buffer. strcat_to_buf() will. */ 155130803Smarcel *string = (char) 0; 156130803Smarcel 157130803Smarcel if (target_width > 0) 158130803Smarcel { 159130803Smarcel sprintf (buf, "%*.*s ", 160130803Smarcel -target_width, target_width, target_shortname); 161130803Smarcel strcat_to_buf (string, status_size, buf); 162130803Smarcel } 163130803Smarcel if (pid_width > 0) 164130803Smarcel { 165130803Smarcel sprintf (buf, "%*.*s ", 166130803Smarcel -pid_width, pid_width, pid_name); 167130803Smarcel strcat_to_buf (string, status_size, buf); 168130803Smarcel } 169130803Smarcel 170130803Smarcel /* Show whether we are in SingleKey mode. */ 171130803Smarcel if (tui_current_key_mode == TUI_SINGLE_KEY_MODE) 172130803Smarcel { 173130803Smarcel strcat_to_buf (string, status_size, SINGLE_KEY); 174130803Smarcel strcat_to_buf (string, status_size, " "); 175130803Smarcel } 176130803Smarcel 177130803Smarcel /* procedure/class name */ 178130803Smarcel if (proc_width > 0) 179130803Smarcel { 180130803Smarcel if (strlen (pname) > proc_width) 181130803Smarcel sprintf (buf, "%s%*.*s* ", PROC_PREFIX, 182130803Smarcel 1 - proc_width, proc_width - 1, pname); 183130803Smarcel else 184130803Smarcel sprintf (buf, "%s%*.*s ", PROC_PREFIX, 185130803Smarcel -proc_width, proc_width, pname); 186130803Smarcel strcat_to_buf (string, status_size, buf); 187130803Smarcel } 188130803Smarcel 189130803Smarcel if (line_width > 0) 190130803Smarcel { 191130803Smarcel sprintf (buf, "%s%*.*s ", LINE_PREFIX, 192130803Smarcel -line_width, line_width, line_buf); 193130803Smarcel strcat_to_buf (string, status_size, buf); 194130803Smarcel } 195130803Smarcel if (pc_width > 0) 196130803Smarcel { 197130803Smarcel strcat_to_buf (string, status_size, PC_PREFIX); 198130803Smarcel strcat_to_buf (string, status_size, pc_buf); 199130803Smarcel } 200130803Smarcel 201130803Smarcel 202130803Smarcel for (i = strlen (string); i < status_size; i++) 203130803Smarcel string[i] = ' '; 204130803Smarcel string[status_size] = (char) 0; 205130803Smarcel 206130803Smarcel ui_file_delete (pc_out); 207130803Smarcel return string; 208130803Smarcel} 209130803Smarcel 210130803Smarcel/* Get a printable name for the function at the address. 211130803Smarcel The symbol name is demangled if demangling is turned on. 212130803Smarcel Returns a pointer to a static area holding the result. */ 213130803Smarcelstatic char* 214130803Smarceltui_get_function_from_frame (struct frame_info *fi) 215130803Smarcel{ 216130803Smarcel static char name[256]; 217130803Smarcel struct ui_file *stream = tui_sfileopen (256); 218130803Smarcel char *p; 219130803Smarcel 220130803Smarcel print_address_symbolic (get_frame_pc (fi), stream, demangle, ""); 221130803Smarcel p = tui_file_get_strbuf (stream); 222130803Smarcel 223130803Smarcel /* Use simple heuristics to isolate the function name. The symbol can 224130803Smarcel be demangled and we can have function parameters. Remove them because 225130803Smarcel the status line is too short to display them. */ 226130803Smarcel if (*p == '<') 227130803Smarcel p++; 228130803Smarcel strncpy (name, p, sizeof (name)); 229130803Smarcel p = strchr (name, '('); 230130803Smarcel if (!p) 231130803Smarcel p = strchr (name, '>'); 232130803Smarcel if (p) 233130803Smarcel *p = 0; 234130803Smarcel p = strchr (name, '+'); 235130803Smarcel if (p) 236130803Smarcel *p = 0; 237130803Smarcel ui_file_delete (stream); 238130803Smarcel return name; 239130803Smarcel} 240130803Smarcel 241130803Smarcelvoid 242130803Smarceltui_show_locator_content (void) 243130803Smarcel{ 244130803Smarcel char *string; 245130803Smarcel struct tui_gen_win_info * locator; 246130803Smarcel 247130803Smarcel locator = tui_locator_win_info_ptr (); 248130803Smarcel 249130803Smarcel if (locator != NULL && locator->handle != (WINDOW *) NULL) 250130803Smarcel { 251130803Smarcel struct tui_win_element * element; 252130803Smarcel 253130803Smarcel element = (struct tui_win_element *) locator->content[0]; 254130803Smarcel 255130803Smarcel string = tui_make_status_line (&element->which_element.locator); 256130803Smarcel wmove (locator->handle, 0, 0); 257130803Smarcel wstandout (locator->handle); 258130803Smarcel waddstr (locator->handle, string); 259130803Smarcel wclrtoeol (locator->handle); 260130803Smarcel wstandend (locator->handle); 261130803Smarcel tui_refresh_win (locator); 262130803Smarcel wmove (locator->handle, 0, 0); 263130803Smarcel xfree (string); 264130803Smarcel locator->content_in_use = TRUE; 265130803Smarcel } 266130803Smarcel} 267130803Smarcel 268130803Smarcel 269130803Smarcel/* Set the filename portion of the locator. */ 270130803Smarcelstatic void 271130803Smarceltui_set_locator_filename (const char *filename) 272130803Smarcel{ 273130803Smarcel struct tui_gen_win_info * locator = tui_locator_win_info_ptr (); 274130803Smarcel struct tui_locator_element * element; 275130803Smarcel 276130803Smarcel if (locator->content[0] == NULL) 277130803Smarcel { 278130803Smarcel tui_set_locator_info (filename, NULL, 0, 0); 279130803Smarcel return; 280130803Smarcel } 281130803Smarcel 282130803Smarcel element = &((struct tui_win_element *) locator->content[0])->which_element.locator; 283130803Smarcel element->file_name[0] = 0; 284130803Smarcel strcat_to_buf (element->file_name, MAX_LOCATOR_ELEMENT_LEN, filename); 285130803Smarcel} 286130803Smarcel 287130803Smarcel/* Update the locator, with the provided arguments. */ 288130803Smarcelstatic void 289130803Smarceltui_set_locator_info (const char *filename, const char *procname, int lineno, 290130803Smarcel CORE_ADDR addr) 291130803Smarcel{ 292130803Smarcel struct tui_gen_win_info * locator = tui_locator_win_info_ptr (); 293130803Smarcel struct tui_locator_element * element; 294130803Smarcel 295130803Smarcel /* Allocate the locator content if necessary. */ 296130803Smarcel if (locator->content_size <= 0) 297130803Smarcel { 298130803Smarcel locator->content = (void **) tui_alloc_content (1, locator->type); 299130803Smarcel locator->content_size = 1; 300130803Smarcel } 301130803Smarcel 302130803Smarcel element = &((struct tui_win_element *) locator->content[0])->which_element.locator; 303130803Smarcel element->proc_name[0] = (char) 0; 304130803Smarcel strcat_to_buf (element->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname); 305130803Smarcel element->line_no = lineno; 306130803Smarcel element->addr = addr; 307130803Smarcel tui_set_locator_filename (filename); 308130803Smarcel} 309130803Smarcel 310130803Smarcel/* Update only the filename portion of the locator. */ 311130803Smarcelvoid 312130803Smarceltui_update_locator_filename (const char *filename) 313130803Smarcel{ 314130803Smarcel tui_set_locator_filename (filename); 315130803Smarcel tui_show_locator_content (); 316130803Smarcel} 317130803Smarcel 318130803Smarcel/* Function to print the frame information for the TUI. */ 319130803Smarcelvoid 320130803Smarceltui_show_frame_info (struct frame_info *fi) 321130803Smarcel{ 322130803Smarcel struct tui_win_info * win_info; 323130803Smarcel int i; 324130803Smarcel 325130803Smarcel if (fi) 326130803Smarcel { 327130803Smarcel int start_line, i; 328130803Smarcel CORE_ADDR low; 329130803Smarcel struct tui_gen_win_info * locator = tui_locator_win_info_ptr (); 330130803Smarcel int source_already_displayed; 331130803Smarcel struct symtab_and_line sal; 332130803Smarcel 333130803Smarcel find_frame_sal (fi, &sal); 334130803Smarcel 335130803Smarcel source_already_displayed = sal.symtab != 0 336130803Smarcel && tui_source_is_displayed (sal.symtab->filename); 337130803Smarcel tui_set_locator_info (sal.symtab == 0 ? "??" : sal.symtab->filename, 338130803Smarcel tui_get_function_from_frame (fi), 339130803Smarcel sal.line, 340130803Smarcel get_frame_pc (fi)); 341130803Smarcel tui_show_locator_content (); 342130803Smarcel start_line = 0; 343130803Smarcel for (i = 0; i < (tui_source_windows ())->count; i++) 344130803Smarcel { 345130803Smarcel union tui_which_element *item; 346130803Smarcel win_info = (struct tui_win_info *) (tui_source_windows ())->list[i]; 347130803Smarcel 348130803Smarcel item = &((struct tui_win_element *) locator->content[0])->which_element; 349130803Smarcel if (win_info == TUI_SRC_WIN) 350130803Smarcel { 351130803Smarcel start_line = (item->locator.line_no - 352130803Smarcel (win_info->generic.viewport_height / 2)) + 1; 353130803Smarcel if (start_line <= 0) 354130803Smarcel start_line = 1; 355130803Smarcel } 356130803Smarcel else 357130803Smarcel { 358130803Smarcel if (find_pc_partial_function (get_frame_pc (fi), (char **) NULL, 359130803Smarcel &low, (CORE_ADDR) NULL) == 0) 360130803Smarcel error ("No function contains program counter for selected frame.\n"); 361130803Smarcel else 362130803Smarcel low = tui_get_low_disassembly_address (low, get_frame_pc (fi)); 363130803Smarcel } 364130803Smarcel 365130803Smarcel if (win_info == TUI_SRC_WIN) 366130803Smarcel { 367130803Smarcel union tui_line_or_address l; 368130803Smarcel l.line_no = start_line; 369130803Smarcel if (!(source_already_displayed 370130803Smarcel && tui_line_is_displayed (item->locator.line_no, win_info, TRUE))) 371130803Smarcel tui_update_source_window (win_info, sal.symtab, l, TRUE); 372130803Smarcel else 373130803Smarcel { 374130803Smarcel l.line_no = item->locator.line_no; 375130803Smarcel tui_set_is_exec_point_at (l, win_info); 376130803Smarcel } 377130803Smarcel } 378130803Smarcel else 379130803Smarcel { 380130803Smarcel if (win_info == TUI_DISASM_WIN) 381130803Smarcel { 382130803Smarcel union tui_line_or_address a; 383130803Smarcel a.addr = low; 384130803Smarcel if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE)) 385130803Smarcel tui_update_source_window (win_info, sal.symtab, a, TRUE); 386130803Smarcel else 387130803Smarcel { 388130803Smarcel a.addr = item->locator.addr; 389130803Smarcel tui_set_is_exec_point_at (a, win_info); 390130803Smarcel } 391130803Smarcel } 392130803Smarcel } 393130803Smarcel tui_update_exec_info (win_info); 394130803Smarcel } 395130803Smarcel } 396130803Smarcel else 397130803Smarcel { 398130803Smarcel tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0); 399130803Smarcel tui_show_locator_content (); 400130803Smarcel for (i = 0; i < (tui_source_windows ())->count; i++) 401130803Smarcel { 402130803Smarcel win_info = (struct tui_win_info *) (tui_source_windows ())->list[i]; 403130803Smarcel tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT); 404130803Smarcel tui_update_exec_info (win_info); 405130803Smarcel } 406130803Smarcel } 407130803Smarcel} 408130803Smarcel 409130803Smarcel/* Function to initialize gdb commands, for tui window stack 410130803Smarcel manipulation. */ 411130803Smarcelvoid 412130803Smarcel_initialize_tui_stack (void) 413130803Smarcel{ 414130803Smarcel add_com ("update", class_tui, tui_update_command, 415130803Smarcel "Update the source window and locator to display the current " 416130803Smarcel "execution point.\n"); 417130803Smarcel} 418130803Smarcel 419130803Smarcel/* Command to update the display with the current execution point. */ 420130803Smarcelstatic void 421130803Smarceltui_update_command (char *arg, int from_tty) 422130803Smarcel{ 423130803Smarcel char cmd[sizeof("frame 0")]; 424130803Smarcel 425130803Smarcel strcpy (cmd, "frame 0"); 426130803Smarcel execute_command (cmd, from_tty); 427130803Smarcel} 428