summaryrefslogtreecommitdiff
path: root/gdb/tui/tui-winsource.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/tui/tui-winsource.c')
-rw-r--r--gdb/tui/tui-winsource.c715
1 files changed, 715 insertions, 0 deletions
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
new file mode 100644
index 00000000000..87609b4cde8
--- /dev/null
+++ b/gdb/tui/tui-winsource.c
@@ -0,0 +1,715 @@
+/* TUI display source/assembly window.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "value.h"
+#include "source.h"
+
+#include "tui/tui.h"
+#include "tui/tui-data.h"
+#include "tui/tui-stack.h"
+#include "tui/tui-win.h"
+#include "tui/tui-wingeneral.h"
+#include "tui/tui-winsource.h"
+#include "tui/tui-source.h"
+#include "tui/tui-disasm.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
+
+/* Function to display the "main" routine. */
+void
+tui_display_main (void)
+{
+ if ((sourceWindows ())->count > 0)
+ {
+ CORE_ADDR addr;
+
+ addr = tui_get_begin_asm_address ();
+ if (addr != (CORE_ADDR) 0)
+ {
+ struct symtab_and_line sal;
+
+ tuiUpdateSourceWindowsWithAddr (addr);
+ sal = find_pc_line (addr, 0);
+ if (sal.symtab)
+ tuiUpdateLocatorFilename (sal.symtab->filename);
+ else
+ tuiUpdateLocatorFilename ("??");
+ }
+ }
+}
+
+
+
+/*
+ ** tuiUpdateSourceWindow().
+ ** Function to display source in the source window. This function
+ ** initializes the horizontal scroll to 0.
+ */
+void
+tuiUpdateSourceWindow (TuiWinInfoPtr winInfo, struct symtab *s,
+ TuiLineOrAddress lineOrAddr, int noerror)
+{
+ winInfo->detail.sourceInfo.horizontalOffset = 0;
+ tuiUpdateSourceWindowAsIs (winInfo, s, lineOrAddr, noerror);
+
+ return;
+} /* tuiUpdateSourceWindow */
+
+
+/*
+ ** tuiUpdateSourceWindowAsIs().
+ ** Function to display source in the source/asm window. This
+ ** function shows the source as specified by the horizontal offset.
+ */
+void
+tuiUpdateSourceWindowAsIs (TuiWinInfoPtr winInfo, struct symtab *s,
+ TuiLineOrAddress lineOrAddr, int noerror)
+{
+ TuiStatus ret;
+
+ if (winInfo->generic.type == SRC_WIN)
+ ret = tuiSetSourceContent (s, lineOrAddr.lineNo, noerror);
+ else
+ ret = tui_set_disassem_content (lineOrAddr.addr);
+
+ if (ret == TUI_FAILURE)
+ {
+ tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
+ tuiClearExecInfoContent (winInfo);
+ }
+ else
+ {
+ tui_update_breakpoint_info (winInfo, 0);
+ tuiShowSourceContent (winInfo);
+ tuiUpdateExecInfo (winInfo);
+ if (winInfo->generic.type == SRC_WIN)
+ {
+ struct symtab_and_line sal;
+
+ sal.line = lineOrAddr.lineNo +
+ (winInfo->generic.contentSize - 2);
+ sal.symtab = s;
+ set_current_source_symtab_and_line (&sal);
+ /*
+ ** If the focus was in the asm win, put it in the src
+ ** win if we don't have a split layout
+ */
+ if (tuiWinWithFocus () == disassemWin &&
+ currentLayout () != SRC_DISASSEM_COMMAND)
+ tuiSetWinFocusTo (srcWin);
+ }
+ }
+
+
+ return;
+} /* tuiUpdateSourceWindowAsIs */
+
+
+/*
+ ** tuiUpdateSourceWindowsWithAddr().
+ ** Function to ensure that the source and/or disassemly windows
+ ** reflect the input address.
+ */
+void
+tuiUpdateSourceWindowsWithAddr (CORE_ADDR addr)
+{
+ if (addr != 0)
+ {
+ struct symtab_and_line sal;
+ TuiLineOrAddress l;
+
+ switch (currentLayout ())
+ {
+ case DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ tui_show_disassem (addr);
+ break;
+ case SRC_DISASSEM_COMMAND:
+ tui_show_disassem_and_update_source (addr);
+ break;
+ default:
+ sal = find_pc_line (addr, 0);
+ l.lineNo = sal.line;
+ tuiShowSource (sal.symtab, l, FALSE);
+ break;
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < (sourceWindows ())->count; i++)
+ {
+ TuiWinInfoPtr winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
+
+ tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
+ tuiClearExecInfoContent (winInfo);
+ }
+ }
+
+ return;
+} /* tuiUpdateSourceWindowsWithAddr */
+
+/*
+ ** tuiUpdateSourceWindowsWithLine().
+ ** Function to ensure that the source and/or disassemly windows
+ ** reflect the input address.
+ */
+void
+tuiUpdateSourceWindowsWithLine (struct symtab *s, int line)
+{
+ CORE_ADDR pc;
+ TuiLineOrAddress l;
+
+ switch (currentLayout ())
+ {
+ case DISASSEM_COMMAND:
+ case DISASSEM_DATA_COMMAND:
+ find_line_pc (s, line, &pc);
+ tuiUpdateSourceWindowsWithAddr (pc);
+ break;
+ default:
+ l.lineNo = line;
+ tuiShowSource (s, l, FALSE);
+ if (currentLayout () == SRC_DISASSEM_COMMAND)
+ {
+ find_line_pc (s, line, &pc);
+ tui_show_disassem (pc);
+ }
+ break;
+ }
+
+ return;
+} /* tuiUpdateSourceWindowsWithLine */
+
+/*
+ ** tuiClearSourceContent().
+ */
+void
+tuiClearSourceContent (TuiWinInfoPtr winInfo, int displayPrompt)
+{
+ if (m_winPtrNotNull (winInfo))
+ {
+ register int i;
+
+ winInfo->generic.contentInUse = FALSE;
+ tuiEraseSourceContent (winInfo, displayPrompt);
+ for (i = 0; i < winInfo->generic.contentSize; i++)
+ {
+ TuiWinElementPtr element =
+ (TuiWinElementPtr) winInfo->generic.content[i];
+ element->whichElement.source.hasBreak = FALSE;
+ element->whichElement.source.isExecPoint = FALSE;
+ }
+ }
+
+ return;
+} /* tuiClearSourceContent */
+
+
+/*
+ ** tuiEraseSourceContent().
+ */
+void
+tuiEraseSourceContent (TuiWinInfoPtr winInfo, int displayPrompt)
+{
+ int xPos;
+ int halfWidth = (winInfo->generic.width - 2) / 2;
+
+ if (winInfo->generic.handle != (WINDOW *) NULL)
+ {
+ werase (winInfo->generic.handle);
+ checkAndDisplayHighlightIfNeeded (winInfo);
+ if (displayPrompt == EMPTY_SOURCE_PROMPT)
+ {
+ char *noSrcStr;
+
+ if (winInfo->generic.type == SRC_WIN)
+ noSrcStr = NO_SRC_STRING;
+ else
+ noSrcStr = NO_DISASSEM_STRING;
+ if (strlen (noSrcStr) >= halfWidth)
+ xPos = 1;
+ else
+ xPos = halfWidth - strlen (noSrcStr);
+ mvwaddstr (winInfo->generic.handle,
+ (winInfo->generic.height / 2),
+ xPos,
+ noSrcStr);
+
+ /* elz: added this function call to set the real contents of
+ the window to what is on the screen, so that later calls
+ to refresh, do display
+ the correct stuff, and not the old image */
+
+ tuiSetSourceContentNil (winInfo, noSrcStr);
+ }
+ tuiRefreshWin (&winInfo->generic);
+ }
+ return;
+} /* tuiEraseSourceContent */
+
+
+/* Redraw the complete line of a source or disassembly window. */
+static void
+tui_show_source_line (TuiWinInfoPtr winInfo, int lineno)
+{
+ TuiWinElementPtr line;
+ int x, y;
+
+ line = (TuiWinElementPtr) winInfo->generic.content[lineno - 1];
+ if (line->whichElement.source.isExecPoint)
+ wattron (winInfo->generic.handle, A_STANDOUT);
+
+ mvwaddstr (winInfo->generic.handle, lineno, 1,
+ line->whichElement.source.line);
+ if (line->whichElement.source.isExecPoint)
+ wattroff (winInfo->generic.handle, A_STANDOUT);
+
+ /* Clear to end of line but stop before the border. */
+ getyx (winInfo->generic.handle, y, x);
+ while (x + 1 < winInfo->generic.width)
+ {
+ waddch (winInfo->generic.handle, ' ');
+ getyx (winInfo->generic.handle, y, x);
+ }
+}
+
+/*
+ ** tuiShowSourceContent().
+ */
+void
+tuiShowSourceContent (TuiWinInfoPtr winInfo)
+{
+ if (winInfo->generic.contentSize > 0)
+ {
+ int lineno;
+
+ for (lineno = 1; lineno <= winInfo->generic.contentSize; lineno++)
+ tui_show_source_line (winInfo, lineno);
+ }
+ else
+ tuiEraseSourceContent (winInfo, TRUE);
+
+ checkAndDisplayHighlightIfNeeded (winInfo);
+ tuiRefreshWin (&winInfo->generic);
+ winInfo->generic.contentInUse = TRUE;
+}
+
+
+/*
+ ** tuiHorizontalSourceScroll().
+ ** Scroll the source forward or backward horizontally
+ */
+void
+tuiHorizontalSourceScroll (TuiWinInfoPtr winInfo,
+ TuiScrollDirection direction,
+ int numToScroll)
+{
+ if (winInfo->generic.content != (OpaquePtr) NULL)
+ {
+ int offset;
+ struct symtab *s;
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+
+ if (cursal.symtab == (struct symtab *) NULL)
+ s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
+ else
+ s = cursal.symtab;
+
+ if (direction == LEFT_SCROLL)
+ offset = winInfo->detail.sourceInfo.horizontalOffset + numToScroll;
+ else
+ {
+ if ((offset =
+ winInfo->detail.sourceInfo.horizontalOffset - numToScroll) < 0)
+ offset = 0;
+ }
+ winInfo->detail.sourceInfo.horizontalOffset = offset;
+ tuiUpdateSourceWindowAsIs (
+ winInfo,
+ s,
+ ((TuiWinElementPtr)
+ winInfo->generic.content[0])->whichElement.source.lineOrAddr,
+ FALSE);
+ }
+
+ return;
+} /* tuiHorizontalSourceScroll */
+
+
+/* Set or clear the hasBreak flag in the line whose line is lineNo. */
+void
+tuiSetIsExecPointAt (TuiLineOrAddress l, TuiWinInfoPtr winInfo)
+{
+ int changed = 0;
+ int i;
+ TuiWinContent content = (TuiWinContent) winInfo->generic.content;
+
+ i = 0;
+ while (i < winInfo->generic.contentSize)
+ {
+ int newState;
+
+ if (content[i]->whichElement.source.lineOrAddr.addr == l.addr)
+ newState = TRUE;
+ else
+ newState = FALSE;
+ if (newState != content[i]->whichElement.source.isExecPoint)
+ {
+ changed++;
+ content[i]->whichElement.source.isExecPoint = newState;
+ tui_show_source_line (winInfo, i + 1);
+ }
+ i++;
+ }
+ if (changed)
+ tuiRefreshWin (&winInfo->generic);
+}
+
+/* Update the execution windows to show the active breakpoints.
+ This is called whenever a breakpoint is inserted, removed or
+ has its state changed. */
+void
+tui_update_all_breakpoint_info ()
+{
+ TuiList* list = sourceWindows ();
+ int i;
+
+ for (i = 0; i < list->count; i++)
+ {
+ TuiWinInfoPtr win = (TuiWinInfoPtr) list->list[i];
+
+ if (tui_update_breakpoint_info (win, FALSE))
+ {
+ tuiUpdateExecInfo (win);
+ }
+ }
+}
+
+
+/* Scan the source window and the breakpoints to update the
+ hasBreak information for each line.
+ Returns 1 if something changed and the execution window
+ must be refreshed. */
+int
+tui_update_breakpoint_info (TuiWinInfoPtr win, int current_only)
+{
+ int i;
+ int need_refresh = 0;
+ TuiSourceInfoPtr src = &win->detail.sourceInfo;
+
+ for (i = 0; i < win->generic.contentSize; i++)
+ {
+ struct breakpoint *bp;
+ extern struct breakpoint *breakpoint_chain;
+ int mode;
+ TuiSourceElement* line;
+
+ line = &((TuiWinElementPtr) win->generic.content[i])->whichElement.source;
+ if (current_only && !line->isExecPoint)
+ continue;
+
+ /* Scan each breakpoint to see if the current line has something to
+ do with it. Identify enable/disabled breakpoints as well as
+ those that we already hit. */
+ mode = 0;
+ for (bp = breakpoint_chain;
+ bp != (struct breakpoint *) NULL;
+ bp = bp->next)
+ {
+ if ((win == srcWin
+ && bp->source_file
+ && (strcmp (src->filename, bp->source_file) == 0)
+ && bp->line_number == line->lineOrAddr.lineNo)
+ || (win == disassemWin
+ && bp->loc->address == line->lineOrAddr.addr))
+ {
+ if (bp->enable_state == bp_disabled)
+ mode |= TUI_BP_DISABLED;
+ else
+ mode |= TUI_BP_ENABLED;
+ if (bp->hit_count)
+ mode |= TUI_BP_HIT;
+ if (bp->cond)
+ mode |= TUI_BP_CONDITIONAL;
+ if (bp->type == bp_hardware_breakpoint)
+ mode |= TUI_BP_HARDWARE;
+ }
+ }
+ if (line->hasBreak != mode)
+ {
+ line->hasBreak = mode;
+ need_refresh = 1;
+ }
+ }
+ return need_refresh;
+}
+
+
+/*
+ ** tuiSetExecInfoContent().
+ ** Function to initialize the content of the execution info window,
+ ** based upon the input window which is either the source or
+ ** disassembly window.
+ */
+TuiStatus
+tuiSetExecInfoContent (TuiWinInfoPtr winInfo)
+{
+ TuiStatus ret = TUI_SUCCESS;
+
+ if (winInfo->detail.sourceInfo.executionInfo != (TuiGenWinInfoPtr) NULL)
+ {
+ TuiGenWinInfoPtr execInfoPtr = winInfo->detail.sourceInfo.executionInfo;
+
+ if (execInfoPtr->content == (OpaquePtr) NULL)
+ execInfoPtr->content =
+ (OpaquePtr) allocContent (winInfo->generic.height,
+ execInfoPtr->type);
+ if (execInfoPtr->content != (OpaquePtr) NULL)
+ {
+ int i;
+
+ tui_update_breakpoint_info (winInfo, 1);
+ for (i = 0; i < winInfo->generic.contentSize; i++)
+ {
+ TuiWinElementPtr element;
+ TuiWinElementPtr srcElement;
+ int mode;
+
+ element = (TuiWinElementPtr) execInfoPtr->content[i];
+ srcElement = (TuiWinElementPtr) winInfo->generic.content[i];
+
+ memset(element->whichElement.simpleString, ' ',
+ sizeof(element->whichElement.simpleString));
+ element->whichElement.simpleString[TUI_EXECINFO_SIZE - 1] = 0;
+
+ /* Now update the exec info content based upon the state
+ of each line as indicated by the source content. */
+ mode = srcElement->whichElement.source.hasBreak;
+ if (mode & TUI_BP_HIT)
+ element->whichElement.simpleString[TUI_BP_HIT_POS] =
+ (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
+ else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
+ element->whichElement.simpleString[TUI_BP_HIT_POS] =
+ (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
+
+ if (mode & TUI_BP_ENABLED)
+ element->whichElement.simpleString[TUI_BP_BREAK_POS] = '+';
+ else if (mode & TUI_BP_DISABLED)
+ element->whichElement.simpleString[TUI_BP_BREAK_POS] = '-';
+
+ if (srcElement->whichElement.source.isExecPoint)
+ element->whichElement.simpleString[TUI_EXEC_POS] = '>';
+ }
+ execInfoPtr->contentSize = winInfo->generic.contentSize;
+ }
+ else
+ ret = TUI_FAILURE;
+ }
+
+ return ret;
+}
+
+
+/*
+ ** tuiShowExecInfoContent().
+ */
+void
+tuiShowExecInfoContent (TuiWinInfoPtr winInfo)
+{
+ TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
+ int curLine;
+
+ werase (execInfo->handle);
+ tuiRefreshWin (execInfo);
+ for (curLine = 1; (curLine <= execInfo->contentSize); curLine++)
+ mvwaddstr (execInfo->handle,
+ curLine,
+ 0,
+ ((TuiWinElementPtr)
+ execInfo->content[curLine - 1])->whichElement.simpleString);
+ tuiRefreshWin (execInfo);
+ execInfo->contentInUse = TRUE;
+
+ return;
+} /* tuiShowExecInfoContent */
+
+
+/*
+ ** tuiEraseExecInfoContent().
+ */
+void
+tuiEraseExecInfoContent (TuiWinInfoPtr winInfo)
+{
+ TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
+
+ werase (execInfo->handle);
+ tuiRefreshWin (execInfo);
+
+ return;
+} /* tuiEraseExecInfoContent */
+
+/*
+ ** tuiClearExecInfoContent().
+ */
+void
+tuiClearExecInfoContent (TuiWinInfoPtr winInfo)
+{
+ winInfo->detail.sourceInfo.executionInfo->contentInUse = FALSE;
+ tuiEraseExecInfoContent (winInfo);
+
+ return;
+} /* tuiClearExecInfoContent */
+
+/*
+ ** tuiUpdateExecInfo().
+ ** Function to update the execution info window
+ */
+void
+tuiUpdateExecInfo (TuiWinInfoPtr winInfo)
+{
+ tuiSetExecInfoContent (winInfo);
+ tuiShowExecInfoContent (winInfo);
+} /* tuiUpdateExecInfo */
+
+TuiStatus
+tuiAllocSourceBuffer (TuiWinInfoPtr winInfo)
+{
+ register char *srcLineBuf;
+ register int i, lineWidth, maxLines;
+ TuiStatus ret = TUI_FAILURE;
+
+ maxLines = winInfo->generic.height; /* less the highlight box */
+ lineWidth = winInfo->generic.width - 1;
+ /*
+ ** Allocate the buffer for the source lines. Do this only once since they
+ ** will be re-used for all source displays. The only other time this will
+ ** be done is when a window's size changes.
+ */
+ if (winInfo->generic.content == (OpaquePtr) NULL)
+ {
+ srcLineBuf = (char *) xmalloc ((maxLines * lineWidth) * sizeof (char));
+ if (srcLineBuf == (char *) NULL)
+ fputs_unfiltered (
+ "Unable to Allocate Memory for Source or Disassembly Display.\n",
+ gdb_stderr);
+ else
+ {
+ /* allocate the content list */
+ if ((winInfo->generic.content =
+ (OpaquePtr) allocContent (maxLines, SRC_WIN)) == (OpaquePtr) NULL)
+ {
+ tuiFree (srcLineBuf);
+ srcLineBuf = (char *) NULL;
+ fputs_unfiltered (
+ "Unable to Allocate Memory for Source or Disassembly Display.\n",
+ gdb_stderr);
+ }
+ }
+ for (i = 0; i < maxLines; i++)
+ ((TuiWinElementPtr)
+ winInfo->generic.content[i])->whichElement.source.line =
+ srcLineBuf + (lineWidth * i);
+ ret = TUI_SUCCESS;
+ }
+ else
+ ret = TUI_SUCCESS;
+
+ return ret;
+} /* tuiAllocSourceBuffer */
+
+
+/*
+ ** tuiLineIsDisplayed().
+ ** Answer whether the a particular line number or address is displayed
+ ** in the current source window.
+ */
+int
+tuiLineIsDisplayed (int line, TuiWinInfoPtr winInfo,
+ int checkThreshold)
+{
+ int isDisplayed = FALSE;
+ int i, threshold;
+
+ if (checkThreshold)
+ threshold = SCROLL_THRESHOLD;
+ else
+ threshold = 0;
+ i = 0;
+ while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
+ {
+ isDisplayed = (((TuiWinElementPtr)
+ winInfo->generic.content[i])->whichElement.source.lineOrAddr.lineNo
+ == (int) line);
+ i++;
+ }
+
+ return isDisplayed;
+} /* tuiLineIsDisplayed */
+
+
+/*
+ ** tuiLineIsDisplayed().
+ ** Answer whether the a particular line number or address is displayed
+ ** in the current source window.
+ */
+int
+tuiAddrIsDisplayed (CORE_ADDR addr, TuiWinInfoPtr winInfo,
+ int checkThreshold)
+{
+ int isDisplayed = FALSE;
+ int i, threshold;
+
+ if (checkThreshold)
+ threshold = SCROLL_THRESHOLD;
+ else
+ threshold = 0;
+ i = 0;
+ while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
+ {
+ isDisplayed = (((TuiWinElementPtr)
+ winInfo->generic.content[i])->whichElement.source.lineOrAddr.addr
+ == addr);
+ i++;
+ }
+
+ return isDisplayed;
+}
+
+
+/*****************************************
+** STATIC LOCAL FUNCTIONS **
+******************************************/