//===-- 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
    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);

    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
