OSDN Git Service

* gdb.texinfo (Target Description Format): Add version attribute
[pf3gnuchains/pf3gnuchains4x.git] / gdb / tui / tui-stack.c
1 /* TUI display locator.
2
3    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
4    Free Software 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., 51 Franklin Street, Fifth Floor,
23    Boston, MA 02110-1301, 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   deprecated_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 = (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) 0) == 0)
360                 error (_("No function contains program counter for selected frame."));
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               struct tui_line_or_address l;
368               l.loa = LOA_LINE;
369               l.u.line_no = start_line;
370               if (!(source_already_displayed
371                     && tui_line_is_displayed (item->locator.line_no, win_info, TRUE)))
372                 tui_update_source_window (win_info, sal.symtab, l, TRUE);
373               else
374                 {
375                   l.u.line_no = item->locator.line_no;
376                   tui_set_is_exec_point_at (l, win_info);
377                 }
378             }
379           else
380             {
381               if (win_info == TUI_DISASM_WIN)
382                 {
383                   struct tui_line_or_address a;
384                   a.loa = LOA_ADDRESS;
385                   a.u.addr = low;
386                   if (!tui_addr_is_displayed (item->locator.addr, win_info, TRUE))
387                     tui_update_source_window (win_info, sal.symtab, a, TRUE);
388                   else
389                     {
390                       a.u.addr = item->locator.addr;
391                       tui_set_is_exec_point_at (a, win_info);
392                     }
393                 }
394             }
395           tui_update_exec_info (win_info);
396         }
397     }
398   else
399     {
400       tui_set_locator_info (NULL, NULL, 0, (CORE_ADDR) 0);
401       tui_show_locator_content ();
402       for (i = 0; i < (tui_source_windows ())->count; i++)
403         {
404           win_info = (tui_source_windows ())->list[i];
405           tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
406           tui_update_exec_info (win_info);
407         }
408     }
409 }
410
411 /* Function to initialize gdb commands, for tui window stack
412    manipulation.  */
413 void
414 _initialize_tui_stack (void)
415 {
416   add_com ("update", class_tui, tui_update_command, _("\
417 Update the source window and locator to display the current execution point.\n"));
418 }
419
420 /* Command to update the display with the current execution point.  */
421 static void
422 tui_update_command (char *arg, int from_tty)
423 {
424   char cmd[sizeof("frame 0")];
425
426   strcpy (cmd, "frame 0");
427   execute_command (cmd, from_tty);
428 }