# Copyright (C) 2010-2012 Free Software Foundation, Inc.

# 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/>.

# This file is part of the GDB testsuite.  It tests python pretty
# printers.
import gdb

def signal_stop_handler (event):
    if (isinstance (event, gdb.StopEvent)):
        print "event type: stop"
    if (isinstance (event, gdb.SignalEvent)):
        print "stop reason: signal"
        print "stop signal: %s" % (event.stop_signal)
        if ( event.inferior_thread is not None) :
            print "thread num: %s" % (event.inferior_thread.num);

def breakpoint_stop_handler (event):
    if (isinstance (event, gdb.StopEvent)):
        print "event type: stop"
    if (isinstance (event, gdb.BreakpointEvent)):
        print "stop reason: breakpoint"
        print "first breakpoint number: %s" % (event.breakpoint.number)
        for bp in event.breakpoints:
        	print "breakpoint number: %s" % (bp.number)
        if ( event.inferior_thread is not None) :
            print "thread num: %s" % (event.inferior_thread.num);
        else:
            print "all threads stopped"

def exit_handler (event):
    if (isinstance (event, gdb.ExitedEvent)):
        print "event type: exit"
    print "exit code: %d" % (event.exit_code)
    print "exit inf: %d" % (event.inferior.num)
    print "dir ok: %s" % str('exit_code' in dir(event))

def continue_handler (event):
    if (isinstance (event, gdb.ContinueEvent)):
        print "event type: continue"
    if ( event.inferior_thread is not None) :
        print "thread num: %s" % (event.inferior_thread.num);

def new_objfile_handler (event):
    if (isinstance (event, gdb.NewObjFileEvent)):
        print "event type: new_objfile"
    if (event.new_objfile is not None):
    	print "new objfile name: %s" % (event.new_objfile.filename)
    else:
        print "new objfile is None"

class test_events (gdb.Command):
    """Test events."""

    def __init__ (self):
        gdb.Command.__init__ (self, "test_events", gdb.COMMAND_STACK)

    def invoke (self, arg, from_tty):
        gdb.events.stop.connect (signal_stop_handler)
        gdb.events.stop.connect (breakpoint_stop_handler)
        gdb.events.exited.connect (exit_handler)
        gdb.events.cont.connect (continue_handler)
        print "Event testers registered."

test_events ()

class test_newobj_events (gdb.Command):
    """NewObj events."""

    def __init__ (self):
        gdb.Command.__init__ (self, "test_newobj_events", gdb.COMMAND_STACK)

    def invoke (self, arg, from_tty):
        gdb.events.new_objfile.connect (new_objfile_handler)
        print "New ObjectFile Event tester registered."

test_newobj_events ()
