Files
gdb-gui/gui/commands.py
Tom Tromey b73212ab30 add thread enforcement decorators
This adds a couple of decorators that can be used to
mark functions as needing to be run in the gdb thread
or in the gtk thread.

This found at least one bug.
2013-11-03 19:48:27 -07:00

197 lines
6.4 KiB
Python

# Copyright (C) 2012, 2013 Tom Tromey <tom@tromey.com>
# 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 3 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, see <http://www.gnu.org/licenses/>.
import gdb
import gui.startup
import gui.source
import gui.logwindow
import gui.toplevel
import gui.dprintf
import gui.events
import re
from gui.startup import in_gtk_thread
class GuiCommand(gdb.Command):
def __init__(self):
super(GuiCommand, self).__init__('gui', gdb.COMMAND_SUPPORT,
prefix = True)
class GuiSourceCommand(gdb.Command):
"""Create a new source window.
Usage: gui source
This creates a new source window in the GUI. Any number of source
windows can be created."""
def __init__(self):
super(GuiSourceCommand, self).__init__('gui source',
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
gui.startup.start_gtk()
gui.startup.send_to_gtk(gui.source.SourceWindow)
class GuiLogWindowCommand(gdb.Command):
"""Create a new log window.
Usage: gui log
This creates a new "log" window in the GUI. A log window is used
to display output from "gui print", "gui printf", "gui output",
and "gui dprintf".
Multiple log windows can be created and output can be directed to
a given instance using the "@" syntax, like:
gui printf @5 "hello\n"
"""
def __init__(self):
super(GuiLogWindowCommand, self).__init__('gui log',
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
gui.startup.start_gtk()
window = gui.logwindow.LogWindow()
print "Created log window %d; now the default" % window.number
class GuiPrintBase(gdb.Command):
def __init__(self, command):
super(GuiPrintBase, self).__init__('gui ' + command,
gdb.COMMAND_SUPPORT)
self.command = command
# Given ARG, return a pair (WINDOW, NEW_ARG).
def _parse_arg(self, arg, do_default = True):
arg = arg.strip()
match = re.match('@(\\d+)\\s+(.*)$', arg)
if match is not None:
winno = int(match.group(1))
arg = match.group(2)
window = gui.toplevel.state.get(winno)
if window is None:
raise gdb.GdbError('could not find window %d' % winno)
if not isinstance(window, gui.logwindow.LogWindow):
raise gdb.GdbError('window %d is not a log window' % winno)
elif do_default:
window = gui.logwindow.default_log_window
if window is None:
raise gdb.GdbError('no default log window')
else:
window = None
return (window, arg)
def invoke(self, arg, from_tty):
(window, arg) = self._parse_arg(arg)
text = gdb.execute(self.command + ' ' + arg, from_tty, True)
window.append(text)
class GuiPrintCommand(GuiPrintBase):
def __init__(self):
super(GuiPrintCommand, self).__init__('print')
class GuiOutputCommand(GuiPrintBase):
def __init__(self):
super(GuiOutputCommand, self).__init__('output')
class GuiPrintfCommand(GuiPrintBase):
def __init__(self):
super(GuiPrintfCommand, self).__init__('printf')
class GuiDprintfCommand(GuiPrintBase):
def __init__(self):
super(GuiDprintfCommand, self).__init__('dprintf')
def invoke(self, arg, from_tty):
(window, arg) = self._parse_arg(arg, False)
orig_arg = arg
(ignore, arg) = gdb.decode_line(arg)
if arg is None:
raise gdb.GdbError("no printf arguments to 'gui dprintf'")
arg = arg.strip()
if not arg.startswith(','):
raise gdb.GdbError("comma expected after linespec")
arg = arg[1:]
spec = arg[0 : -len(arg)]
DPrintfBreakpoint(spec, window, arg)
class InfoWindowsCommand(gdb.Command):
def __init__(self):
super(InfoWindowsCommand, self).__init__('info windows',
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
gui.toplevel.state.display()
class DeleteWindowsCommand(gdb.Command):
def __init__(self):
super(DeleteWindowsCommand, self).__init__('delete window',
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
winno = int(arg)
window = gui.toplevel.state.get(winno)
if window is not None:
window.destroy()
GuiCommand()
GuiSourceCommand()
GuiLogWindowCommand()
GuiPrintCommand()
GuiOutputCommand()
GuiPrintfCommand()
InfoWindowsCommand()
DeleteWindowsCommand()
_can_override = False
# A temporary test to see if you have a gdb that supports this.
class TestCommand(gdb.Command):
"""A temporary test command created for the GUI.
This does nothing, the GUI startup code uses it to see if
your copy of gdb has some command-overriding support."""
def __init__(self, set_it):
super(TestCommand, self).__init__('maint gui-test', gdb.COMMAND_DATA)
self.set_it = set_it
def invoke(self, arg, from_tty):
if self.set_it:
global _can_override
_can_override = True
else:
try:
super(TestCommand, self).invoke(arg, from_tty)
except:
pass
TestCommand(True)
TestCommand(False).invoke('', 0)
if _can_override:
class Overrider(gdb.Command):
def __init__(self, name, event):
super(Overrider, self).__init__(name, gdb.COMMAND_DATA)
self.event = event
def invoke(self, arg, from_tty):
super(Overrider, self).invoke(arg, from_tty)
self.event.post()
Overrider('up', gui.events.frame_changed)
Overrider('down', gui.events.frame_changed)
Overrider('frame', gui.events.frame_changed)