//===-- SWIG Interface for SBDebugger ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

namespace lldb {

%feature("docstring",
"SBDebugger is the primordial object that creates SBTargets and provides
access to them.  It also manages the overall debugging experiences.

For example (from example/disasm.py),::

    import lldb
    import os
    import sys

    def disassemble_instructions (insts):
        for i in insts:
            print i

    ...

    # Create a new debugger instance
    debugger = lldb.SBDebugger.Create()

    # When we step or continue, don't return from the function until the process
    # stops. We do this by setting the async mode to false.
    debugger.SetAsync (False)

    # Create a target from a file and arch
    print('Creating a target for \'%s\'' % exe)

    target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)

    if target:
        # If the target is valid set a breakpoint at main
        main_bp = target.BreakpointCreateByName (fname, target.GetExecutable().GetFilename());

        print main_bp

        # Launch the process. Since we specified synchronous mode, we won't return
        # from this function until we hit the breakpoint at main
        process = target.LaunchSimple (None, None, os.getcwd())

        # Make sure the launch went ok
        if process:
            # Print some simple process info
            state = process.GetState ()
            print process
            if state == lldb.eStateStopped:
                # Get the first thread
                thread = process.GetThreadAtIndex (0)
                if thread:
                    # Print some simple thread info
                    print thread
                    # Get the first frame
                    frame = thread.GetFrameAtIndex (0)
                    if frame:
                        # Print some simple frame info
                        print frame
                        function = frame.GetFunction()
                        # See if we have debug info (a function)
                        if function:
                            # We do have a function, print some info for the function
                            print function
                            # Now get all instructions for this function and print them
                            insts = function.GetInstructions(target)
                            disassemble_instructions (insts)
                        else:
                            # See if we have a symbol in the symbol table for where we stopped
                            symbol = frame.GetSymbol();
                            if symbol:
                                # We do have a symbol, print some info for the symbol
                                print symbol
                                # Now get all instructions for this symbol and print them
                                insts = symbol.GetInstructions(target)
                                disassemble_instructions (insts)

                        registerList = frame.GetRegisters()
                        print('Frame registers (size of register set = %d):' % registerList.GetSize())
                        for value in registerList:
                            #print value
                            print('%s (number of children = %d):' % (value.GetName(), value.GetNumChildren()))
                            for child in value:
                                print('Name: ', child.GetName(), ' Value: ', child.GetValue())

                print('Hit the breakpoint at main, enter to continue and wait for program to exit or \'Ctrl-D\'/\'quit\' to terminate the program')
                next = sys.stdin.readline()
                if not next or next.rstrip('\\n') == 'quit':
                    print('Terminating the inferior process...')
                    process.Kill()
                else:
                    # Now continue to the program exit
                    process.Continue()
                    # When we return from the above function we will hopefully be at the
                    # program exit. Print out some process info
                    print process
            elif state == lldb.eStateExited:
                print('Didn\'t hit the breakpoint at main, program has exited...')
            else:
                print('Unexpected process state: %s, killing process...' % debugger.StateAsCString (state))
                process.Kill()

Sometimes you need to create an empty target that will get filled in later.  The most common use for this
is to attach to a process by name or pid where you don't know the executable up front.  The most convenient way
to do this is: ::

    target = debugger.CreateTarget('')
    error = lldb.SBError()
    process = target.AttachToProcessWithName(debugger.GetListener(), 'PROCESS_NAME', False, error)

or the equivalent arguments for :py:class:`SBTarget.AttachToProcessWithID` .") SBDebugger;
class SBDebugger
{
public:

    static void
    Initialize();

    static SBError
    InitializeWithErrorHandling();

    static void
    Terminate();

    static lldb::SBDebugger
    Create();

    static lldb::SBDebugger
    Create(bool source_init_files);

    static lldb::SBDebugger
    Create(bool source_init_files, lldb::LogOutputCallback log_callback, void *baton);

    static void
    Destroy (lldb::SBDebugger &debugger);

    static void
    MemoryPressureDetected();

    SBDebugger();

    SBDebugger(const lldb::SBDebugger &rhs);

    ~SBDebugger();

    bool
    IsValid() const;

    explicit operator bool() const;

    void
    Clear ();

    void
    SetAsync (bool b);

    bool
    GetAsync ();

    void
    SkipLLDBInitFiles (bool b);

#ifdef SWIGPYTHON
    %pythoncode %{
        def SetOutputFileHandle(self, file, transfer_ownership):
            "DEPRECATED, use SetOutputFile"
            if file is None:
                import sys
                file = sys.stdout
            self.SetOutputFile(SBFile.Create(file, borrow=True))

        def SetInputFileHandle(self, file, transfer_ownership):
            "DEPRECATED, use SetInputFile"
            if file is None:
                import sys
                file = sys.stdin
            self.SetInputFile(SBFile.Create(file, borrow=True))

        def SetErrorFileHandle(self, file, transfer_ownership):
            "DEPRECATED, use SetErrorFile"
            if file is None:
                import sys
                file = sys.stderr
            self.SetErrorFile(SBFile.Create(file, borrow=True))
    %}
#endif


    %extend {

        lldb::FileSP GetInputFileHandle() {
            return self->GetInputFile().GetFile();
        }

        lldb::FileSP GetOutputFileHandle() {
            return self->GetOutputFile().GetFile();
        }

        lldb::FileSP GetErrorFileHandle() {
            return self->GetErrorFile().GetFile();
        }
    }

    SBError
    SetInputString (const char* data);

    SBError
    SetInputFile (SBFile file);

    SBError
    SetOutputFile (SBFile file);

    SBError
    SetErrorFile (SBFile file);

    SBError
    SetInputFile (FileSP file);

    SBError
    SetOutputFile (FileSP file);

    SBError
    SetErrorFile (FileSP file);

    SBFile
    GetInputFile ();

    SBFile
    GetOutputFile ();

    SBFile
    GetErrorFile ();

    lldb::SBCommandInterpreter
    GetCommandInterpreter ();

    void
    HandleCommand (const char *command);

    lldb::SBListener
    GetListener ();

    void
    HandleProcessEvent (const lldb::SBProcess &process,
                        const lldb::SBEvent &event,
                        SBFile out,
                        SBFile err);

    void
    HandleProcessEvent (const lldb::SBProcess &process,
                        const lldb::SBEvent &event,
                        FileSP BORROWED,
                        FileSP BORROWED);

    lldb::SBTarget
    CreateTarget (const char *filename,
                  const char *target_triple,
                  const char *platform_name,
                  bool add_dependent_modules,
                  lldb::SBError& sb_error);

    lldb::SBTarget
    CreateTargetWithFileAndTargetTriple (const char *filename,
                                         const char *target_triple);

    lldb::SBTarget
    CreateTargetWithFileAndArch (const char *filename,
                                 const char *archname);

    lldb::SBTarget
    CreateTarget (const char *filename);

    %feature("docstring",
    "The dummy target holds breakpoints and breakpoint names that will prime newly created targets."
    ) GetDummyTarget;
    lldb::SBTarget GetDummyTarget();

    %feature("docstring",
    "Return true if target is deleted from the target list of the debugger."
    ) DeleteTarget;
    bool
    DeleteTarget (lldb::SBTarget &target);

    lldb::SBTarget
    GetTargetAtIndex (uint32_t idx);

    uint32_t
    GetIndexOfTarget (lldb::SBTarget target);

    lldb::SBTarget
    FindTargetWithProcessID (pid_t pid);

    lldb::SBTarget
    FindTargetWithFileAndArch (const char *filename,
                               const char *arch);

    uint32_t
    GetNumTargets ();

    lldb::SBTarget
    GetSelectedTarget ();

    void
    SetSelectedTarget (lldb::SBTarget &target);

    lldb::SBPlatform
    GetSelectedPlatform();

    void
    SetSelectedPlatform(lldb::SBPlatform &platform);

    %feature("docstring",
    "Get the number of currently active platforms."
    ) GetNumPlatforms;
    uint32_t
    GetNumPlatforms ();

    %feature("docstring",
    "Get one of the currently active platforms."
    ) GetPlatformAtIndex;
    lldb::SBPlatform
    GetPlatformAtIndex (uint32_t idx);

    %feature("docstring",
    "Get the number of available platforms."
    ) GetNumAvailablePlatforms;
    uint32_t
    GetNumAvailablePlatforms ();

    %feature("docstring", "
    Get the name and description of one of the available platforms.

    @param idx Zero-based index of the platform for which info should be
               retrieved, must be less than the value returned by
               GetNumAvailablePlatforms().") GetAvailablePlatformInfoAtIndex;
    lldb::SBStructuredData
    GetAvailablePlatformInfoAtIndex (uint32_t idx);

    lldb::SBSourceManager
    GetSourceManager ();

    // REMOVE: just for a quick fix, need to expose platforms through
    // SBPlatform from this class.
    lldb::SBError
    SetCurrentPlatform (const char *platform_name);

    bool
    SetCurrentPlatformSDKRoot (const char *sysroot);

    // FIXME: Once we get the set show stuff in place, the driver won't need
    // an interface to the Set/Get UseExternalEditor.
    bool
    SetUseExternalEditor (bool input);

    bool
    GetUseExternalEditor ();

    bool
    SetUseColor (bool use_color);

    bool
    GetUseColor () const;

    static bool
    GetDefaultArchitecture (char *arch_name, size_t arch_name_len);

    static bool
    SetDefaultArchitecture (const char *arch_name);

    lldb::ScriptLanguage
    GetScriptingLanguage (const char *script_language_name);

    static const char *
    GetVersionString ();

    static const char *
    StateAsCString (lldb::StateType state);

    static SBStructuredData GetBuildConfiguration();

    static bool
    StateIsRunningState (lldb::StateType state);

    static bool
    StateIsStoppedState (lldb::StateType state);

    bool
    EnableLog (const char *channel, const char ** types);

    void
    SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton);

    void
    DispatchInput (const void *data, size_t data_len);

    void
    DispatchInputInterrupt ();

    void
    DispatchInputEndOfFile ();

    const char *
    GetInstanceName  ();

    static SBDebugger
    FindDebuggerWithID (int id);

    static lldb::SBError
    SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name);

    static lldb::SBStringList
    GetInternalVariableValue (const char *var_name, const char *debugger_instance_name);

    bool
    GetDescription (lldb::SBStream &description);

    uint32_t
    GetTerminalWidth () const;

    void
    SetTerminalWidth (uint32_t term_width);

    lldb::user_id_t
    GetID ();

    const char *
    GetPrompt() const;

    void
    SetPrompt (const char *prompt);

    const char *
    GetReproducerPath() const;

    lldb::ScriptLanguage
    GetScriptLanguage() const;

    void
    SetScriptLanguage (lldb::ScriptLanguage script_lang);

    bool
    GetCloseInputOnEOF () const;

    void
    SetCloseInputOnEOF (bool b);

    lldb::SBTypeCategory
    GetCategory (const char* category_name);

    SBTypeCategory
    GetCategory (lldb::LanguageType lang_type);

    lldb::SBTypeCategory
    CreateCategory (const char* category_name);

    bool
    DeleteCategory (const char* category_name);

    uint32_t
    GetNumCategories ();

    lldb::SBTypeCategory
    GetCategoryAtIndex (uint32_t);

    lldb::SBTypeCategory
    GetDefaultCategory();

    lldb::SBTypeFormat
    GetFormatForType (lldb::SBTypeNameSpecifier);

    lldb::SBTypeSummary
    GetSummaryForType (lldb::SBTypeNameSpecifier);

    lldb::SBTypeFilter
    GetFilterForType (lldb::SBTypeNameSpecifier);

    lldb::SBTypeSynthetic
    GetSyntheticForType (lldb::SBTypeNameSpecifier);

    SBStructuredData GetScriptInterpreterInfo(ScriptLanguage);

    STRING_EXTENSION(SBDebugger)

    %feature("docstring",
"Launch a command interpreter session. Commands are read from standard input or
from the input handle specified for the debugger object. Output/errors are
similarly redirected to standard output/error or the configured handles.

@param[in] auto_handle_events If true, automatically handle resulting events.
@param[in] spawn_thread If true, start a new thread for IO handling.
@param[in] options Parameter collection of type SBCommandInterpreterRunOptions.
@param[in] num_errors Initial error counter.
@param[in] quit_requested Initial quit request flag.
@param[in] stopped_for_crash Initial crash flag.

@return
A tuple with the number of errors encountered by the interpreter, a boolean
indicating whether quitting the interpreter was requested and another boolean
set to True in case of a crash.

Example: ::

    # Start an interactive lldb session from a script (with a valid debugger object
    # created beforehand):
    n_errors, quit_requested, has_crashed = debugger.RunCommandInterpreter(True,
        False, lldb.SBCommandInterpreterRunOptions(), 0, False, False)") RunCommandInterpreter;
    %apply int& INOUT { int& num_errors };
    %apply bool& INOUT { bool& quit_requested };
    %apply bool& INOUT { bool& stopped_for_crash };
    void
    RunCommandInterpreter (bool auto_handle_events,
                           bool spawn_thread,
                           SBCommandInterpreterRunOptions &options,
                           int  &num_errors,
                           bool &quit_requested,
                           bool &stopped_for_crash);

    lldb::SBError
    RunREPL (lldb::LanguageType language, const char *repl_options);

#ifdef SWIGPYTHON
    %pythoncode%{
    def __iter__(self):
        '''Iterate over all targets in a lldb.SBDebugger object.'''
        return lldb_iter(self, 'GetNumTargets', 'GetTargetAtIndex')

    def __len__(self):
        '''Return the number of targets in a lldb.SBDebugger object.'''
        return self.GetNumTargets()
    %}
#endif

}; // class SBDebugger

} // namespace lldb
