/* Python interface to inferior function events.

   Copyright (C) 2013-2018 Free Software Foundation, Inc.

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

#include "defs.h"
#include "py-event.h"
#include "py-ref.h"

/* Construct either a gdb.InferiorCallPreEvent or a
   gdb.InferiorCallPostEvent. */

static PyObject *
create_inferior_call_event_object (inferior_call_kind flag, ptid_t ptid,
				   CORE_ADDR addr)
{
  gdbpy_ref<> event;

  switch (flag)
    {
    case INFERIOR_CALL_PRE:
      event = create_event_object (&inferior_call_pre_event_object_type);
      break;
    case INFERIOR_CALL_POST:
      event = create_event_object (&inferior_call_post_event_object_type);
      break;
    default:
      gdb_assert_not_reached ("invalid inferior_call_kind");
    }

  gdbpy_ref<> ptid_obj (gdbpy_create_ptid_object (ptid));
  if (ptid_obj == NULL)
    return NULL;

  if (evpy_add_attribute (event.get (), "ptid", ptid_obj.get ()) < 0)
    return NULL;

  gdbpy_ref<> addr_obj (PyLong_FromLongLong (addr));
  if (addr_obj == NULL)
    return NULL;

  if (evpy_add_attribute (event.get (), "address", addr_obj.get ()) < 0)
    return NULL;

  return event.release ();
}

/* Construct a gdb.RegisterChangedEvent containing the affected
   register number. */

static PyObject *
create_register_changed_event_object (struct frame_info *frame, 
				      int regnum)
{
  gdbpy_ref<> event (create_event_object (&register_changed_event_object_type));
  if (event == NULL)
    return NULL;

  gdbpy_ref<> frame_obj (frame_info_to_frame_object (frame));
  if (frame_obj == NULL)
    return NULL;

  if (evpy_add_attribute (event.get (), "frame", frame_obj.get ()) < 0)
    return NULL;

  gdbpy_ref<> regnum_obj (PyLong_FromLongLong (regnum));
  if (regnum_obj == NULL)
    return NULL;

  if (evpy_add_attribute (event.get (), "regnum", regnum_obj.get ()) < 0)
    return NULL;

  return event.release ();
}

/* Construct a gdb.MemoryChangedEvent describing the extent of the
   affected memory. */

static PyObject *
create_memory_changed_event_object (CORE_ADDR addr, ssize_t len)
{
  gdbpy_ref<> event (create_event_object (&memory_changed_event_object_type));

  if (event == NULL)
    return NULL;

  gdbpy_ref<> addr_obj (PyLong_FromLongLong (addr));
  if (addr_obj == NULL)
    return NULL;

  if (evpy_add_attribute (event.get (), "address", addr_obj.get ()) < 0)
    return NULL;

  gdbpy_ref<> len_obj (PyLong_FromLong (len));
  if (len_obj == NULL)
    return NULL;

  if (evpy_add_attribute (event.get (), "length", len_obj.get ()) < 0)
    return NULL;

  return event.release ();
}

/* Callback function which notifies observers when an event occurs which
   calls a function in the inferior.
   This function will create a new Python inferior-call event object.
   Return -1 if emit fails.  */

int
emit_inferior_call_event (inferior_call_kind flag, ptid_t thread,
			  CORE_ADDR addr)
{
  if (evregpy_no_listeners_p (gdb_py_events.inferior_call))
    return 0;

  gdbpy_ref<> event (create_inferior_call_event_object (flag, thread, addr));
  if (event != NULL)
    return evpy_emit_event (event.get (), gdb_py_events.inferior_call);
  return -1;
}

/* Callback when memory is modified by the user.  This function will
   create a new Python memory changed event object. */

int
emit_memory_changed_event (CORE_ADDR addr, ssize_t len)
{
  if (evregpy_no_listeners_p (gdb_py_events.memory_changed))
    return 0;

  gdbpy_ref<> event (create_memory_changed_event_object (addr, len));
  if (event != NULL)
    return evpy_emit_event (event.get (), gdb_py_events.memory_changed);
  return -1;
}

/* Callback when a register is modified by the user.  This function
   will create a new Python register changed event object. */

int
emit_register_changed_event (struct frame_info* frame, int regnum)
{
  if (evregpy_no_listeners_p (gdb_py_events.register_changed))
    return 0;

  gdbpy_ref<> event (create_register_changed_event_object (frame, regnum));
  if (event != NULL)
    return evpy_emit_event (event.get (), gdb_py_events.register_changed);
  return -1;
}
