%header %{

class PyErr_Cleaner
{
public:
    PyErr_Cleaner(bool print=false) :
    m_print(print)
    {
    }

    ~PyErr_Cleaner()
    {
        if (PyErr_Occurred())
        {
            if(m_print && !PyErr_ExceptionMatches(PyExc_SystemExit))
                PyErr_Print();
            PyErr_Clear();
        }
    }

private:
    bool m_print;
};

llvm::Expected<bool>
lldb_private::LLDBSwigPythonBreakpointCallbackFunction
(
    const char *python_function_name,
    const char *session_dictionary_name,
    const lldb::StackFrameSP& frame_sp,
    const lldb::BreakpointLocationSP& bp_loc_sp,
    lldb_private::StructuredDataImpl *args_impl
)
{
    using namespace llvm;

    lldb::SBFrame sb_frame (frame_sp);
    lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp);

    PyErr_Cleaner py_err_cleaner(true);
    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);

    unsigned max_positional_args;
    if (auto arg_info = pfunc.GetArgInfo())
        max_positional_args = arg_info.get().max_positional_args;
    else
        return arg_info.takeError();

    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
    PythonObject bp_loc_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_bp_loc));

    auto result = [&] () -> Expected<PythonObject> {
        // If the called function doesn't take extra_args, drop them here:
        if (max_positional_args < 4) {
            return pfunc.Call(frame_arg, bp_loc_arg, dict);
        } else {
            // FIXME: SBStructuredData leaked here
            lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
            PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(*args_value));
            return pfunc.Call(frame_arg, bp_loc_arg, args_arg, dict);
        }
    } ();

    if (!result)
        return result.takeError();

    // Only False counts as false!
    return result.get().get() != Py_False;
}

// resolve a dotted Python name in the form
// foo.bar.baz.Foobar to an actual Python object
// if pmodule is NULL, the __main__ module will be used
// as the starting point for the search


// This function is called by lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...)
// and is used when a script command is attached to a breakpoint for execution.

// This function is called by lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...)
// and is used when a script command is attached to a watchpoint for execution.

bool
lldb_private::LLDBSwigPythonWatchpointCallbackFunction
(
    const char *python_function_name,
    const char *session_dictionary_name,
    const lldb::StackFrameSP& frame_sp,
    const lldb::WatchpointSP& wp_sp
)
{
    lldb::SBFrame sb_frame (frame_sp);
    lldb::SBWatchpoint sb_wp(wp_sp);

    bool stop_at_watchpoint = true;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);

    if (!pfunc.IsAllocated())
        return stop_at_watchpoint;

    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
    PythonObject wp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_wp));
    PythonObject result = pfunc(frame_arg, wp_arg, dict);

    if (result.get() == Py_False)
        stop_at_watchpoint = false;

    return stop_at_watchpoint;
}

bool
lldb_private::LLDBSwigPythonCallTypeScript
(
    const char *python_function_name,
    const void *session_dictionary,
    const lldb::ValueObjectSP& valobj_sp,
    void** pyfunct_wrapper,
    const lldb::TypeSummaryOptionsSP& options_sp,
    std::string& retval
)
{
    lldb::SBTypeSummaryOptions sb_options(options_sp.get());

    retval.clear();

    if (!python_function_name || !session_dictionary)
        return false;

    PyObject *pfunc_impl = nullptr;

    if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper))
    {
        pfunc_impl = (PyObject*)(*pyfunct_wrapper);
        if (pfunc_impl->ob_refcnt == 1)
        {
            Py_XDECREF(pfunc_impl);
            pfunc_impl = NULL;
        }
    }

    PyObject *py_dict = (PyObject*)session_dictionary;
    if (!PythonDictionary::Check(py_dict))
        return true;

    PythonDictionary dict(PyRefType::Borrowed, py_dict);

    PyErr_Cleaner pyerr_cleanup(true);  // show Python errors

    PythonCallable pfunc(PyRefType::Borrowed, pfunc_impl);

    if (!pfunc.IsAllocated())
    {
        pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
        if (!pfunc.IsAllocated())
            return false;

        if (pyfunct_wrapper)
        {
            *pyfunct_wrapper = pfunc.get();
            Py_XINCREF(pfunc.get());
        }
    }

    PythonObject result;
    auto argc = pfunc.GetArgInfo();
    if (!argc) {
        llvm::consumeError(argc.takeError());
        return false;
    }

    PythonObject value_arg = ToSWIGWrapper(valobj_sp);
    PythonObject options_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_options));

    if (argc.get().max_positional_args < 3)
        result = pfunc(value_arg,dict);
    else
        result = pfunc(value_arg,dict,options_arg);

    retval = result.Str().GetString().str();

    return true;
}

void*
lldb_private::LLDBSwigPythonCreateSyntheticProvider
(
    const char *python_class_name,
    const char *session_dictionary_name,
    const lldb::ValueObjectSP& valobj_sp
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name,dict);

    if (!pfunc.IsAllocated())
        Py_RETURN_NONE;

    auto sb_value = std::make_unique<lldb::SBValue>(valobj_sp);
    sb_value->SetPreferSyntheticValue(false);

    PythonObject val_arg = ToSWIGWrapper(std::move(sb_value));
    if (!val_arg.IsAllocated())
        Py_RETURN_NONE;

    PythonObject result = pfunc(val_arg, dict);

    if (result.IsAllocated())
        return result.release();

    Py_RETURN_NONE;
}

void*
lldb_private::LLDBSwigPythonCreateCommandObject
(
    const char *python_class_name,
    const char *session_dictionary_name,
    const lldb::DebuggerSP debugger_sp
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);
    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);

    if (!pfunc.IsAllocated())
        return nullptr;

    lldb::SBDebugger debugger_sb(debugger_sp);
    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
    PythonObject result = pfunc(debugger_arg, dict);

    if (result.IsAllocated())
        return result.release();

    Py_RETURN_NONE;
}

void*
lldb_private::LLDBSwigPythonCreateScriptedProcess
(
    const char *python_class_name,
    const char *session_dictionary_name,
    const lldb::TargetSP& target_sp,
    lldb_private::StructuredDataImpl *args_impl,
    std::string &error_string
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);

    if (!pfunc.IsAllocated()) {
        error_string.append("could not find script class: ");
        error_string.append(python_class_name);
        return nullptr;
    }

    PythonObject target_arg = ToSWIGWrapper(target_sp);

    llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
    if (!arg_info) {
        llvm::handleAllErrors(
            arg_info.takeError(),
            [&](PythonException &E) {
                error_string.append(E.ReadBacktrace());
            },
            [&](const llvm::ErrorInfoBase &E) {
                error_string.append(E.message());
            });
        Py_RETURN_NONE;
    }

    PythonObject result = {};
    if (arg_info.get().max_positional_args == 2) {
        // FIXME: SBStructuredData leaked here
        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(*new lldb::SBStructuredData(args_impl)));
        result = pfunc(target_arg, args_arg);
    } else {
        error_string.assign("wrong number of arguments in __init__, should be 2 (not including self)");
        Py_RETURN_NONE;
    }

    if (result.IsAllocated())
        return result.release();
    Py_RETURN_NONE;
}

void*
lldb_private::LLDBSwigPythonCreateScriptedThread
(
    const char *python_class_name,
    const char *session_dictionary_name,
    const lldb::ProcessSP& process_sp,
    lldb_private::StructuredDataImpl *args_impl,
    std::string &error_string
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);

    if (!pfunc.IsAllocated()) {
        error_string.append("could not find script class: ");
        error_string.append(python_class_name);
        return nullptr;
    }

    llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
    if (!arg_info) {
        llvm::handleAllErrors(
            arg_info.takeError(),
            [&](PythonException &E) {
                error_string.append(E.ReadBacktrace());
            },
            [&](const llvm::ErrorInfoBase &E) {
                error_string.append(E.message());
            });
        Py_RETURN_NONE;
    }

    PythonObject result = {};
    if (arg_info.get().max_positional_args == 2) {
        // FIXME: SBStructuredData leaked here
        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(*new lldb::SBStructuredData(args_impl)));
        result = pfunc(ToSWIGWrapper(process_sp), args_arg);
    } else {
        error_string.assign("wrong number of arguments in __init__, should be 2 (not including self)");
        Py_RETURN_NONE;
    }

    if (result.IsAllocated())
        return result.release();
    Py_RETURN_NONE;
}

