GDB (API)
/home/stan/gdb/src/gdb/tui/tui-stack.c
Go to the documentation of this file.
00001 /* TUI display locator.
00002 
00003    Copyright (C) 1998-2013 Free Software Foundation, Inc.
00004 
00005    Contributed by Hewlett-Packard Company.
00006 
00007    This file is part of GDB.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 3 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00021 
00022 #include "defs.h"
00023 #include "symtab.h"
00024 #include "breakpoint.h"
00025 #include "frame.h"
00026 #include "command.h"
00027 #include "inferior.h"
00028 #include "target.h"
00029 #include "top.h"
00030 #include "gdb-demangle.h"
00031 #include "gdb_string.h"
00032 #include "source.h"
00033 #include "tui/tui.h"
00034 #include "tui/tui-data.h"
00035 #include "tui/tui-stack.h"
00036 #include "tui/tui-wingeneral.h"
00037 #include "tui/tui-source.h"
00038 #include "tui/tui-winsource.h"
00039 #include "tui/tui-file.h"
00040 
00041 #include "gdb_curses.h"
00042 
00043 /* Get a printable name for the function at the address.
00044    The symbol name is demangled if demangling is turned on.
00045    Returns a pointer to a static area holding the result.  */
00046 static char *tui_get_function_from_frame (struct frame_info *fi);
00047 
00048 /* Set the full_name portion of the locator.  */
00049 static void tui_set_locator_fullname (const char *fullname);
00050 
00051 /* Update the locator, with the provided arguments.  */
00052 static void tui_set_locator_info (struct gdbarch *gdbarch,
00053                                   const char *fullname,
00054                                   const char *procname,
00055                                   int lineno, CORE_ADDR addr);
00056 
00057 static void tui_update_command (char *, int);
00058 
00059 
00060 /* Create the status line to display as much information as we can on
00061    this single line: target name, process number, current function,
00062    current line, current PC, SingleKey mode.  */
00063 static char*
00064 tui_make_status_line (struct tui_locator_element *loc)
00065 {
00066   char *string;
00067   char line_buf[50], *pname;
00068   char *buf;
00069   int status_size;
00070   int i, proc_width;
00071   const char *pid_name;
00072   const char *pc_buf;
00073   int target_width;
00074   int pid_width;
00075   int line_width;
00076   int pc_width;
00077   struct ui_file *pc_out;
00078 
00079   if (ptid_equal (inferior_ptid, null_ptid))
00080     pid_name = "No process";
00081   else
00082     pid_name = target_pid_to_str (inferior_ptid);
00083 
00084   target_width = strlen (target_shortname);
00085   if (target_width > MAX_TARGET_WIDTH)
00086     target_width = MAX_TARGET_WIDTH;
00087 
00088   pid_width = strlen (pid_name);
00089   if (pid_width > MAX_PID_WIDTH)
00090     pid_width = MAX_PID_WIDTH;
00091 
00092   status_size = tui_term_width ();
00093   string = (char *) xmalloc (status_size + 1);
00094   buf = (char*) alloca (status_size + 1);
00095 
00096   /* Translate line number and obtain its size.  */
00097   if (loc->line_no > 0)
00098     xsnprintf (line_buf, sizeof (line_buf), "%d", loc->line_no);
00099   else
00100     strcpy (line_buf, "??");
00101   line_width = strlen (line_buf);
00102   if (line_width < MIN_LINE_WIDTH)
00103     line_width = MIN_LINE_WIDTH;
00104 
00105   /* Translate PC address.  */
00106   pc_out = tui_sfileopen (128);
00107   fputs_filtered (loc->gdbarch? paddress (loc->gdbarch, loc->addr) : "??",
00108                   pc_out);
00109   pc_buf = tui_file_get_strbuf (pc_out);
00110   pc_width = strlen (pc_buf);
00111   
00112   /* First determine the amount of proc name width we have available.
00113      The +1 are for a space separator between fields.
00114      The -1 are to take into account the \0 counted by sizeof.  */
00115   proc_width = (status_size
00116                 - (target_width + 1)
00117                 - (pid_width + 1)
00118                 - (sizeof (PROC_PREFIX) - 1 + 1)
00119                 - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
00120                 - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
00121                 - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
00122                    ? (sizeof (SINGLE_KEY) - 1 + 1)
00123                    : 0));
00124 
00125   /* If there is no room to print the function name, try by removing
00126      some fields.  */
00127   if (proc_width < MIN_PROC_WIDTH)
00128     {
00129       proc_width += target_width + 1;
00130       target_width = 0;
00131       if (proc_width < MIN_PROC_WIDTH)
00132         {
00133           proc_width += pid_width + 1;
00134           pid_width = 0;
00135           if (proc_width <= MIN_PROC_WIDTH)
00136             {
00137               proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
00138               pc_width = 0;
00139               if (proc_width < 0)
00140                 {
00141                   proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
00142                   line_width = 0;
00143                   if (proc_width < 0)
00144                     proc_width = 0;
00145                 }
00146             }
00147         }
00148     }
00149 
00150   /* Now convert elements to string form.  */
00151   pname = loc->proc_name;
00152 
00153   /* Now create the locator line from the string version of the
00154      elements.  We could use sprintf() here but that wouldn't ensure
00155      that we don't overrun the size of the allocated buffer.
00156      strcat_to_buf() will.  */
00157   *string = (char) 0;
00158 
00159   if (target_width > 0)
00160     {
00161       sprintf (buf, "%*.*s ",
00162                -target_width, target_width, target_shortname);
00163       strcat_to_buf (string, status_size, buf);
00164     }
00165   if (pid_width > 0)
00166     {
00167       sprintf (buf, "%*.*s ",
00168                -pid_width, pid_width, pid_name);
00169       strcat_to_buf (string, status_size, buf);
00170     }
00171   
00172   /* Show whether we are in SingleKey mode.  */
00173   if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
00174     {
00175       strcat_to_buf (string, status_size, SINGLE_KEY);
00176       strcat_to_buf (string, status_size, " ");
00177     }
00178 
00179   /* Procedure/class name.  */
00180   if (proc_width > 0)
00181     {
00182       if (strlen (pname) > proc_width)
00183         sprintf (buf, "%s%*.*s* ", PROC_PREFIX,
00184                  1 - proc_width, proc_width - 1, pname);
00185       else
00186         sprintf (buf, "%s%*.*s ", PROC_PREFIX,
00187                  -proc_width, proc_width, pname);
00188       strcat_to_buf (string, status_size, buf);
00189     }
00190 
00191   if (line_width > 0)
00192     {
00193       sprintf (buf, "%s%*.*s ", LINE_PREFIX,
00194                -line_width, line_width, line_buf);
00195       strcat_to_buf (string, status_size, buf);
00196     }
00197   if (pc_width > 0)
00198     {
00199       strcat_to_buf (string, status_size, PC_PREFIX);
00200       strcat_to_buf (string, status_size, pc_buf);
00201     }
00202   
00203   
00204   for (i = strlen (string); i < status_size; i++)
00205     string[i] = ' ';
00206   string[status_size] = (char) 0;
00207 
00208   ui_file_delete (pc_out);
00209   return string;
00210 }
00211 
00212 /* Get a printable name for the function at the address.  The symbol
00213    name is demangled if demangling is turned on.  Returns a pointer to
00214    a static area holding the result.  */
00215 static char*
00216 tui_get_function_from_frame (struct frame_info *fi)
00217 {
00218   static char name[256];
00219   struct ui_file *stream = tui_sfileopen (256);
00220   char *p;
00221 
00222   print_address_symbolic (get_frame_arch (fi), get_frame_pc (fi),
00223                           stream, demangle, "");
00224   p = tui_file_get_strbuf (stream);
00225 
00226   /* Use simple heuristics to isolate the function name.  The symbol
00227      can be demangled and we can have function parameters.  Remove
00228      them because the status line is too short to display them.  */
00229   if (*p == '<')
00230     p++;
00231   strncpy (name, p, sizeof (name) - 1);
00232   name[sizeof (name) - 1] = 0;
00233   p = strchr (name, '(');
00234   if (!p)
00235     p = strchr (name, '>');
00236   if (p)
00237     *p = 0;
00238   p = strchr (name, '+');
00239   if (p)
00240     *p = 0;
00241   ui_file_delete (stream);
00242   return name;
00243 }
00244 
00245 void
00246 tui_show_locator_content (void)
00247 {
00248   char *string;
00249   struct tui_gen_win_info *locator;
00250 
00251   locator = tui_locator_win_info_ptr ();
00252 
00253   if (locator != NULL && locator->handle != (WINDOW *) NULL)
00254     {
00255       struct tui_win_element *element;
00256 
00257       element = (struct tui_win_element *) locator->content[0];
00258 
00259       string = tui_make_status_line (&element->which_element.locator);
00260       wmove (locator->handle, 0, 0);
00261       /* We ignore the return value from wstandout and wstandend, casting
00262          them to void in order to avoid a compiler warning.  The warning
00263          itself was introduced by a patch to ncurses 5.7 dated 2009-08-29,
00264          changing these macro to expand to code that causes the compiler
00265          to generate an unused-value warning.  */
00266       (void) wstandout (locator->handle);
00267       waddstr (locator->handle, string);
00268       wclrtoeol (locator->handle);
00269       (void) wstandend (locator->handle);
00270       tui_refresh_win (locator);
00271       wmove (locator->handle, 0, 0);
00272       xfree (string);
00273       locator->content_in_use = TRUE;
00274     }
00275 }
00276 
00277 
00278 /* Set the filename portion of the locator.  */
00279 static void
00280 tui_set_locator_fullname (const char *fullname)
00281 {
00282   struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
00283   struct tui_locator_element *element;
00284 
00285   if (locator->content[0] == NULL)
00286     {
00287       tui_set_locator_info (NULL, fullname, NULL, 0, 0);
00288       return;
00289     }
00290 
00291   element = &((struct tui_win_element *)
00292               locator->content[0])->which_element.locator;
00293   element->full_name[0] = 0;
00294   strcat_to_buf (element->full_name, MAX_LOCATOR_ELEMENT_LEN, fullname);
00295 }
00296 
00297 /* Update the locator, with the provided arguments.  */
00298 static void
00299 tui_set_locator_info (struct gdbarch *gdbarch,
00300                       const char *fullname,
00301                       const char *procname, 
00302                       int lineno,
00303                       CORE_ADDR addr)
00304 {
00305   struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
00306   struct tui_locator_element *element;
00307 
00308   /* Allocate the locator content if necessary.  */
00309   if (locator->content_size <= 0)
00310     {
00311       locator->content = (void **) tui_alloc_content (1, locator->type);
00312       locator->content_size = 1;
00313     }
00314 
00315   element = &((struct tui_win_element *)
00316               locator->content[0])->which_element.locator;
00317   element->proc_name[0] = (char) 0;
00318   strcat_to_buf (element->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname);
00319   element->line_no = lineno;
00320   element->addr = addr;
00321   element->gdbarch = gdbarch;
00322   tui_set_locator_fullname (fullname);
00323 }
00324 
00325 /* Update only the full_name portion of the locator.  */
00326 void
00327 tui_update_locator_fullname (const char *fullname)
00328 {
00329   tui_set_locator_fullname (fullname);
00330   tui_show_locator_content ();
00331 }
00332 
00333 /* Function to print the frame information for the TUI.  */
00334 void
00335 tui_show_frame_info (struct frame_info *fi)
00336 {
00337   struct tui_win_info *win_info;
00338   int i;
00339 
00340   if (fi)
00341     {
00342       int start_line, i;
00343       CORE_ADDR low;
00344       struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
00345       int source_already_displayed;
00346       struct symtab_and_line sal;
00347       CORE_ADDR pc;
00348 
00349       find_frame_sal (fi, &sal);
00350 
00351       source_already_displayed = sal.symtab != 0
00352         && tui_source_is_displayed (symtab_to_fullname (sal.symtab));
00353 
00354       if (get_frame_pc_if_available (fi, &pc))
00355         tui_set_locator_info (get_frame_arch (fi),
00356                               (sal.symtab == 0
00357                                ? "??" : symtab_to_fullname (sal.symtab)),
00358                               tui_get_function_from_frame (fi),
00359                               sal.line,
00360                               pc);
00361       else
00362         tui_set_locator_info (get_frame_arch (fi),
00363                               "??", _("<unavailable>"), sal.line, 0);
00364 
00365       tui_show_locator_content ();
00366       start_line = 0;
00367       for (i = 0; i < (tui_source_windows ())->count; i++)
00368         {
00369           union tui_which_element *item;
00370 
00371           win_info = (tui_source_windows ())->list[i];
00372 
00373           item = &((struct tui_win_element *)
00374                    locator->content[0])->which_element;
00375           if (win_info == TUI_SRC_WIN)
00376             {
00377               start_line = (item->locator.line_no -
00378                            (win_info->generic.viewport_height / 2)) + 1;
00379               if (start_line <= 0)
00380                 start_line = 1;
00381             }
00382           else
00383             {
00384               if (find_pc_partial_function (get_frame_pc (fi),
00385                                             (const char **) NULL,
00386                                             &low, (CORE_ADDR) 0) == 0)
00387                 {
00388                   /* There is no symbol available for current PC.  There is no
00389                      safe way how to "disassemble backwards".  */
00390                   low = get_frame_pc (fi);
00391                 }
00392               else
00393                 low = tui_get_low_disassembly_address (get_frame_arch (fi),
00394                                                        low, get_frame_pc (fi));
00395             }
00396 
00397           if (win_info == TUI_SRC_WIN)
00398             {
00399               struct tui_line_or_address l;
00400 
00401               l.loa = LOA_LINE;
00402               l.u.line_no = start_line;
00403               if (!(source_already_displayed
00404                     && tui_line_is_displayed (item->locator.line_no,
00405                                               win_info, TRUE)))
00406                 tui_update_source_window (win_info, get_frame_arch (fi),
00407                                           sal.symtab, l, TRUE);
00408               else
00409                 {
00410                   l.u.line_no = item->locator.line_no;
00411                   tui_set_is_exec_point_at (l, win_info);
00412                 }
00413             }
00414           else
00415             {
00416               if (win_info == TUI_DISASM_WIN)
00417                 {
00418                   struct tui_line_or_address a;
00419 
00420                   a.loa = LOA_ADDRESS;
00421                   a.u.addr = low;
00422                   if (!tui_addr_is_displayed (item->locator.addr,
00423                                               win_info, TRUE))
00424                     tui_update_source_window (win_info, get_frame_arch (fi),
00425                                               sal.symtab, a, TRUE);
00426                   else
00427                     {
00428                       a.u.addr = item->locator.addr;
00429                       tui_set_is_exec_point_at (a, win_info);
00430                     }
00431                 }
00432             }
00433           tui_update_exec_info (win_info);
00434         }
00435     }
00436   else
00437     {
00438       tui_set_locator_info (NULL, NULL, NULL, 0, (CORE_ADDR) 0);
00439       tui_show_locator_content ();
00440       for (i = 0; i < (tui_source_windows ())->count; i++)
00441         {
00442           win_info = (tui_source_windows ())->list[i];
00443           tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
00444           tui_update_exec_info (win_info);
00445         }
00446     }
00447 }
00448 
00449 /* Function to initialize gdb commands, for tui window stack
00450    manipulation.  */
00451 
00452 /* Provide a prototype to silence -Wmissing-prototypes.  */
00453 extern initialize_file_ftype _initialize_tui_stack;
00454 
00455 void
00456 _initialize_tui_stack (void)
00457 {
00458   add_com ("update", class_tui, tui_update_command,
00459            _("Update the source window and locator to "
00460              "display the current execution point.\n"));
00461 }
00462 
00463 /* Command to update the display with the current execution point.  */
00464 static void
00465 tui_update_command (char *arg, int from_tty)
00466 {
00467   char cmd[sizeof("frame 0")];
00468 
00469   strcpy (cmd, "frame 0");
00470   execute_command (cmd, from_tty);
00471 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines