1 /* TUI display source/assembly window.
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
6 Contributed by Hewlett-Packard Company.
8 This file is part of GDB.
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.
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.
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. */
25 /* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
26 "defs.h" should be included first. Unfortunatly some systems
27 (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
28 and they clash with "bfd.h"'s definiton of true/false. The correct
29 fix is to remove true/false from "bfd.h", however, until that
30 happens, hack around it by including "config.h" and <curses.h>
46 #include "breakpoint.h"
53 #include "tuiGeneralWin.h"
54 #include "tuiSourceWin.h"
55 #include "tuiSource.h"
56 #include "tuiDisassem.h"
59 /*****************************************
60 ** EXTERNAL FUNCTION DECLS **
61 ******************************************/
63 /*****************************************
64 ** EXTERNAL DATA DECLS **
65 ******************************************/
66 extern int current_source_line
;
67 extern struct symtab
*current_source_symtab
;
70 ** tuiDisplayMainFunction().
71 ** Function to display the "main" routine"
74 tuiDisplayMainFunction (void)
76 if ((sourceWindows ())->count
> 0)
80 addr
= parse_and_eval_address ("main");
81 if (addr
== (CORE_ADDR
) 0)
82 addr
= parse_and_eval_address ("MAIN");
83 if (addr
!= (CORE_ADDR
) 0)
85 struct symtab_and_line sal
;
87 tuiUpdateSourceWindowsWithAddr (addr
);
88 sal
= find_pc_line (addr
, 0);
89 tuiSwitchFilename (sal
.symtab
->filename
);
94 } /* tuiDisplayMainFunction */
99 ** tuiUpdateSourceWindow().
100 ** Function to display source in the source window. This function
101 ** initializes the horizontal scroll to 0.
104 tuiUpdateSourceWindow (TuiWinInfoPtr winInfo
, struct symtab
*s
,
105 TuiLineOrAddress lineOrAddr
, int noerror
)
107 winInfo
->detail
.sourceInfo
.horizontalOffset
= 0;
108 tuiUpdateSourceWindowAsIs (winInfo
, s
, lineOrAddr
, noerror
);
111 } /* tuiUpdateSourceWindow */
115 ** tuiUpdateSourceWindowAsIs().
116 ** Function to display source in the source/asm window. This
117 ** function shows the source as specified by the horizontal offset.
120 tuiUpdateSourceWindowAsIs (TuiWinInfoPtr winInfo
, struct symtab
*s
,
121 TuiLineOrAddress lineOrAddr
, int noerror
)
125 if (winInfo
->generic
.type
== SRC_WIN
)
126 ret
= tuiSetSourceContent (s
, lineOrAddr
.lineNo
, noerror
);
128 ret
= tuiSetDisassemContent (s
, lineOrAddr
.addr
);
130 if (ret
== TUI_FAILURE
)
132 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
133 tuiClearExecInfoContent (winInfo
);
137 tuiEraseSourceContent (winInfo
, NO_EMPTY_SOURCE_PROMPT
);
138 tuiShowSourceContent (winInfo
);
139 tuiUpdateExecInfo (winInfo
);
140 if (winInfo
->generic
.type
== SRC_WIN
)
142 current_source_line
= lineOrAddr
.lineNo
+
143 (winInfo
->generic
.contentSize
- 2);
144 current_source_symtab
= s
;
146 ** If the focus was in the asm win, put it in the src
147 ** win if we don't have a split layout
149 if (tuiWinWithFocus () == disassemWin
&&
150 currentLayout () != SRC_DISASSEM_COMMAND
)
151 tuiSetWinFocusTo (srcWin
);
157 } /* tuiUpdateSourceWindowAsIs */
161 ** tuiUpdateSourceWindowsWithAddr().
162 ** Function to ensure that the source and/or disassemly windows
163 ** reflect the input address.
166 tuiUpdateSourceWindowsWithAddr (CORE_ADDR addr
)
170 struct symtab_and_line sal
;
173 switch (currentLayout ())
175 case DISASSEM_COMMAND
:
176 case DISASSEM_DATA_COMMAND
:
177 tuiShowDisassem (addr
);
179 case SRC_DISASSEM_COMMAND
:
180 tuiShowDisassemAndUpdateSource (addr
);
183 sal
= find_pc_line (addr
, 0);
185 tuiShowSource (sal
.symtab
, l
, FALSE
);
193 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
195 TuiWinInfoPtr winInfo
= (TuiWinInfoPtr
) (sourceWindows ())->list
[i
];
197 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
198 tuiClearExecInfoContent (winInfo
);
203 } /* tuiUpdateSourceWindowsWithAddr */
206 ** tuiUpdateSourceWindowsWithLine().
207 ** Function to ensure that the source and/or disassemly windows
208 ** reflect the input address.
211 tuiUpdateSourceWindowsWithLine (struct symtab
*s
, int line
)
216 switch (currentLayout ())
218 case DISASSEM_COMMAND
:
219 case DISASSEM_DATA_COMMAND
:
220 find_line_pc (s
, line
, &pc
);
221 tuiUpdateSourceWindowsWithAddr (pc
);
225 tuiShowSource (s
, l
, FALSE
);
226 if (currentLayout () == SRC_DISASSEM_COMMAND
)
228 find_line_pc (s
, line
, &pc
);
229 tuiShowDisassem (pc
);
235 } /* tuiUpdateSourceWindowsWithLine */
238 ** tuiClearSourceContent().
241 tuiClearSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
243 if (m_winPtrNotNull (winInfo
))
247 winInfo
->generic
.contentInUse
= FALSE
;
248 tuiEraseSourceContent (winInfo
, displayPrompt
);
249 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
251 TuiWinElementPtr element
=
252 (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
253 element
->whichElement
.source
.hasBreak
= FALSE
;
254 element
->whichElement
.source
.isExecPoint
= FALSE
;
259 } /* tuiClearSourceContent */
263 ** tuiEraseSourceContent().
266 tuiEraseSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
269 int halfWidth
= (winInfo
->generic
.width
- 2) / 2;
271 if (winInfo
->generic
.handle
!= (WINDOW
*) NULL
)
273 werase (winInfo
->generic
.handle
);
274 checkAndDisplayHighlightIfNeeded (winInfo
);
275 if (displayPrompt
== EMPTY_SOURCE_PROMPT
)
279 if (winInfo
->generic
.type
== SRC_WIN
)
280 noSrcStr
= NO_SRC_STRING
;
282 noSrcStr
= NO_DISASSEM_STRING
;
283 if (strlen (noSrcStr
) >= halfWidth
)
286 xPos
= halfWidth
- strlen (noSrcStr
);
287 mvwaddstr (winInfo
->generic
.handle
,
288 (winInfo
->generic
.height
/ 2),
292 /* elz: added this function call to set the real contents of
293 the window to what is on the screen, so that later calls
294 to refresh, do display
295 the correct stuff, and not the old image */
297 tuiSetSourceContentNil (winInfo
, noSrcStr
);
299 tuiRefreshWin (&winInfo
->generic
);
302 } /* tuiEraseSourceContent */
306 ** tuiEraseAllSourceContent().
309 tuiEraseAllSourceWinsContent (int displayPrompt
)
313 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
314 tuiEraseSourceContent ((TuiWinInfoPtr
) (sourceWindows ())->list
[i
],
318 } /* tuiEraseAllSourceWinsContent */
321 /* Redraw the complete line of a source or disassembly window. */
323 tui_show_source_line (TuiWinInfoPtr winInfo
, int lineno
)
325 TuiWinElementPtr line
;
328 line
= (TuiWinElementPtr
) winInfo
->generic
.content
[lineno
- 1];
329 if (line
->whichElement
.source
.isExecPoint
)
330 wattron (winInfo
->generic
.handle
, A_STANDOUT
);
332 mvwaddstr (winInfo
->generic
.handle
, lineno
, 1,
333 line
->whichElement
.source
.line
);
334 if (line
->whichElement
.source
.isExecPoint
)
335 wattroff (winInfo
->generic
.handle
, A_STANDOUT
);
337 /* Clear to end of line but stop before the border. */
338 getyx (winInfo
->generic
.handle
, y
, x
);
339 while (x
+ 1 < winInfo
->generic
.width
)
341 waddch (winInfo
->generic
.handle
, ' ');
342 getyx (winInfo
->generic
.handle
, y
, x
);
347 ** tuiShowSourceContent().
350 tuiShowSourceContent (TuiWinInfoPtr winInfo
)
352 if (winInfo
->generic
.contentSize
> 0)
356 for (lineno
= 1; lineno
<= winInfo
->generic
.contentSize
; lineno
++)
357 tui_show_source_line (winInfo
, lineno
);
360 tuiEraseSourceContent (winInfo
, TRUE
);
362 checkAndDisplayHighlightIfNeeded (winInfo
);
363 tuiRefreshWin (&winInfo
->generic
);
364 winInfo
->generic
.contentInUse
= TRUE
;
369 ** tuiHorizontalSourceScroll().
370 ** Scroll the source forward or backward horizontally
373 tuiHorizontalSourceScroll (TuiWinInfoPtr winInfo
,
374 TuiScrollDirection direction
,
377 if (winInfo
->generic
.content
!= (OpaquePtr
) NULL
)
382 if (current_source_symtab
== (struct symtab
*) NULL
)
383 s
= find_pc_symtab (selected_frame
->pc
);
385 s
= current_source_symtab
;
387 if (direction
== LEFT_SCROLL
)
388 offset
= winInfo
->detail
.sourceInfo
.horizontalOffset
+ numToScroll
;
392 winInfo
->detail
.sourceInfo
.horizontalOffset
- numToScroll
) < 0)
395 winInfo
->detail
.sourceInfo
.horizontalOffset
= offset
;
396 tuiUpdateSourceWindowAsIs (
400 winInfo
->generic
.content
[0])->whichElement
.source
.lineOrAddr
,
405 } /* tuiHorizontalSourceScroll */
409 ** tuiSetHasExecPointAt().
410 ** Set or clear the hasBreak flag in the line whose line is lineNo.
413 tuiSetIsExecPointAt (TuiLineOrAddress l
, TuiWinInfoPtr winInfo
)
416 TuiWinContent content
= (TuiWinContent
) winInfo
->generic
.content
;
419 while (i
< winInfo
->generic
.contentSize
)
421 if (content
[i
]->whichElement
.source
.lineOrAddr
.addr
== l
.addr
)
422 content
[i
]->whichElement
.source
.isExecPoint
= TRUE
;
424 content
[i
]->whichElement
.source
.isExecPoint
= FALSE
;
429 } /* tuiSetIsExecPointAt */
432 ** tuiSetHasBreakAt().
433 ** Set or clear the hasBreak flag in the line whose line is lineNo.
436 tuiSetHasBreakAt (struct breakpoint
*bp
, TuiWinInfoPtr winInfo
, int hasBreak
)
439 TuiWinContent content
= (TuiWinContent
) winInfo
->generic
.content
;
442 while (i
< winInfo
->generic
.contentSize
)
445 TuiGenWinInfoPtr locator
= locatorWinInfoPtr ();
447 if (winInfo
== srcWin
)
449 char *fileNameDisplayed
= (char *) NULL
;
451 if (((TuiWinElementPtr
)
452 locator
->content
[0])->whichElement
.locator
.fileName
!=
454 fileNameDisplayed
= ((TuiWinElementPtr
)
455 locator
->content
[0])->whichElement
.locator
.fileName
;
456 else if (current_source_symtab
!= (struct symtab
*) NULL
)
457 fileNameDisplayed
= current_source_symtab
->filename
;
459 gotIt
= (fileNameDisplayed
!= (char *) NULL
&&
460 bp
->source_file
!= NULL
&&
461 (strcmp (bp
->source_file
, fileNameDisplayed
) == 0) &&
462 content
[i
]->whichElement
.source
.lineOrAddr
.lineNo
==
466 gotIt
= (content
[i
]->whichElement
.source
.lineOrAddr
.addr
470 content
[i
]->whichElement
.source
.hasBreak
= hasBreak
;
477 } /* tuiSetHasBreakAt */
481 ** tuiAllSetHasBreakAt().
482 ** Set or clear the hasBreak flag in all displayed source windows.
485 tuiAllSetHasBreakAt (struct breakpoint
*bp
, int hasBreak
)
489 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
490 tuiSetHasBreakAt (bp
,
491 (TuiWinInfoPtr
) (sourceWindows ())->list
[i
], hasBreak
);
494 } /* tuiAllSetHasBreakAt */
497 /*********************************
498 ** EXECUTION INFO FUNCTIONS **
499 *********************************/
502 ** tuiSetExecInfoContent().
503 ** Function to initialize the content of the execution info window,
504 ** based upon the input window which is either the source or
505 ** disassembly window.
508 tuiSetExecInfoContent (TuiWinInfoPtr winInfo
)
510 TuiStatus ret
= TUI_SUCCESS
;
512 if (winInfo
->detail
.sourceInfo
.executionInfo
!= (TuiGenWinInfoPtr
) NULL
)
514 TuiGenWinInfoPtr execInfoPtr
= winInfo
->detail
.sourceInfo
.executionInfo
;
516 if (execInfoPtr
->content
== (OpaquePtr
) NULL
)
517 execInfoPtr
->content
=
518 (OpaquePtr
) allocContent (winInfo
->generic
.height
,
520 if (execInfoPtr
->content
!= (OpaquePtr
) NULL
)
524 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
526 TuiWinElementPtr element
;
527 TuiWinElementPtr srcElement
;
529 element
= (TuiWinElementPtr
) execInfoPtr
->content
[i
];
530 srcElement
= (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
532 ** First check to see if we have a breakpoint that is
533 ** temporary. If so, and this is our current execution point,
534 ** then clear the break indicator.
536 if (srcElement
->whichElement
.source
.hasBreak
&&
537 srcElement
->whichElement
.source
.isExecPoint
)
539 struct breakpoint
*bp
;
541 extern struct breakpoint
*breakpoint_chain
;
543 for (bp
= breakpoint_chain
;
544 (bp
!= (struct breakpoint
*) NULL
&& !found
);
548 (winInfo
== srcWin
&&
550 srcElement
->whichElement
.source
.lineOrAddr
.lineNo
) ||
551 (winInfo
== disassemWin
&&
552 bp
->address
== (CORE_ADDR
)
553 srcElement
->whichElement
.source
.lineOrAddr
.addr
);
555 srcElement
->whichElement
.source
.hasBreak
=
556 (bp
->disposition
!= disp_del
|| bp
->hit_count
<= 0);
559 srcElement
->whichElement
.source
.hasBreak
= FALSE
;
562 ** Now update the exec info content based upon the state
563 ** of each line as indicated by the source content.
565 if (srcElement
->whichElement
.source
.hasBreak
&&
566 srcElement
->whichElement
.source
.isExecPoint
)
567 element
->whichElement
.simpleString
= breakLocationStr ();
568 else if (srcElement
->whichElement
.source
.hasBreak
)
569 element
->whichElement
.simpleString
= breakStr ();
570 else if (srcElement
->whichElement
.source
.isExecPoint
)
571 element
->whichElement
.simpleString
= locationStr ();
573 element
->whichElement
.simpleString
= blankStr ();
575 execInfoPtr
->contentSize
= winInfo
->generic
.contentSize
;
582 } /* tuiSetExecInfoContent */
586 ** tuiShowExecInfoContent().
589 tuiShowExecInfoContent (TuiWinInfoPtr winInfo
)
591 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
594 werase (execInfo
->handle
);
595 tuiRefreshWin (execInfo
);
596 for (curLine
= 1; (curLine
<= execInfo
->contentSize
); curLine
++)
597 mvwaddstr (execInfo
->handle
,
601 execInfo
->content
[curLine
- 1])->whichElement
.simpleString
);
602 tuiRefreshWin (execInfo
);
603 execInfo
->contentInUse
= TRUE
;
606 } /* tuiShowExecInfoContent */
610 ** tuiShowAllExecInfosContent()
613 tuiShowAllExecInfosContent (void)
617 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
618 tuiShowExecInfoContent ((TuiWinInfoPtr
) (sourceWindows ())->list
[i
]);
621 } /* tuiShowAllExecInfosContent */
625 ** tuiEraseExecInfoContent().
628 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo
)
630 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
632 werase (execInfo
->handle
);
633 tuiRefreshWin (execInfo
);
636 } /* tuiEraseExecInfoContent */
639 ** tuiClearExecInfoContent().
642 tuiClearExecInfoContent (TuiWinInfoPtr winInfo
)
644 winInfo
->detail
.sourceInfo
.executionInfo
->contentInUse
= FALSE
;
645 tuiEraseExecInfoContent (winInfo
);
648 } /* tuiClearExecInfoContent */
651 ** tuiUpdateExecInfo().
652 ** Function to update the execution info window
655 tuiUpdateExecInfo (TuiWinInfoPtr winInfo
)
657 tuiSetExecInfoContent (winInfo
);
658 tuiShowExecInfoContent (winInfo
);
659 } /* tuiUpdateExecInfo */
663 ** tuiUpdateAllExecInfos()
666 tuiUpdateAllExecInfos (void)
670 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
671 tuiUpdateExecInfo ((TuiWinInfoPtr
) (sourceWindows ())->list
[i
]);
674 } /* tuiUpdateAllExecInfos */
677 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo
)
679 register char *srcLine
, *srcLineBuf
;
680 register int i
, lineWidth
, c
, maxLines
;
681 TuiStatus ret
= TUI_FAILURE
;
683 maxLines
= winInfo
->generic
.height
; /* less the highlight box */
684 lineWidth
= winInfo
->generic
.width
- 1;
686 ** Allocate the buffer for the source lines. Do this only once since they
687 ** will be re-used for all source displays. The only other time this will
688 ** be done is when a window's size changes.
690 if (winInfo
->generic
.content
== (OpaquePtr
) NULL
)
692 srcLineBuf
= (char *) xmalloc ((maxLines
* lineWidth
) * sizeof (char));
693 if (srcLineBuf
== (char *) NULL
)
695 "Unable to Allocate Memory for Source or Disassembly Display.\n",
699 /* allocate the content list */
700 if ((winInfo
->generic
.content
=
701 (OpaquePtr
) allocContent (maxLines
, SRC_WIN
)) == (OpaquePtr
) NULL
)
703 tuiFree (srcLineBuf
);
704 srcLineBuf
= (char *) NULL
;
706 "Unable to Allocate Memory for Source or Disassembly Display.\n",
710 for (i
= 0; i
< maxLines
; i
++)
712 winInfo
->generic
.content
[i
])->whichElement
.source
.line
=
713 srcLineBuf
+ (lineWidth
* i
);
720 } /* tuiAllocSourceBuffer */
724 ** tuiLineIsDisplayed().
725 ** Answer whether the a particular line number or address is displayed
726 ** in the current source window.
729 tuiLineIsDisplayed (int line
, TuiWinInfoPtr winInfo
,
732 int isDisplayed
= FALSE
;
736 threshold
= SCROLL_THRESHOLD
;
740 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
742 isDisplayed
= (((TuiWinElementPtr
)
743 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.lineNo
749 } /* tuiLineIsDisplayed */
753 ** tuiLineIsDisplayed().
754 ** Answer whether the a particular line number or address is displayed
755 ** in the current source window.
758 tuiAddrIsDisplayed (CORE_ADDR addr
, TuiWinInfoPtr winInfo
,
761 int isDisplayed
= FALSE
;
765 threshold
= SCROLL_THRESHOLD
;
769 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
771 isDisplayed
= (((TuiWinElementPtr
)
772 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.addr
781 /*****************************************
782 ** STATIC LOCAL FUNCTIONS **
783 ******************************************/