void*
lldb_private::LLDBSwigPythonCreateScriptedThreadPlan
(
    const char *python_class_name,
    const char *session_dictionary_name,
    lldb_private::StructuredDataImpl *args_impl,
    std::string &error_string,
    const lldb::ThreadPlanSP& thread_plan_sp
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;


    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);

    if (!pfunc.IsAllocated()) {
        error_string.append("could not find script class: ");
        error_string.append(python_class_name);
        return nullptr;
    }

    PythonObject tp_arg = ToSWIGWrapper(thread_plan_sp);

    llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
    if (!arg_info) {
        llvm::handleAllErrors(
            arg_info.takeError(),
            [&](PythonException &E) {
                error_string.append(E.ReadBacktrace());
            },
            [&](const llvm::ErrorInfoBase &E) {
                error_string.append(E.message());
            });
        Py_RETURN_NONE;
    }

    PythonObject result = {};
    if (arg_info.get().max_positional_args == 2) {
        if (args_impl != nullptr) {
           error_string.assign("args passed, but __init__ does not take an args dictionary");
           Py_RETURN_NONE;
        }
        result = pfunc(tp_arg, dict);
    } else if (arg_info.get().max_positional_args >= 3) {
        // FIXME: SBStructuredData leaked here
        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(*new lldb::SBStructuredData(args_impl)));
        result = pfunc(tp_arg, args_arg, dict);
    } else {
        error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)");
        Py_RETURN_NONE;
    }

    // FIXME: At this point we should check that the class we found supports all the methods
    // that we need.

    if (result.IsAllocated())
        return result.release();
    Py_RETURN_NONE;
}

bool
lldb_private::LLDBSWIGPythonCallThreadPlan
(
    void *implementor,
    const char *method_name,
    lldb_private::Event *event,
    bool &got_error
)
{
    got_error = false;

    PyErr_Cleaner py_err_cleaner(false);
    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
    auto pfunc = self.ResolveName<PythonCallable>(method_name);

    if (!pfunc.IsAllocated())
        return false;

    PythonObject result;
    if (event != nullptr)
    {
        lldb::SBEvent sb_event(event);
        PythonObject event_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_event));
        result = pfunc(event_arg);
    }
    else
        result = pfunc();

    if (PyErr_Occurred())
    {
        got_error = true;
        printf ("Return value was neither false nor true for call to %s.\n", method_name);
        PyErr_Print();
        return false;
    }

    if (result.get() == Py_True)
        return true;
    else if (result.get() == Py_False)
        return false;

    // Somebody returned the wrong thing...
    got_error = true;
    printf ("Wrong return value type for call to %s.\n", method_name);
    return false;
}

void *lldb_private::LLDBSwigPythonCreateScriptedBreakpointResolver(
    const char *python_class_name, const char *session_dictionary_name,
    lldb_private::StructuredDataImpl *args_impl,
    const lldb::BreakpointSP &breakpoint_sp) {

    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);

    if (!pfunc.IsAllocated())
        return nullptr;

    // FIXME: SBStructuredData leaked here
    lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
    PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(*args_value));

    PythonObject result = pfunc(ToSWIGWrapper(breakpoint_sp), args_arg, dict);
    // FIXME: At this point we should check that the class we found supports all the methods
    // that we need.

    if (result.IsAllocated())
    {
        // Check that __callback__ is defined:
        auto callback_func = result.ResolveName<PythonCallable>("__callback__");
        if (callback_func.IsAllocated())
            return result.release();
        else
            result.release();
    }
    Py_RETURN_NONE;
}

unsigned int
lldb_private::LLDBSwigPythonCallBreakpointResolver
(
    void *implementor,
    const char *method_name,
    lldb_private::SymbolContext *sym_ctx
)
{
    PyErr_Cleaner py_err_cleaner(false);
    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
    auto pfunc = self.ResolveName<PythonCallable>(method_name);

    if (!pfunc.IsAllocated())
        return 0;

    PythonObject result;
    if (sym_ctx != nullptr) {
      lldb::SBSymbolContext sb_sym_ctx(sym_ctx);
      PythonObject sym_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_sym_ctx));
      result = pfunc(sym_ctx_arg);
    } else
      result = pfunc();

    if (PyErr_Occurred())
    {
        PyErr_Print();
        PyErr_Clear();
        return 0;
    }

    // The callback will return a bool, but we're need to also return ints
    // so we're squirrelling the bool through as an int...  And if you return
    // nothing, we'll continue.
    if (strcmp(method_name, "__callback__") == 0) {
        if (result.get() == Py_False)
          return 0;
        else
          return 1;
    }

    long long ret_val = unwrapOrSetPythonException(As<long long>(result));

    if (PyErr_Occurred()) {
        PyErr_Print();
        PyErr_Clear();
        return 0;
    }

    return ret_val;
}

void *
lldb_private::LLDBSwigPythonCreateScriptedStopHook
(
    lldb::TargetSP target_sp,
    const char *python_class_name,
    const char *session_dictionary_name,
    lldb_private::StructuredDataImpl *args_impl,
    Status &error
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0') {
        error.SetErrorString("Empty class name.");
        Py_RETURN_NONE;
    }
    if (!session_dictionary_name) {
      error.SetErrorString("No session dictionary");
      Py_RETURN_NONE;
    }
    
    PyErr_Cleaner py_err_cleaner(true);

    auto dict = 
        PythonModule::MainModule().ResolveName<PythonDictionary>(
            session_dictionary_name);
    auto pfunc = 
        PythonObject::ResolveNameWithDictionary<PythonCallable>(
            python_class_name, dict);

    if (!pfunc.IsAllocated()) {
        error.SetErrorStringWithFormat("Could not find class: %s.", 
                                       python_class_name);
        return nullptr;
    }

    // FIXME: SBStructuredData leaked here
    lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
    PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(*args_value));

    PythonObject result = pfunc(ToSWIGWrapper(target_sp), args_arg, dict);

    if (result.IsAllocated())
    {
        // Check that the handle_stop callback is defined:
        auto callback_func = result.ResolveName<PythonCallable>("handle_stop");
        if (callback_func.IsAllocated()) {
          if (auto args_info = callback_func.GetArgInfo()) {
            size_t num_args = (*args_info).max_positional_args; 
            if (num_args != 2) {
              error.SetErrorStringWithFormat("Wrong number of args for "
              "handle_stop callback, should be 2 (excluding self), got: %zu",
              num_args);
              Py_RETURN_NONE;
            } else
              return result.release();
          } else {
            error.SetErrorString("Couldn't get num arguments for handle_stop "
                                 "callback.");
            Py_RETURN_NONE;
          }
          return result.release();
        }
        else {
          error.SetErrorStringWithFormat("Class \"%s\" is missing the required "
                                         "handle_stop callback.",
                                         python_class_name);
          result.release();
        }
    }
    Py_RETURN_NONE;
}

bool
lldb_private::LLDBSwigPythonStopHookCallHandleStop
(
    void *implementor,
    lldb::ExecutionContextRefSP exc_ctx_sp,
    lldb::StreamSP stream
)
{
    // handle_stop will return a bool with the meaning "should_stop"...
    // If you return nothing we'll assume we are going to stop.
    // Also any errors should return true, since we should stop on error.

    PyErr_Cleaner py_err_cleaner(false);
    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
    auto pfunc = self.ResolveName<PythonCallable>("handle_stop");

    if (!pfunc.IsAllocated())
        return true;

    PythonObject result;
    lldb::SBExecutionContext sb_exc_ctx(exc_ctx_sp);
    PythonObject exc_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_exc_ctx));
    lldb::SBStream sb_stream;
    PythonObject sb_stream_arg(PyRefType::Owned, 
                               SBTypeToSWIGWrapper(sb_stream));
    result = pfunc(exc_ctx_arg, sb_stream_arg);

    if (PyErr_Occurred())
    {
        stream->PutCString("Python error occurred handling stop-hook.");
        PyErr_Print();
        PyErr_Clear();
        return true;
    }
    
    // Now add the result to the output stream.  SBStream only
    // makes an internally help StreamString which I can't interpose, so I 
    // have to copy it over here.
    stream->PutCString(sb_stream.GetData());
    
    if (result.get() == Py_False)
      return false;
    else
      return true;
}

