]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/gdb/gdb/tui/tui-stack.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / gdb / gdb / tui / tui-stack.c
1 /* TUI display locator.
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 "symtab.h"
27 #include "breakpoint.h"
28 #include "frame.h"
29 #include "command.h"
30 #include "inferior.h"
31 #include "target.h"
32 #include "top.h"
33 #include "gdb_string.h"
34 #include "tui/tui.h"
35 #include "tui/tui-data.h"
36 #include "tui/tui-stack.h"
37 #include "tui/tui-wingeneral.h"
38 #include "tui/tui-source.h"
39 #include "tui/tui-winsource.h"
40 #include "tui/tui-file.h"
41
42 #include "gdb_curses.h"
43
44 /* Get a printable name for the function at the address.
45    The symbol name is demangled if demangling is turned on.
46    Returns a pointer to a static area holding the result.  */
47 static char* tui_get_function_from_frame (struct frame_info *fi);
48
49 /* Set the filename portion of the locator.  */
50 static void tui_set_locator_filename (const char *filename);
51
52 /* Update the locator, with the provided arguments.  */
53 static void tui_set_locator_info (const char *filename, const char *procname,
54                                   int lineno, CORE_ADDR addr);
55
56 static void tui_update_command (char *, int);
57 \f
58
59 /* Create the status line to display as much information as we
60    can on this single line: target name, process number, current
61    function, current line, current PC, SingleKey mode.  */
62 static char*
63 tui_make_status_line (struct tui_locator_element* loc)
64 {
65   char* string;
66   char line_buf[50], *pname;
67   char* buf;
68   int status_size;
69   int i, proc_width;
70   const char* pid_name;
71   const char* pc_buf;
72   int target_width;
73   int pid_width;
74   int line_width;
75   int pc_width;
76   struct ui_file *pc_out;
77
78   if (ptid_equal (inferior_ptid, null_ptid))
79     pid_name = "No process";
80   else
81     pid_name = target_pid_to_str (inferior_ptid);
82
83   target_width = strlen (target_shortname);
84   if (target_width > MAX_TARGET_WIDTH)
85     target_width = MAX_TARGET_WIDTH;
86
87   pid_width = strlen (pid_name);
88   if (pid_width > MAX_PID_WIDTH)
89     pid_width = MAX_PID_WIDTH;
90
91   status_size = tui_term_width ();
92   string = (char *) xmalloc (status_size + 1);
93   buf = (char*) alloca (status_size + 1);
94
95   /* Translate line number and obtain its size.  */
96   if (loc->line_no > 0)
97     sprintf (line_buf, "%d", loc->line_no);
98   else
99     strcpy (line_buf, "??");
100   line_width = strlen (line_buf);
101   if (line_width < MIN_LINE_WIDTH)
102     line_width = MIN_LINE_WIDTH;
103
104   /* Translate PC address.  */
105   pc_out = tui_sfileopen (128);
106   print_address_numeric (loc->addr, 1, pc_out);
107   pc_buf = tui_file_get_strbuf (pc_out);
108   pc_width = strlen (pc_buf);
109   
110   /* First determine the amount of proc name width we have available.
111      The +1 are for a space separator between fields.
112      The -1 are to take into account the \0 counted by sizeof.  */
113   proc_width = (status_size
114                 - (target_width + 1)
115                 - (pid_width + 1)
116                 - (sizeof (PROC_PREFIX) - 1 + 1)
117                 - (sizeof (LINE_PREFIX) - 1 + line_width + 1)
118                 - (sizeof (PC_PREFIX) - 1 + pc_width + 1)
119                 - (tui_current_key_mode == TUI_SINGLE_KEY_MODE
120                    ? (sizeof (SINGLE_KEY) - 1 + 1)
121                    : 0));
122
123   /* If there is no room to print the function name, try by removing
124      some fields.  */
125   if (proc_width < MIN_PROC_WIDTH)
126     {
127       proc_width += target_width + 1;
128       target_width = 0;
129       if (proc_width < MIN_PROC_WIDTH)
130         {
131           proc_width += pid_width + 1;
132           pid_width = 0;
133           if (proc_width <= MIN_PROC_WIDTH)
134             {
135               proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1;
136               pc_width = 0;
137               if (proc_width < 0)
138                 {
139                   proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1;
140                   line_width = 0;
141                   if (proc_width < 0)
142                     proc_width = 0;
143                 }
144             }
145         }
146     }
147
148   /* Now convert elements to string form */
149   pname = loc->proc_name;
150
151   /* Now create the locator line from the string version
152      of the elements.  We could use sprintf() here but
153      that wouldn't ensure that we don't overrun the size
154      of the allocated buffer.  strcat_to_buf() will.  */
155   *string = (char) 0;
156
157   if (target_width > 0)
158     {
159       sprintf (buf, "%*.*s ",
160                -target_width, target_width, target_shortname);
161       strcat_to_buf (string, status_size, buf);
162     }
163   if (pid_width > 0)
164     {
165       sprintf (buf, "%*.*s ",
166                -pid_width, pid_width, pid_name);
167       strcat_to_buf (string, status_size, buf);
168     }
169   
170   /* Show whether we are in SingleKey mode.  */
171   if (tui_current_key_mode == TUI_SINGLE_KEY_MODE)
172     {
173       strcat_to_buf (string, status_size, SINGLE_KEY);
174       strcat_to_buf (string, status_size, " ");
175     }
176
177   /* procedure/class name */
178   if (proc_width > 0)
179     {
180       if (strlen (pname) > proc_width)
181         sprintf (buf, "%s%*.*s* ", PROC_PREFIX,
182                  1 - proc_width, proc_width - 1, pname);
183       else
184         sprintf (buf, "%s%*.*s ", PROC_PREFIX,
185                  -proc_width, proc_width, pname);
186       strcat_to_buf (string, status_size, buf);
187     }
188
189   if (line_width > 0)
190     {
191       sprintf (buf, "%s%*.*s ", LINE_PREFIX,
192                -line_width, line_width, line_buf);
193       strcat_to_buf (string, status_size, buf);
194     }
195   if (pc_width > 0)
196     {
197       strcat_to_buf (string, status_size, PC_PREFIX);
198       strcat_to_buf (string, status_size, pc_buf);
199     }
200   
201   
202   for (i = strlen (string); i < status_size; i++)
203     string[i] = ' ';
204   string[status_size] = (char) 0;
205
206   ui_file_delete (pc_out);
207   return string;
208 }
209
210 /* Get a printable name for the function at the address.
211    The symbol name is demangled if demangling is turned on.
212    Returns a pointer to a static area holding the result.  */
213 static char*
214 tui_get_function_from_frame (struct frame_info *fi)
215 {
216   static char name[256];
217   struct ui_file *stream = tui_sfileopen (256);
218   char *p;
219
220   print_address_symbolic (get_frame_pc (fi), stream, demangle, "");
221   p = tui_file_get_strbuf (stream);
222
223   /* Use simple heuristics to isolate the function name.  The symbol can
224      be demangled and we can have function parameters.  Remove them because
225      the status line is too short to display them.  */
226   if (*p == '<')
227     p++;
228   strncpy (name, p, sizeof (name));
229   p = strchr (name, '(');
230   if (!p)
231     p = strchr (name, '>');
232   if (p)
233     *p = 0;
234   p = strchr (name, '+');
235   if (p)
236     *p = 0;
237   ui_file_delete (stream);
238   return name;
239 }
240
241 void
242 tui_show_locator_content (void)
243 {
244   char *string;
245   struct tui_gen_win_info * locator;
246
247   locator = tui_locator_win_info_ptr ();
248
249   if (locator != NULL && locator->handle != (WINDOW *) NULL)
250     {
251       struct tui_win_element * element;
252
253       element = (struct tui_win_element *) locator->content[0];
254
255       string = tui_make_status_line (&element->which_element.locator);
256       wmove (locator->handle, 0, 0);
257       wstandout (locator->handle);
258       waddstr (locator->handle, string);
259       wclrtoeol (locator->handle);
260       wstandend (locator->handle);
261       tui_refresh_win (locator);
262       wmove (locator->handle, 0, 0);
263       xfree (string);
264       locator->content_in_use = TRUE;
265     }
266 }
267
268
269 /* Set the filename portion of the locator.  */
270 static void
271 tui_set_locator_filename (const char *filename)
272 {
273   struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
274   struct tui_locator_element * element;
275
276   if (locator->content[0] == NULL)
277     {
278       tui_set_locator_info (filename, NULL, 0, 0);
279       return;
280     }
281
282   element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
283   element->file_name[0] = 0;
284   strcat_to_buf (element->file_name, MAX_LOCATOR_ELEMENT_LEN, filename);
285 }
286
287 /* Update the locator, with the provided arguments.  */
288 static void
289 tui_set_locator_info (const char *filename, const char *procname, int lineno,
290                       CORE_ADDR addr)
291 {
292   struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
293   struct tui_locator_element * element;
294
295   /* Allocate the locator content if necessary.  */
296   if (locator->content_size <= 0)
297     {
298       locator->content = (void **) tui_alloc_content (1, locator->type);
299       locator->content_size = 1;
300     }
301
302   element = &((struct tui_win_element *) locator->content[0])->which_element.locator;
303   element->proc_name[0] = (char) 0;
304   strcat_to_buf (element->proc_name, MAX_LOCATOR_ELEMENT_LEN, procname);
305   element->line_no = lineno;
306   element->addr = addr;
307   tui_set_locator_filename (filename);
308 }
309
310 /* Update only the filename portion of the locator.  */
311 void
312 tui_update_locator_filename (const char *filename)
313 {
314   tui_set_locator_filename (filename);
315   tui_show_locator_content ();
316 }
317
318 /* Function to print the frame information for the TUI.  */
319 void
320 tui_show_frame_info (struct frame_info *fi)
321 {
322   struct tui_win_info * win_info;
323   int i;
324
325   if (fi)
326     {
327       int start_line, i;
328       CORE_ADDR low;
329       struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
330       int source_already_displayed;
331       struct symtab_and_line sal;
332
333       find_frame_sal (fi, &sal);
334
335       source_already_displayed = sal.symtab != 0
336         && tui_source_is_displayed (sal.symtab->filename);
337       tui_set_locator_info (sal.symtab == 0 ? "??" : sal.symtab->filename,
338                             tui_get_function_from_frame (fi),
339                             sal.line,
340                             get_frame_pc (fi));
341       tui_show_locator_content ();
342       start_line = 0;
343       for (i = 0; i < (tui_source_windows ())->count; i++)
344         {
345           union tui_which_element *item;
346           win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
347
348           item = &((struct tui_win_element *) locator->content[0])->which_element;
349           if (win_info == TUI_SRC_WIN)
350             {
351               start_line = (item->locator.line_no -
352                            (win_info->generic.viewport_height / 2)) + 1;
353               if (start_line <= 0)
354                 start_line = 1;
355             }
356           else
357             {
358               if (find_pc_partial_function (get_frame_pc (fi), (char **) NULL,
359                                             &low, (CORE_ADDR) NULL) == 0)
360                 error ("No function contains program counter for selected frame.\n");
361               else
362                 low = tui_get_low_disassembly_address (low, get_frame_pc (fi));
363             }
364
365           if (win_info == TUI_SRC_WIN)
366             {
367               union tui_line_or_address l;
368               l.line_no = start_line;
369               if (!(source_already_displayed
370                     && tui_line_is_displayed (item->locator.line_no, win_info, TRUE)))
371                 tui_update_source_window (win_info, sal.symtab, l, TRUE);
372               else
373                 {
374                   l.line_no = item->locator.line_no;
375                   tui_set_is_exec_point_at (l, win_info);
376                 }
377             }
378           else
379             {
380               if (win_info == TUI_DISASM_WIN)
381                 {
382                   union tui_line_or_address a;
383                   a.addr = low;
384                   if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE))
385                     tui_update_source_window (win_info, sal.symtab, a, TRUE);
386                   else
387                     {
388                       a.addr = item->locator.addr;
389                       tui_set_is_exec_point_at (a, win_info);
390                     }
391                 }
392             }
393           tui_update_exec_info (win_info);
394         }
395     }
396   else
397     {
398       tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0);
399       tui_show_locator_content ();
400       for (i = 0; i < (tui_source_windows ())->count; i++)
401         {
402           win_info = (struct tui_win_info *) (tui_source_windows ())->list[i];
403           tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
404           tui_update_exec_info (win_info);
405         }
406     }
407 }
408
409 /* Function to initialize gdb commands, for tui window stack
410    manipulation.  */
411 void
412 _initialize_tui_stack (void)
413 {
414   add_com ("update", class_tui, tui_update_command,
415            "Update the source window and locator to display the current "
416            "execution point.\n");
417 }
418
419 /* Command to update the display with the current execution point.  */
420 static void
421 tui_update_command (char *arg, int from_tty)
422 {
423   char cmd[sizeof("frame 0")];
424
425   strcpy (cmd, "frame 0");
426   execute_command (cmd, from_tty);
427 }