// wrapper that calls an optional instance member of an object taking no arguments
static PyObject*
LLDBSwigPython_CallOptionalMember
(
    PyObject* implementor,
    char* callee_name,
    PyObject* ret_if_not_found = Py_None,
    bool* was_found = NULL
)
{
    PyErr_Cleaner py_err_cleaner(false);

    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
    auto pfunc = self.ResolveName<PythonCallable>(callee_name);

    if (!pfunc.IsAllocated())
    {
        if (was_found)
            *was_found = false;
        Py_XINCREF(ret_if_not_found);
        return ret_if_not_found;
    }

    if (was_found)
        *was_found = true;

    PythonObject result = pfunc();
    return result.release();
}

size_t
lldb_private::LLDBSwigPython_CalculateNumChildren
(
    PyObject *implementor,
    uint32_t max
)
{
    PythonObject self(PyRefType::Borrowed, implementor);
    auto pfunc = self.ResolveName<PythonCallable>("num_children");

    if (!pfunc.IsAllocated())
        return 0;

    auto arg_info = pfunc.GetArgInfo();
    if (!arg_info) {
        llvm::consumeError(arg_info.takeError());
        return 0;
    }

    size_t ret_val;
    if (arg_info.get().max_positional_args < 1)
        ret_val = unwrapOrSetPythonException(As<long long>(pfunc.Call()));
    else
        ret_val = unwrapOrSetPythonException(As<long long>(pfunc.Call(PythonInteger(max))));

    if (PyErr_Occurred())
    {
        PyErr_Print();
        PyErr_Clear();
        return 0;
    }

    if (arg_info.get().max_positional_args < 1)
        ret_val = std::min(ret_val, static_cast<size_t>(max));

    return ret_val;
}

PyObject*
lldb_private::LLDBSwigPython_GetChildAtIndex
(
    PyObject *implementor,
    uint32_t idx
)
{
    PyErr_Cleaner py_err_cleaner(true);

    PythonObject self(PyRefType::Borrowed, implementor);
    auto pfunc = self.ResolveName<PythonCallable>("get_child_at_index");

    if (!pfunc.IsAllocated())
        return nullptr;

    PythonObject result = pfunc(PythonInteger(idx));

    if (!result.IsAllocated())
        return nullptr;

    lldb::SBValue* sbvalue_ptr = nullptr;
    if (SWIG_ConvertPtr(result.get(), (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
        return nullptr;

    if (sbvalue_ptr == nullptr)
        return nullptr;

    return result.release();
}

int
lldb_private::LLDBSwigPython_GetIndexOfChildWithName
(
    PyObject *implementor,
    const char* child_name
)
{
    PyErr_Cleaner py_err_cleaner(true);

    PythonObject self(PyRefType::Borrowed, implementor);
    auto pfunc = self.ResolveName<PythonCallable>("get_child_index");

    if (!pfunc.IsAllocated())
        return UINT32_MAX;

    llvm::Expected<PythonObject> result = pfunc.Call(PythonString(child_name));

    long long retval = unwrapOrSetPythonException(As<long long>(std::move(result)));

    if (PyErr_Occurred()) { 
        PyErr_Clear(); // FIXME print this? do something else
        return UINT32_MAX;
    }

    if (retval >= 0)
        return (uint32_t)retval;

    return UINT32_MAX;
}

bool
lldb_private::LLDBSwigPython_UpdateSynthProviderInstance
(
    PyObject *implementor
)
{
    bool ret_val = false;

    static char callee_name[] = "update";

    PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name);

    if (py_return == Py_True)
        ret_val = true;

    Py_XDECREF(py_return);

    return ret_val;
}

bool
lldb_private::LLDBSwigPython_MightHaveChildrenSynthProviderInstance
(
    PyObject *implementor
)
{
    bool ret_val = false;

    static char callee_name[] = "has_children";

    PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_True);

    if (py_return == Py_True)
        ret_val = true;

    Py_XDECREF(py_return);

    return ret_val;
}

PyObject*
lldb_private::LLDBSwigPython_GetValueSynthProviderInstance
(
    PyObject *implementor
)
{
    PyObject* ret_val = nullptr;

    static char callee_name[] = "get_value";

    PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_None);

    if (py_return == Py_None || py_return == nullptr)
        ret_val = nullptr;

    lldb::SBValue* sbvalue_ptr = NULL;

    if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
        ret_val = nullptr;
    else if (sbvalue_ptr == NULL)
        ret_val = nullptr;
    else
        ret_val = py_return;

    Py_XDECREF(py_return);
    return ret_val;
}

void*
lldb_private::LLDBSWIGPython_CastPyObjectToSBData
(
    PyObject* data
)
{
    lldb::SBData* sb_ptr = nullptr;

    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBData, 0);

    if (valid_cast == -1)
        return NULL;

    return sb_ptr;
}


void*
lldb_private::LLDBSWIGPython_CastPyObjectToSBError
(
    PyObject* data
)
{
    lldb::SBError* sb_ptr = nullptr;

    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBError, 0);

    if (valid_cast == -1)
        return NULL;

    return sb_ptr;
}


void*
lldb_private::LLDBSWIGPython_CastPyObjectToSBValue
(
    PyObject* data
)
{
    lldb::SBValue* sb_ptr = NULL;

    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0);

    if (valid_cast == -1)
        return NULL;

    return sb_ptr;
}

void*
lldb_private::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo
(
    PyObject* data
)
{
    lldb::SBMemoryRegionInfo* sb_ptr = NULL;

    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBMemoryRegionInfo, 0);

    if (valid_cast == -1)
        return NULL;

    return sb_ptr;
}

bool
lldb_private::LLDBSwigPythonCallCommand
(
    const char *python_function_name,
    const char *session_dictionary_name,
    lldb::DebuggerSP& debugger,
    const char* args,
    lldb_private::CommandReturnObject& cmd_retobj,
    lldb::ExecutionContextRefSP exe_ctx_ref_sp
)
{
    lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
    lldb::SBDebugger debugger_sb(debugger);
    lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);

    PyErr_Cleaner py_err_cleaner(true);
    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);

    if (!pfunc.IsAllocated())
        return false;

    auto argc = pfunc.GetArgInfo();
    if (!argc) {
        llvm::consumeError(argc.takeError());
        return false;
    }
    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
    PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb));
    PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(cmd_retobj_sb));

    if (argc.get().max_positional_args < 5u)
        pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict);
    else
        pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg, dict);

    return true;
}

bool
lldb_private::LLDBSwigPythonCallCommandObject
(
    PyObject *implementor,
    lldb::DebuggerSP& debugger,
    const char* args,
    lldb_private::CommandReturnObject& cmd_retobj,
    lldb::ExecutionContextRefSP exe_ctx_ref_sp
)
{
    lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
    lldb::SBDebugger debugger_sb(debugger);
    lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);

    PyErr_Cleaner py_err_cleaner(true);

    PythonObject self(PyRefType::Borrowed, implementor);
    auto pfunc = self.ResolveName<PythonCallable>("__call__");

    if (!pfunc.IsAllocated())
        return false;

    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
    PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb));
    PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(cmd_retobj_sb));

    pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg);

    return true;
}

void*
lldb_private::LLDBSWIGPythonCreateOSPlugin
(
    const char *python_class_name,
    const char *session_dictionary_name,
    const lldb::ProcessSP& process_sp
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);

    if (!pfunc.IsAllocated())
        Py_RETURN_NONE;

    auto result = pfunc(ToSWIGWrapper(process_sp));

    if (result.IsAllocated())
        return result.release();

    Py_RETURN_NONE;
}

void*
lldb_private::LLDBSWIGPython_CreateFrameRecognizer
(
    const char *python_class_name,
    const char *session_dictionary_name
)
{
    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);

    if (!pfunc.IsAllocated())
        Py_RETURN_NONE;

    auto result = pfunc();

    if (result.IsAllocated())
        return result.release();

    Py_RETURN_NONE;
}

PyObject*
lldb_private::LLDBSwigPython_GetRecognizedArguments
(
    PyObject *implementor,
    const lldb::StackFrameSP& frame_sp
)
{
    static char callee_name[] = "get_recognized_arguments";

    lldb::SBFrame frame_sb(frame_sp);
    PyObject *arg = SBTypeToSWIGWrapper(frame_sb);

    PythonString str(callee_name);
    PyObject* result = PyObject_CallMethodObjArgs(implementor, str.get(), arg,
                                                  NULL);
    return result;
}

void*
lldb_private::LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp)
{
    if (!module || !setting)
        Py_RETURN_NONE;

    PyErr_Cleaner py_err_cleaner(true);
    PythonObject py_module(PyRefType::Borrowed, (PyObject *)module);
    auto pfunc = py_module.ResolveName<PythonCallable>("get_dynamic_setting");

    if (!pfunc.IsAllocated())
        Py_RETURN_NONE;

    auto result = pfunc(ToSWIGWrapper(target_sp), PythonString(setting));

    return result.release();
}

bool lldb_private::LLDBSWIGPythonRunScriptKeywordProcess(
    const char *python_function_name, const char *session_dictionary_name,
    const lldb::ProcessSP &process, std::string &output) {

    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
        return false;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);

    if (!pfunc.IsAllocated())
        return false;

    auto result = pfunc(ToSWIGWrapper(process), dict);

    output = result.Str().GetString().str();

    return true;
}

bool
lldb_private::LLDBSWIGPythonRunScriptKeywordThread
(const char* python_function_name,
const char* session_dictionary_name,
lldb::ThreadSP& thread,
std::string& output)

{
    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
        return false;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);

    if (!pfunc.IsAllocated())
        return false;

    lldb::SBThread thread_sb(thread);
    PythonObject thread_arg(PyRefType::Owned, SBTypeToSWIGWrapper(thread_sb));
    auto result = pfunc(thread_arg, dict);

    output = result.Str().GetString().str();

    return true;
}

bool lldb_private::LLDBSWIGPythonRunScriptKeywordTarget(
    const char *python_function_name, const char *session_dictionary_name,
    const lldb::TargetSP &target, std::string &output) {

    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
        return false;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name,dict);

    if (!pfunc.IsAllocated())
        return false;

    auto result = pfunc(ToSWIGWrapper(target), dict);

    output = result.Str().GetString().str();

    return true;
}

bool
lldb_private::LLDBSWIGPythonRunScriptKeywordFrame
(const char* python_function_name,
const char* session_dictionary_name,
lldb::StackFrameSP& frame,
std::string& output)

{
    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
        return false;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name,dict);

    if (!pfunc.IsAllocated())
        return false;

    lldb::SBFrame frame_sb(frame);
    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(frame_sb));
    auto result = pfunc(frame_arg, dict);

    output = result.Str().GetString().str();

    return true;
}

bool lldb_private::LLDBSWIGPythonRunScriptKeywordValue(
    const char *python_function_name, const char *session_dictionary_name,
    const lldb::ValueObjectSP &value, std::string &output) {

    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
        return false;

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);

    if (!pfunc.IsAllocated())
        return false;

    auto result = pfunc(ToSWIGWrapper(value), dict);

    output = result.Str().GetString().str();

    return true;
}

bool
lldb_private::LLDBSwigPythonCallModuleInit
(
    const char *python_module_name,
    const char *session_dictionary_name,
    lldb::DebuggerSP& debugger
)
{
    std::string python_function_name_string = python_module_name;
    python_function_name_string += ".__lldb_init_module";
    const char* python_function_name = python_function_name_string.c_str();

    PyErr_Cleaner py_err_cleaner(true);

    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);

    // This method is optional and need not exist.  So if we don't find it,
    // it's actually a success, not a failure.
    if (!pfunc.IsAllocated())
        return true;

    lldb::SBDebugger debugger_sb(debugger);
    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
    pfunc(debugger_arg, dict);

    return true;
}

lldb::ValueObjectSP
lldb_private::LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data)
{
    lldb::ValueObjectSP valobj_sp;
    if (data)
    {
        lldb::SBValue* sb_ptr = (lldb::SBValue *)data;
        valobj_sp = sb_ptr->GetSP();
    }
    return valobj_sp;
}

// For the LogOutputCallback functions
static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton) {
    if (baton != Py_None) {
      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
      PyObject *result = PyObject_CallFunction(reinterpret_cast<PyObject*>(baton), const_cast<char*>("s"), str);
	  Py_XDECREF(result);
      SWIG_PYTHON_THREAD_END_BLOCK;
    }
}
%}
