diff --git a/src/text_editor/remedybg_plugin.cpp b/src/text_editor/remedybg_plugin.cpp deleted file mode 100644 index 44db089..0000000 --- a/src/text_editor/remedybg_plugin.cpp +++ /dev/null @@ -1,2263 +0,0 @@ -RegisterVariable(String, BinaryUnderDebug, "build/te.exe"); -RegisterVariable(String, RemedyBGPath, "remedybg.exe"); - -#if OS_WINDOWS - -#define RDBG_MAX_SERVERNAME_LEN 64 - -typedef uint8_t rdbg_Bool; - -// A rolling 32-bit integer is used for any command that takes or returns a UID. -// These UIDs are never persisted and as such, can change between runs of -// RemedyBG. Zero will never be a valid id. -typedef uint32_t rdbg_Id; - -// A string consists of a length followed by an UTF-8 encoded character array of -// 'length' bytes. Strings are never nul-terminated. -#pragma warning(push) -#pragma warning(disable: 4200) -#pragma pack(push, 1) -struct rdbg_String -{ - uint16_t len; - uint8_t data[0]; -}; -#pragma pack(pop) -#pragma warning(pop) - -enum rdbg_CommandResult -{ - RDBG_COMMAND_RESULT_UNKNOWN = 0, - - RDBG_COMMAND_RESULT_OK = 1, - - // Generic failure - RDBG_COMMAND_RESULT_FAIL = 2, - - // Result if the command is aborted due to a specified behavior and - // condition including RDBG_IF_DEBUGGING_TARGET_ABORT_COMMAND or - // RDBG_IF_SESSION_IS_MODIFIED_ABORT_COMMAND. The result can also be returned - // if an unnamed session is saved, prompts for a filename, and the user - // cancels this operation. - RDBG_COMMAND_RESULT_ABORTED = 3, - - // Result if the given command buffer given is less than 2 bytes or if the - // command is not one of the enumerated commands in rdbg_Command. - RDBG_COMMAND_RESULT_INVALID_COMMAND = 4, - - // Result if the response generated is too large to fit in the buffer. - RDBG_COMMAND_RESULT_BUFFER_TOO_SMALL = 5, - - // Result if an opening a file (i.e., a session, text file). - RDBG_COMMAND_RESULT_FAILED_OPENING_FILE = 6, - - // Result if saving a session fails. - RDBG_COMMAND_RESULT_FAILED_SAVING_SESSION = 7, - - // Result if the given ID is invalid. - RDBG_COMMAND_RESULT_INVALID_ID = 8, - - // Result if a command expects the target to be in a particular state (not - // debugging, debugging and suspended, or debugging and executing) and is - // not. - RDBG_COMMAND_RESULT_INVALID_TARGET_STATE = 9, - - // Result if an active configuration does not exist - RDBG_COMMAND_RESULT_FAILED_NO_ACTIVE_CONFIG = 10, - - // Result if the command does not apply to given breakpoint's kind - RDBG_COMMAND_RESULT_INVALID_BREAKPOINT_KIND = 11, -}; - -// Commands that take an rdbg_DebuggingTargetBehavior can specify what should -// happen in the case the target is being debugged. -enum rdbg_DebuggingTargetBehavior -{ - RDBG_IF_DEBUGGING_TARGET_STOP_DEBUGGING = 1, - RDBG_IF_DEBUGGING_TARGET_ABORT_COMMAND = 2 -}; - -// Commands that take an rdbg_ModifiedSessionBehavior can specify what should -// happen when there is an open, modified session. -enum rdbg_ModifiedSessionBehavior -{ - RDBG_IF_SESSION_IS_MODIFIED_SAVE_AND_CONTINUE = 1, - RDBG_IF_SESSION_IS_MODIFIED_CONTINUE_WITHOUT_SAVING = 2, - RDBG_IF_SESSION_IS_MODIFIED_ABORT_COMMAND = 3, -}; - -enum rdbg_TargetState -{ - RDBG_TARGET_STATE_NONE = 1, - RDBG_TARGET_STATE_SUSPENDED = 2, - RDBG_TARGET_STATE_EXECUTING = 3, -}; - -enum rdbg_BreakpointKind -{ - RDBG_BREAKPOINT_KIND_FUNCTION_NAME = 1, - RDBG_BREAKPOINT_KIND_FILENAME_LINE = 2, - RDBG_BREAKPOINT_KIND_ADDRESS = 3, - RDBG_BREAKPOINT_KIND_PROCESSOR = 4, -}; - -enum rdbg_ProcessorBreakpointAccessKind -{ - RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_WRITE = 1, - RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_READ_WRITE = 2, - RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_EXECUTE = 3, -}; - -enum rdbg_Command -{ - // Bring the RemedyBG window to the foreground and activate it. No additional - // arguments follow the command. Returns RDBG_COMMAND_RESULT_OK or - // RDBG_COMMAND_RESULT_FAIL. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_BRING_DEBUGGER_TO_FOREGROUND = 50, - - // Set the size and position of the RemedyBG window. - // - // [cmd :: rdbg_Command (uint16_t)] - // [x :: int32_t] - // [y :: int32_t] - // [width :: int32_t] - // [height :: int32_t] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_SET_WINDOW_POS = 51, - - // Get the size and position of the RemedyBG window. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [x :: int32_t] - // [y :: int32_t] - // [width :: int32_t] - // [height :: int32_t] - // [is_maximized: rdbg_Bool] - RDBG_COMMAND_GET_WINDOW_POS = 52, - - // Set whether to automatically bring the debugger to the foreground whenever - // the target is suspended (breakpoint hit, exception, single-step complete, - // etc.). Defaults to true if not set. - // - // [cmd :: rdbg_Command (uint16_t)] - // [bring_to_foreground_on_suspended :: rdbg_Bool (uint8_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_SET_BRING_TO_FOREGROUND_ON_SUSPENDED = 53, - - // Exit the RemedyBG application. - // - // [cmd :: rdbg_Command (uint16_t)] - // [dtb :: rdbg_DebuggingTargetBehavior (uint8_t)] - // [msb :: rdbg_ModifiedSessionBehavior (uint8_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_EXIT_DEBUGGER = 75, - - // Session - // - - // Returns whether the current session is modified, or "dirty". - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [modified :: rdbg_Bool (uint8_t)] - RDBG_COMMAND_GET_IS_SESSION_MODIFIED = 100, - - // Returns the current session's filename. If the filename has not been set - // for the session then the result will be - // RDBG_COMMAND_RESULT_UNNAMED_SESSION and the length of |filename| will be - // zero. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [filename :: rdbg_String] - RDBG_COMMAND_GET_SESSION_FILENAME = 101, - - // Creates a new session. All configurations are cleared and reset. - // - // [cmd :: rdbg_Command (uint16_t)] - // [dtb :: rdbg_DebuggingTargetBehavior (uint8_t)] - // [msb :: rdbg_ModifiedSessionBehavior (uint8_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_NEW_SESSION = 102, - - // Open a session with the given filename. - // - // [command :: rdbg_Command (uint16_t)] - // [dtb :: rdbg_DebuggingTargetBehavior (uint8_t)] - // [msb :: rdbg_ModifiedSessionBehavior (uint8_t)] - // [filename :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_OPEN_SESSION = 103, - - // Save session with its current filename. If the filename is has not been - // specified for the session the user will be prompted. To save with a - // filename see RDBG_COMMAND_SAVE_AS_SESSION, instead. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_SAVE_SESSION = 104, - - // Save session with a given filename. - // - // [cmd :: rdbg_Command (uint16_t)] - // [filename :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_SAVE_AS_SESSION = 105, - - // Retrieve a list of configurations for the current session. - // - // [cmd :: rdbg_Command (uint16_t) - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [num_configs :: uint16_t] - // .FOR(num_configs) { - // [uid :: rdbg_Id (uint32_t)] - // [command :: rdbg_String] - // [command_args :: rdbg_String] - // [working_dir :: rdbg_String] - // [environment_vars :: rdbg_String] - // [inherit_environment_vars_from_parent :: rdbg_Bool] - // [break_at_nominal_entry_point :: rdbg_Bool] - // [name :: rdbg_String] - // } - RDBG_COMMAND_GET_SESSION_CONFIGS = 106, - - // Add a new session configuration to the current session. All string - // parameters accept zero length strings. Multiple environment variables - // should be newline, '\n', separated. Returns the a unique ID for the - // configuration. - // - // Note that 'name' is currently optional. - // - // [cmd :: rdbg_Command (uint16_t) - // [command :: rdbg_String] - // [command_args :: rdbg_String] - // [working_dir :: rdbg_String] - // [environment_vars :: rdbg_String] - // [inherit_environment_vars_from_parent :: rdbg_Bool] - // [break_at_nominal_entry_point :: rdbg_Bool] - // [name :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [uid :: rdbg_Id] - RDBG_COMMAND_ADD_SESSION_CONFIG = 107, - - // Sets the active configuration for a session by configuration ID. If the - // ID is not valid for the current session - // RDBG_COMMAND_RESULT_INVALID_ID is returned. - // - // [cmd :: rdbg_Command (uint16_t) - // [id :: rdbg_Id] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_SET_ACTIVE_SESSION_CONFIG = 108, - - // Deletes a session configuration by ID. If the ID is not valid for the - // current session RDBG_COMMAND_REMOVE_SESSION_CONFIG is returned. - // - // [cmd :: rdbg_Command (uint16_t) - // [id :: rdbg_Id] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_DELETE_SESSION_CONFIG = 109, - - // Deletes all session configurations in the current session. - // - // [cmd :: rdbg_Command (uint16_t) - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_DELETE_ALL_SESSION_CONFIGS = 110, - - // Source Files - // - - // Opens the given file, if not already opened, and navigates to the - // specified line number. The line number is optional and can be elided from - // the command buffer. Returns result along with an ID for the file. - // - // [cmd :: rdbg_Command (uint16_t) - // [filename :: rdbg_String] - // [line_num :: uint32_t] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [id :: rdbg_Id] - RDBG_COMMAND_GOTO_FILE_AT_LINE = 200, - - // Close the file with the given ID. - // - // [cmd :: rdbg_Command (uint16_t)] - // [id :: rdbg_Id] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_CLOSE_FILE = 201, - - // Close all open files - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_CLOSE_ALL_FILES = 202, - - // Returns the current file. If no file is open, returns a zero ID, - // zero-length filename, and zero line number. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [id :: rdbg_Id] - // [filename :: rdbg_String] - // [line_num :: uint32_t] - RDBG_COMMAND_GET_CURRENT_FILE = 203, - - // Retrieve a list of open files. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [num_files :: uint16_t] - // .FOR(num_files) { - // [id :: rdbg_Id] - // [filename :: rdbg_String] - // [line_num :: uint32_t] - // } - RDBG_COMMAND_GET_OPEN_FILES = 204, - - // - // Debugger Control - - // Returns the target state for the current session. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [staste :: rdbg_TargetState (uint16_t)] - RDBG_COMMAND_GET_TARGET_STATE = 300, - - // If the target is stopped, i.e., not currently being debugged, then start - // debugging the active configuration. Setting break_at_entry to true will - // stop execution at the at entry point specified in the configuration: - // either the nominal entry point, such as "main" or "WinMain" or the entry - // point function as described in the PE header. If the target is already - // being debugged, this will return RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // [break_at_entry_point :: rdbg_Bool (uint8_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_START_DEBUGGING = 301, - - // Stop debugging the target. If the target is not executing this will return - // RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_STOP_DEBUGGING = 302, - - // Restart debugging if the target is being debugging (either suspended or - // executing) and the target was not attached to a process. Otherwise, - // returns RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_RESTART_DEBUGGING = 303, - - // Attach to a process by the given process-id. The value of - // |continue_execution| indicates whether the process should resume execution - // after attached. The debugger target behavior specifies what should happen - // in the case when the target is being debugged (suspended or executing). - // Can return: RDBG_COMMAND_RESULT_OK, RDBG_COMMAND_RESULT_FAIL, or - // RDBG_COMMAND_RESULT_ABORT. - // - // [cmd :: rdbg_Command (uint16_t)] - // [process_id :: uint32_t] - // [continue_execution :: rdbg_Bool] - // [dtb :: rdbg_DebuggingTargetBehavior (uint8_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_ATTACH_TO_PROCESS_BY_PID = 304, - - // Attach to a process by the given name. The first process found, in the - // case there are more than one with the same name, is used. The value of - // |continue_execution| indicates whether the process should resume execution - // after attached. The debugger target behavior specifies what should happen - // in the case when the target is being debugged (suspended or executing). - // Can return: RDBG_COMMAND_RESULT_OK, RDBG_COMMAND_RESULT_FAIL, or - // RDBG_COMMAND_RESULT_ABORT. - // - // [cmd :: rdbg_Command (uint16_t)] - // [process_name :: rdbg_String] - // [continue_execution :: rdbg_Bool] - // [dtb :: rdbg_DebuggingTargetBehavior (uint8_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_ATTACH_TO_PROCESS_BY_NAME = 305, - - // Detach from a target that is being debugged. Can return - // RDBG_COMMAND_RESULT_OK or RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_DETACH_FROM_PROCESS = 306, - - // With the target suspended, step into by line. If a function call occurs, - // this command will enter the function. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_STEP_INTO_BY_LINE = 307, - - // With the target suspended, step into by instruction. If a function call - // occurs, this command will enter the function. Can return - // RDBG_COMMAND_RESULT_OK or RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_STEP_INTO_BY_INSTRUCTION = 308, - - // With the target suspended, step into by line. If a function call occurs, - // this command step over that function and not enter it. Can return - // return RDBG_COMMAND_RESULT_OK or RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_STEP_OVER_BY_LINE = 309, - - // With the target suspended, step into by instruction. If a function call - // occurs, this command will step over that function and not enter it. Can - // return RDBG_COMMAND_RESULT_OK or RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_STEP_OVER_BY_INSTRUCTION = 310, - - // With the target suspended, continue running to the call site of the - // current function, i.e., step out. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_STEP_OUT = 311, - - // With the target suspended, continue execution. Can return - // RDBG_COMMAND_RESULT_OK or RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_CONTINUE_EXECUTION = 312, - - // When the target is not being debugged or is suspended, run to the given - // filename and line number. - // - // [cmd :: rdbg_Command (uint16_t)] - // [filename :: rdbg_String] - // [line_num :: uint32_t] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_RUN_TO_FILE_AT_LINE = 313, - - // Halt the execution of a target that is in the executing state. Can return - // RDBG_COMMAND_RESULT_OK or RDBG_COMMAND_RESULT_INVALID_TARGET_STATE. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_BREAK_EXECUTION = 314, - - // - // Breakpoints - - // Return the current list of breakpoints. These are the user requested - // breakpoints. Resolved breakpoint locations, if any, for a requested - // breakpoint can be obtained using RDBG_COMMAND_GET_BREAKPOINT_LOCATIONS. - // - // * Presently, module name is not used and will always be a zero length - // string. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [num_bps :: uint16_t] - // .FOR(num_bps) { - // [uid :: rdbg_Id] - // [enabled :: rdbg_Bool] - // [module_name :: rdbg_String] - // [condition_expr :: rdbg_String] - // [kind :: rdbg_BreakpointKind (uint8_t)] - // .SWITCH(kind) { - // .CASE(BreakpointKind_FunctionName): - // [function_name :: rdbg_String] - // [overload_id :: uint32_t] - // .CASE(BreakpointKind_FilenameLine): - // [filename :: rdbg_String] - // [line_num :: uint32_t] - // .CASE(BreakpointKind_Address): - // [address :: uint64_t] - // .CASE(BreakpointKind_Processor): - // [addr_expression :: rdbg_String] - // [num_bytes :: uint8_t] - // [access_kind :: rdbg_ProcessorBreakpointAccessKind (uint8_t)] - // } - // } - RDBG_COMMAND_GET_BREAKPOINTS = 600, - - // Return the list of resolved locations for a particular breakpoint. If the - // ID is not valid for the current session RDBG_COMMAND_RESULT_INVALID_ID is - // returned. - // - // [cmd :: rdbg_Command (uint16_t)] - // [bp_id :: rdbg_Id] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [num_locs :: uint16_t] - // .FOR(num_locs) { - // [address :: uint64_t] - // [module_name :: rdbg_String] - // [filename :: rdbg_String] - // [actual_line_num :: uint32_t] - // } - RDBG_COMMAND_GET_BREAKPOINT_LOCATIONS = 601, - - // Return a list of function overloads for the given function name. If the - // target is being debugged (suspended or executing) then returns a list of - // function overloads for the given function name, otherwise - // RDBG_COMMAND_RESULT_INVALID_TARGET_STATE is returned. Note that, - // presently, all modules are searched for the given function. - // - // [cmd :: rdbg_Command (uint16_t)] - // [function_name :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [num_overloads :: uint8_t] - // .FOR(num_overloads) { - // [overload_id :: rdbg_Id] - // [signature :: rdbg_String] - // } - RDBG_COMMAND_GET_FUNCTION_OVERLOADS = 602, - - // Request a breakpoint at the given function name and overload. Pass an - // overload ID of zero to add requested breakpoints for all functions with - // the given name. - // - // [cmd :: rdbg_Command (uint16_t)] - // [function_name :: rdbg_String] - // [overload_id :: rdbg_Id] - // [condition_expr :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_COMMAND_ADD_BREAKPOINT_AT_FUNCTION = 603, - - // Request a breakpoint at the given source file and line number. - // - // [cmd :: rdbg_Command (uint16_t)] - // [filename :: rdbg_String] - // [line_num :: uint32_t] - // [condition_expr :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_COMMAND_ADD_BREAKPOINT_AT_FILENAME_LINE = 604, - - // Request a breakpoint at the given address. - // - // [cmd :: rdbg_Command (uint16_t)] - // [address :: uint64_t] - // [condition_expr :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_COMMAND_ADD_BREAKPOINT_AT_ADDRESS = 605, - - // Add a processor (hardware) breakpoint. - // - // [cmd :: rdbg_Command (uint16_t)] - // [addr_expression :: rdbg_String] - // [num_bytes :: uint8_t] - // [access_kind :: rdbg_ProcessorBreakpointAccessKind (uint8_t)] - // [condition_expr :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_COMMAND_ADD_PROCESSOR_BREAKPOINT = 606, - - // Sets the conditional expression for the given breakpoint. Can pass in a - // zero-length string for none. - // - // [cmd :: rdbg_Command (uint16_t)] - // [bp_id :: rdbg_Id] - // [condition_expr :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_SET_BREAKPOINT_CONDITION = 607, - - // Given an existing breakpoint of type RDBG_BREAKPOINT_KIND_FILENAME_LINE, - // update its line number to the given one-based value. - // - // [cmd :: rdbg_Command (uint16_t)] - // [bp_id :: rdbg_Id] - // [line_num :: uint32_t] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_UPDATE_BREAKPOINT_LINE = 608, - - // Enable or disable an existing breakpoint. - // - // [cmd :: rdbg_Command (uint16_t)] - // [bp_id :: rdbg_Id] - // [enable :: rdbg_Bool] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_ENABLE_BREAKPOINT = 609, - - // Delete an existing breakpoint. - // - // [cmd :: rdbg_Command (uint16_t)] - // [bp_id :: rdbg_Id] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_DELETE_BREAKPOINT = 610, - - // Delete all existing breakpoints. - // - // [cmd :: rdbg_Command (uint16_t)] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_DELETE_ALL_BREAKPOINTS = 611, - - // Return information about a specific user requested breakpoint. - // - // * Presently, module name is not used and will always be a zero length - // string. - // - // [cmd :: rdbg_Command (uint16_t)] - // [bp_id :: rdbg_Id] - // => - // [uid :: rdbg_Id] - // [enabled :: rdbg_Bool] - // [module_name :: rdbg_String] - // [condition_expr :: rdbg_String] - // [kind :: rdbg_BreakpointKind (uint8_t)] - // .SWITCH(kind) { - // .CASE(BreakpointKind_FunctionName): - // [function_name :: rdbg_String] - // [overload_id :: uint32_t] - // .CASE(BreakpointKind_FilenameLine): - // [filename :: rdbg_String] - // [line_num :: uint32_t] - // .CASE(BreakpointKind_Address): - // [address :: uint64_t] - // .CASE(BreakpointKind_Processor): - // [addr_expression :: rdbg_String] - // [num_bytes :: uint8_t] - // [access_kind :: rdbg_ProcessorBreakpointAccessKind (uint8_t)] - // } - RDBG_COMMAND_GET_BREAKPOINT = 612, - - // - // Watch Window Expressions - - // Return a list of watch expressions for the given, one-based watch window, - // presently ranging in [1,8]. - // - // [cmd :: rdbg_Command (uint16_t)] - // [window_num :: uint8_t] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [num_watches :: uint16_t] - // .FOR(num_watches) { - // [uid :: rdbg_Id] - // [expr :: rdbg_String] - // [comment :: rdbg_String] - // } - RDBG_COMMAND_GET_WATCHES = 700, - - // Add a watch expresion to the given, one-based watch window. Presently, - // only single line comments are supported. Spaces will replace any newlines - // found in a comment. - // - // [cmd :: rdbg_Command (uint16_t)] - // [window_num :: uint8_t] - // [expr :: rdbg_String] - // [comment :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - // [uid :: rdbg_Id] - RDBG_COMMAND_ADD_WATCH = 701, - - // Updates the expression for a given watch - // - // [cmd :: rdbg_Command (uint16_t)] - // [uid :: rdbg_Id] - // [expr :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_UPDATE_WATCH_EXPRESSION = 702, - - // Updates the comment for a given watch - // - // [cmd :: rdbg_Command (uint16_t)] - // [uid :: rdbg_Id] - // [comment :: rdbg_String] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_UPDATE_WATCH_COMMENT = 703, - - // Delete the given watch - // - // [cmd :: rdbg_Command (uint16_t)] - // [uid :: rdbg_Id] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_DELETE_WATCH = 704, - - // Delete all watches in the given watch window - // - // [cmd :: rdbg_Command (uint16_t)] - // [window_num :: uint8_t] - // -> - // [result :: rdbg_CommandResult (uint16_t)] - RDBG_COMMAND_DELETE_ALL_WATCHES = 705, -}; - -enum rdbg_SourceLocChangedReason -{ - RDBG_SOURCE_LOC_CHANGED_REASON_UNSPECIFIED = 0, - - // An open-file from the command-line updated the source location - RDBG_SOURCE_LOC_CHANGED_REASON_BY_COMMAND_LINE = 1, - - // A RDBG_COMMAND_GOTO_FILE_AT_LINE from a named-pipes driver updated the source location - RDBG_SOURCE_LOC_CHANGED_REASON_BY_DRIVER = 2, - - // A selection of a breakpoint in breakpoints pane updated the source location - RDBG_SOURCE_LOC_CHANGED_REASON_BREAKPOINT_SELECTED = 3, - - // The current stack frame was changed in the callstack pane and updated the source location - RDBG_SOURCE_LOC_CHANGED_REASON_CURRENT_FRAME_CHANGED = 4, - - // The active thread was changed in the threads pane and updated the source location - RDBG_SOURCE_LOC_CHANGED_REASON_ACTIVE_THREAD_CHANGED = 5, - - // - // The process was suspended and updated the source location - // - RDBG_SOURCE_LOC_CHANGED_REASON_BREAKPOINT_HIT = 6, - RDBG_SOURCE_LOC_CHANGED_REASON_EXCEPTION_HIT = 7, - RDBG_SOURCE_LOC_CHANGED_REASON_STEP_OVER = 8, - RDBG_SOURCE_LOC_CHANGED_REASON_STEP_IN = 9, - RDBG_SOURCE_LOC_CHANGED_REASON_STEP_OUT = 10, - RDBG_SOURCE_LOC_CHANGED_REASON_NON_USER_BREAKPOINT = 11, - RDBG_SOURCE_LOC_CHANGED_REASON_DEBUG_BREAK = 12, -}; - -enum rdbg_DebugEventKind -{ - // A target being debugged has exited. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [exit_code :: uint32_t] - RDBG_DEBUG_EVENT_KIND_EXIT_PROCESS = 100, - - // The target for the active configuration is now being debugged. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [process_id :: uint32_t] - RDBG_DEBUG_EVENT_KIND_TARGET_STARTED = 101, - - // The debugger has attached to a target process. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [process_id :: uint32_t] - RDBG_DEBUG_EVENT_KIND_TARGET_ATTACHED = 102, - - // The debugger has detached from a target process. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [process_id :: uint32_t] - RDBG_DEBUG_EVENT_KIND_TARGET_DETACHED = 103, - - // The debugger has transitioned from suspended to executing. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [process_id :: uint32_t] - RDBG_DEBUG_EVENT_KIND_TARGET_CONTINUED = 104, - - // The source location changed due to an event in the debugger. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [filename :: rdbg_String] - // [line_num :: uint32_t] - // [reason :: rdbg_SourceLocChangedReason (uint16_t) ] - RDBG_DEBUG_EVENT_KIND_SOURCE_LOCATION_CHANGED = 200, - - // An external text editor was requested to be launched for the current file - // and line number. The event is sent even if an external text editor is not - // configured and, if configured, even if the external text editor failed to - // launch for any reason. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [filename :: rdbg_String] - // [line_num :: uint32_t] - RDBG_DEBUG_EVENT_KIND_EXTERNAL_TEXT_EDITOR_LAUNCHED = 201, - - // A user breakpoint was hit - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_DEBUG_EVENT_KIND_BREAKPOINT_HIT = 600, - - // The breakpoint with the given ID has been resolved (has a valid location). - // This can happen if the breakpoint was set in module that became loaded, - // for instance. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_DEBUG_EVENT_KIND_BREAKPOINT_RESOLVED = 601, - - // A new user breakpoint was added. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_DEBUG_EVENT_KIND_BREAKPOINT_ADDED = 602, - - // A user breakpoint was modified. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_DEBUG_EVENT_KIND_BREAKPOINT_MODIFIED = 603, - - // A user breakpoint was removed. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [bp_id :: rdbg_Id] - RDBG_DEBUG_EVENT_KIND_BREAKPOINT_REMOVED = 604, - - // An OutputDebugString was received by the debugger. The given string will - // be UTF-8 encoded. - // - // [kind :: rdbg_DebugEventKind (uint16_t)] - // [str :: rdbg_String] - RDBG_DEBUG_EVENT_KIND_OUTPUT_DEBUG_STRING = 800, -}; - -// Sample usage of driving an instance of RemedyBG using named pipes. -// -// To use: first, start an named instance of RemedyBG using the "--servername" -// switch. -// -// remedybg.exe --servername {name} -// -// After RemedyBG is started, this sample can be run to control and make queries -// to the running instance. -// -// driver {name} -// -// The sample code demonstrates the usage of both these pipes and is written -// using non-overlapped IO for simplicity. Depending on your application, using -// non-blocking IO may be preferable. - - -#define COMMAND_BUF_SIZE 8192 -#define REPLY_BUF_SIZE 8192 -#define ERROR_MSG_LEN 512 - -enum PipeType -{ - DebugControlPipe, - DebugEventsPipe -}; - -struct rdb_Buffer -{ - uint8_t* data; - uint8_t* curr; - uint32_t capacity; - - bool err; // true if overflow (read or write) on the buffer -}; - -static void ReinitBuffer(struct rdb_Buffer* buf) -{ - buf->curr = buf->data; - buf->err = false; -} - -struct ClientContext -{ - HANDLE command_pipe_handle; - - struct rdb_Buffer cmd; - struct rdb_Buffer reply; - - // Stateful behavior so we don't have to pass these to every command that - // needs them. - enum rdbg_DebuggingTargetBehavior dbg_target_behavior; - enum rdbg_ModifiedSessionBehavior mod_session_behavior; - - char last_error[ERROR_MSG_LEN]; -}; - -static void WriteError(int err_msg_len, char* err_msg, char* format, ...) -{ - va_list args; - va_start(args, format); - - int n = vsnprintf(err_msg, err_msg_len, format, args); - if (n > 0) - { - FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, GetLastError(), 0, err_msg + n, - err_msg_len - n, 0); - } - - va_end(args); -} - -static bool ContextHadError(struct ClientContext* ctx) -{ - return ctx->last_error[0] != 0 || ctx->cmd.err || ctx->reply.err; -} - -// -// Utilities for working with a ClientContext buffers -// -#define SetErrIfOverwrite(buf, sz) \ - (buf)->err = (buf)->err || ((buf)->curr > ((buf)->data + (buf)->capacity) - sz) - -#define PushBuffer(buf, ty, val) \ - SetErrIfOverwrite(buf, sizeof(ty)); \ - if (!(buf)->err) { *(ty*)((buf)->curr) = (val); (buf)->curr += sizeof(ty); } - -#define PushCommand(buf, cmd) PushBuffer(buf, uint16_t, (uint16_t)(cmd)) -#define PushDebuggingTargetBehavior(buf, dtb) \ - PushBuffer(buf, uint8_t, (uint8_t)dtb) -#define PushModifiedSessionBehavior(buf, msb) \ - PushBuffer(buf, uint8_t, (uint8_t)msb) -#define PushBool(buf, val) PushBuffer(buf, uint8_t, (uint8_t)(val)) -#define PushId(buf, val) PushBuffer(buf, rdbg_Id, (rdbg_Id)(val)) -#define PushU8(buf, val) PushBuffer(buf, uint8_t, (uint8_t)(val)) -#define PushU32(buf, val) PushBuffer(buf, uint32_t, (uint32_t)(val)) -#define PushS32(buf, val) PushBuffer(buf, int32_t, (int32_t)(val)) -#define PushU64(buf, val) PushBuffer(buf, uint64_t, (uint64_t)(val)) -#define PushProcessorBreakpointAccessKind(buf, akind) \ - PushBuffer(buf, uint8_t, (uint8_t)akind) - -static void PushStringZ(struct rdb_Buffer* b, char* str) -{ - uint16_t len = str ? (uint16_t)strlen(str) : 0; - PushBuffer(b, uint16_t, len); - SetErrIfOverwrite(b, len); - if (!b->err && len > 0) - { - memcpy(b->curr, str, len); - b->curr += len; - } -} - -#define PopBuffer(buf, ty) ( \ - (buf)->err = (buf)->err || \ - ((buf)->curr > ((buf)->data + (buf)->capacity) - sizeof(ty)), \ - (buf)->curr += ((buf)->err == 0 ? sizeof(ty) : 0), \ - (buf)->err == 0 ? *(ty*)((buf)->curr - sizeof(ty)) : (ty)0 ) - -#define PopBool(buf) (rdbg_Bool)PopBuffer(buf, uint8_t) -#define PopU8(buf) PopBuffer(buf, uint8_t) -#define PopU16(buf) PopBuffer(buf, uint16_t) -#define PopU32(buf) PopBuffer(buf, uint32_t) -#define PopS32(buf) PopBuffer(buf, int32_t) -#define PopU64(buf) PopBuffer(buf, uint64_t) -#define PopId(buf) (rdbg_Id)PopU32(buf) -#define PopCommandResult(buf) (enum rdbg_CommandResult)PopBuffer(buf, uint16_t) -#define PopTargetState(buf) (enum rdbg_TargetState)PopBuffer(buf, uint16_t) -#define PopBreakpointKind(buf) (enum rdbg_BreakpointKind)PopBuffer(buf, uint8_t) -#define PopProcessorBreakpointAccessKind(buf) \ - (enum rdbg_ProcessorBreakpointAccessKind)PopBuffer(buf, uint8_t) -#define PopDebugEventKind(buf) (enum rdbg_DebugEventKind)PopBuffer(buf, uint16_t) - -static void PopString(struct rdb_Buffer* buf, struct rdbg_String** str) -{ - uint16_t len = PopBuffer(buf, uint16_t); - buf->err = buf->err || buf->curr > buf->data + buf->capacity + len; - if (!buf->err) - { - *str = (struct rdbg_String*)(buf->curr - sizeof(uint16_t)); - buf->curr += len; - } - else - { - *str = 0; - } -} - -#define PIPE_NAME_PREFIX "\\\\.\\pipe\\" -#define PIPE_NAME_PREFIX_LEN 9 - -bool InitConnection(char* server_name, enum PipeType pipe_type, - int last_error_len, char* last_error, HANDLE* ret_pipe_handle) -{ - bool result = false; - - unsigned len = (unsigned)strlen(server_name); - if (len <= RDBG_MAX_SERVERNAME_LEN) - { - char pipe_name[256] = PIPE_NAME_PREFIX; - strcat(pipe_name, server_name); - if (pipe_type == DebugEventsPipe) - { - strcat(pipe_name, "-events"); - } - - DWORD flags = pipe_type == DebugControlPipe ? - GENERIC_READ | GENERIC_WRITE : - GENERIC_READ | FILE_WRITE_ATTRIBUTES; - - HANDLE pipe_handle = CreateFile(pipe_name, flags, 0, NULL, OPEN_EXISTING, - 0, NULL); - if (pipe_handle != INVALID_HANDLE_VALUE) - { - DWORD new_mode = PIPE_READMODE_MESSAGE; - if (SetNamedPipeHandleState(pipe_handle, &new_mode, NULL, NULL)) - { - *ret_pipe_handle = pipe_handle; - result = true; - } - else - { - WriteError(last_error_len, last_error, - "SetNamedPipeHandleState failed: "); - CloseHandle(pipe_handle); - } - } - else - { - WriteError(last_error_len, last_error, "CreateFile failed: "); - } - } - else - { - WriteError(last_error_len, last_error, "Server name too long."); - } - - return result; -} - -static void CloseConnection(struct ClientContext* ctx) -{ - CloseHandle(ctx->command_pipe_handle); -} - -static void TransactCommand(struct ClientContext* ctx) -{ - DWORD bytes_read = 0; - BOOL res = 0; - struct rdb_Buffer* reply = &ctx->reply; - - ReinitBuffer(reply); - - if (!ContextHadError(ctx)) - { - uint8_t* write_ptr = reply->data; - - res = TransactNamedPipe(ctx->command_pipe_handle, ctx->cmd.data, - (uint32_t)(ctx->cmd.curr - ctx->cmd.data), write_ptr, - REPLY_BUF_SIZE, &bytes_read, NULL); - write_ptr += bytes_read; - - while (!res && GetLastError() == ERROR_MORE_DATA) - { - int bytes_left = REPLY_BUF_SIZE - (int)(write_ptr - reply->data); - if (bytes_left > 0) - { - res = ReadFile(ctx->command_pipe_handle, write_ptr, bytes_left, - &bytes_read, NULL); - write_ptr += bytes_read; - } - else - break; // reply buffer full - } - if (res) - { - reply->capacity = (uint32_t)(write_ptr - reply->data); - } - else - { - WriteError(sizeof(ctx->last_error), ctx->last_error, - "TransactCommand failed: "); - } - } -} - -#define BeginCommand(ctx, c) \ - ReinitBuffer(&((ctx)->cmd)); \ - PushCommand(&((ctx)->cmd), c) - -#define SendCommand(ctx, c, res) \ - BeginCommand(ctx, c); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define BeginCommandWithFlags(ctx, c) \ - BeginCommand(ctx, c); \ - PushDebuggingTargetBehavior(&((ctx)->cmd), (ctx)->dbg_target_behavior); \ - PushModifiedSessionBehavior(&((ctx)->cmd), (ctx)->mod_session_behavior) - -#define SendCommandWithFlags(ctx, c, res) \ - BeginCommandWithFlags(ctx, c); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define BringDebuggerToForeground(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_BRING_DEBUGGER_TO_FOREGROUND, res) - -#define SetDebuggerWindowPos(ctx, x, y, cx, cy, res) \ - BeginCommand(ctx, RDBG_COMMAND_SET_WINDOW_POS); \ - PushS32(&(ctx)->cmd, x); \ - PushS32(&(ctx)->cmd, y); \ - PushS32(&(ctx)->cmd, cx); \ - PushS32(&(ctx)->cmd, cy); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define GetDebuggerWindowPos(ctx, res, x, y, cx, cy, is_maximized) \ - SendCommand(ctx, RDBG_COMMAND_GET_WINDOW_POS, res); \ - *(x) = PopId(&((ctx)->reply)); \ - *(y) = PopId(&((ctx)->reply)); \ - *(cx) = PopId(&((ctx)->reply)); \ - *(cy) = PopId(&((ctx)->reply)); \ - *(is_maximized) = PopBool(&((ctx)->reply)) != 0 - -#define SetBringToForegroundOnSuspended(ctx, btfos, res) \ - BeginCommand(ctx, RDBG_COMMAND_SET_BRING_TO_FOREGROUND_ON_SUSPENDED); \ - PushBool(&(ctx)->cmd, btfos); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define ExitDebugger(ctx, res) \ - SendCommandWithFlags(ctx, RDBG_COMMAND_EXIT_DEBUGGER, res) - -#define GetIsSessionModified(ctx, res, is_modified) \ - SendCommand(ctx, RDBG_COMMAND_GET_IS_SESSION_MODIFIED, res); \ - *(is_modified) = PopBool(&((ctx)->reply)) != 0 - -#define GetSessionFilename(ctx, res, filename) \ - SendCommand(ctx, RDBG_COMMAND_GET_SESSION_FILENAME, res); \ - PopString(&((ctx)->reply), filename) - -#define NewSession(ctx, res) \ - SendCommandWithFlags(ctx, RDBG_COMMAND_NEW_SESSION, res) - -#define SendCommandWithString(ctx, c, str, res) \ - BeginCommand(ctx, c); \ - PushStringZ(&(ctx)->cmd, str); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define OpenSession(ctx, filename, res) \ - SendCommandWithString(ctx, RDBG_COMMAND_OPEN_SESSION, filename, res) - -#define SaveSession(ctx, res) \ - SendCommandWithFlags(ctx, RDBG_COMMAND_SAVE_SESSION, res) - -#define SaveAsSession(ctx, filename, res) \ - SendCommandWithString(ctx, RDBG_COMMAND_SAVE_AS_SESSION, filename, res) - -#define GetSessionConfigs(ctx, res, cfg_it) \ - SendCommand(ctx, RDBG_COMMAND_GET_SESSION_CONFIGS, res); \ - BufIterator_Init(cfg_it, PopBuffer(&((ctx)->reply), uint16_t), \ - ((ctx)->reply)) - -#define AddSessionConfig(ctx, command, args, wdir, env, inh, brk, res, id) \ - BeginCommand(ctx, RDBG_COMMAND_ADD_SESSION_CONFIG); \ - PushStringZ(&(ctx)->cmd, command); \ - PushStringZ(&(ctx)->cmd, args); \ - PushStringZ(&(ctx)->cmd, wdir); \ - PushStringZ(&(ctx)->cmd, env); \ - PushBool(&(ctx)->cmd, inh); \ - PushBool(&(ctx)->cmd, brk); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - *(id) = PopId(&((ctx)->reply)) - -#define SendCommandWithId(ctx, c, id, res) \ - BeginCommand(ctx, c); \ - PushId(&(ctx)->cmd, id); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define SetActiveSessionConfig(ctx, id, res) \ - SendCommandWithId(ctx, RDBG_COMMAND_SET_ACTIVE_SESSION_CONFIG, id, res) - -#define DeleteSessionConfig(ctx, id, res) \ - SendCommandWithId(ctx, RDBG_COMMAND_DELETE_SESSION_CONFIG, id, res) - -#define DeleteAllSessionConfigs(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_DELETE_ALL_SESSION_CONFIGS, res) - -#define GoToFileAtLine(ctx, filename, line, res, id) \ - BeginCommand(ctx, RDBG_COMMAND_GOTO_FILE_AT_LINE); \ - PushStringZ(&(ctx)->cmd, filename); \ - PushBuffer(&(ctx)->cmd, uint32_t, line); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - *(id) = PopId(&((ctx)->reply)) - -#define CloseFileById(ctx, id, res) \ - SendCommandWithId(ctx, RDBG_COMMAND_CLOSE_FILE, id, res) - -#define CloseAllFiles(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_CLOSE_ALL_FILES, res) - -#define GetCurrentFile(ctx, res, file_id, filename, line_num) \ - SendCommand(ctx, RDBG_COMMAND_GET_CURRENT_FILE, res); \ - *(file_id) = PopId(&(ctx)->reply); \ - PopString(&(ctx)->reply, filename); \ - *(line_num) = PopBuffer(&(ctx)->reply, uint32_t) - -#define GetOpenFiles(ctx, res, file_it) \ - SendCommand(ctx, RDBG_COMMAND_GET_OPEN_FILES, res); \ - BufIterator_Init(file_it, PopBuffer(&((ctx)->reply), uint16_t), ((ctx)->reply)) - -#define StartDebugging(ctx, break_at_entry_point, res) \ - BeginCommand(ctx, RDBG_COMMAND_START_DEBUGGING); \ - PushBool(&(ctx)->cmd, break_at_entry_point); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define StopDebugging(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_STOP_DEBUGGING, res) - -#define RestartDebugging(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_RESTART_DEBUGGING, res) - -#define AttachToProcessById(ctx, pid, cnt, res) \ - BeginCommand(ctx, RDBG_COMMAND_ATTACH_TO_PROCESS_BY_PID); \ - PushBuffer(&(ctx)->cmd, uint32_t, (uint32_t)(pid)); \ - PushBool(&(ctx)->cmd, cnt); \ - PushDebuggingTargetBehavior(&((ctx)->cmd), (ctx)->dbg_target_behavior); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define AttachToProcessByName(ctx, name, cnt, res) \ - BeginCommand(ctx, RDBG_COMMAND_ATTACH_TO_PROCESS_BY_NAME); \ - PushStringZ(&(ctx)->cmd, name); \ - PushBool(&(ctx)->cmd, cnt); \ - PushDebuggingTargetBehavior(&((ctx)->cmd), (ctx)->dbg_target_behavior); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define DetachFromProcess(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_DETACH_FROM_PROCESS, res) - -#define StepIntoByLine(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_STEP_INTO_BY_LINE, res) - -#define StepIntoByInstruction(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_STEP_INTO_BY_INSTRUCTION, res) - -#define StepOverByLine(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_STEP_OVER_BY_LINE, res) - -#define StepOverByInstruction(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_STEP_OVER_BY_INSTRUCTION, res) - -#define StepOut(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_STEP_OUT, res) - -#define ContinueExecution(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_CONTINUE_EXECUTION, res) - -#define RunToFileAtLine(ctx, filename, line, res) \ - BeginCommand(ctx, RDBG_COMMAND_RUN_TO_FILE_AT_LINE); \ - PushStringZ(&(ctx)->cmd, filename); \ - PushBuffer(&(ctx)->cmd, uint32_t, line); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define BreakExecution(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_BREAK_EXECUTION, res) - -#define GetTargetState(ctx, res, state) \ - SendCommand(ctx, RDBG_COMMAND_GET_TARGET_STATE, res); \ - *(state) = PopTargetState(&((ctx)->reply)) - -#define GetAllBreakpoints(ctx, res, bp_it) \ - SendCommand(ctx, RDBG_COMMAND_GET_BREAKPOINTS, res); \ - BufIterator_Init(bp_it, PopBuffer(&((ctx)->reply), uint16_t), ((ctx)->reply)) - -#define GetBreakpoint(ctx, id, res, bp) \ - SendCommandWithId(ctx, RDBG_COMMAND_GET_BREAKPOINT, id, res); \ - PopBreakpoint(&((ctx)->reply), bp) - -#define GetBreakpointLocations(ctx, id, res, num_locs) \ - SendCommandWithId(ctx, RDBG_COMMAND_GET_BREAKPOINT_LOCATIONS, id, res); \ - *(num_locs) = PopU16(&((ctx)->reply)) - -#define GetFunctionOverloads(ctx, res, fn_name, fno_it) \ - BeginCommand(ctx, RDBG_COMMAND_GET_FUNCTION_OVERLOADS); \ - PushStringZ(&(ctx)->cmd, fn_name); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - BufIterator_Init(fno_it, PopU8(&((ctx)->reply)), ((ctx)->reply)) - -#define AddBreakpointAtFn(ctx, fn_name, oid, cond, res, bp_id) \ - BeginCommand(ctx, RDBG_COMMAND_ADD_BREAKPOINT_AT_FUNCTION); \ - PushStringZ(&(ctx)->cmd, fn_name); \ - PushId(&(ctx)->cmd, oid) \ - PushStringZ(&(ctx)->cmd, cond); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - *(bp_id) = PopId(&((ctx)->reply)) - -#define AddBreakpointAtFilenameLine(ctx, file, line, cond, res, bp_id) \ - BeginCommand(ctx, RDBG_COMMAND_ADD_BREAKPOINT_AT_FILENAME_LINE); \ - PushStringZ(&(ctx)->cmd, file); \ - PushU32(&(ctx)->cmd, line) \ - PushStringZ(&(ctx)->cmd, cond); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - *(bp_id) = PopId(&((ctx)->reply)) - -#define AddBreakpointAtAddress(ctx, addr, cond, res, bp_id) \ - BeginCommand(ctx, RDBG_COMMAND_ADD_BREAKPOINT_AT_ADDRESS); \ - PushU64(&(ctx)->cmd, addr) \ - PushStringZ(&(ctx)->cmd, cond); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - *(bp_id) = PopId(&((ctx)->reply)) - -#define AddProcessorBreakpoint(ctx, addr_expr, nbytes, akind, cond, res, bp_id) \ - BeginCommand(ctx, RDBG_COMMAND_ADD_PROCESSOR_BREAKPOINT); \ - PushStringZ(&(ctx)->cmd, addr_expr); \ - PushU8(&(ctx)->cmd, nbytes); \ - PushProcessorBreakpointAccessKind(&(ctx)->cmd, akind); \ - PushStringZ(&(ctx)->cmd, cond); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - *(bp_id) = PopId(&((ctx)->reply)) - -#define SetBreakpointCondition(ctx, bp_id, cond, res) \ - BeginCommand(ctx, RDBG_COMMAND_SET_BREAKPOINT_CONDITION); \ - PushId(&(ctx)->cmd, bp_id) \ - PushStringZ(&(ctx)->cmd, cond); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define UpdateBreakpointLine(ctx, bp_id, line, res) \ - BeginCommand(ctx, RDBG_COMMAND_UPDATE_BREAKPOINT_LINE); \ - PushId(&(ctx)->cmd, bp_id); \ - PushU32(&(ctx)->cmd, line); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define EnableBreakpoint(ctx, bp_id, enable, res) \ - BeginCommand(ctx, RDBG_COMMAND_ENABLE_BREAKPOINT); \ - PushId(&(ctx)->cmd, bp_id); \ - PushBool(&(ctx)->cmd, enable); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define DeleteBreakpoint(ctx, bp_id, res) \ - BeginCommand(ctx, RDBG_COMMAND_DELETE_BREAKPOINT); \ - PushId(&(ctx)->cmd, bp_id); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define DeleteAllBreakpoints(ctx, res) \ - SendCommand(ctx, RDBG_COMMAND_DELETE_ALL_BREAKPOINTS, res) - -#define GetWatches(ctx, window_num, res, it) \ - BeginCommand(ctx, RDBG_COMMAND_GET_WATCHES); \ - PushU8(&(ctx)->cmd, window_num); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - BufIterator_Init(it, PopU16(&((ctx)->reply)), ((ctx)->reply)) - -#define AddWatch(ctx, window_num, expr, comment, res, id) \ - BeginCommand(ctx, RDBG_COMMAND_ADD_WATCH); \ - PushU8(&(ctx)->cmd, window_num); \ - PushStringZ(&(ctx)->cmd, expr); \ - PushStringZ(&(ctx)->cmd, comment); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)); \ - *id = PopId(&((ctx)->reply)) - -#define UpdateWatchExpression(ctx, id, expr, res) \ - BeginCommand(ctx, RDBG_COMMAND_UPDATE_WATCH_EXPRESSION); \ - PushId(&(ctx)->cmd, id); \ - PushStringZ(&(ctx)->cmd, expr); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define UpdateWatchComment(ctx, id, comment, res) \ - BeginCommand(ctx, RDBG_COMMAND_UPDATE_WATCH_COMMENT); \ - PushId(&(ctx)->cmd, id); \ - PushStringZ(&(ctx)->cmd, comment); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -#define DeleteWatch(ctx, id, res) \ - SendCommandWithId(ctx, RDBG_COMMAND_DELETE_WATCH, id, res) - -#define DeleteAllWatches(ctx, window_num, res) \ - BeginCommand(ctx, RDBG_COMMAND_DELETE_ALL_WATCHES); \ - PushU8(&(ctx)->cmd, window_num); \ - TransactCommand((ctx)); \ - *(res) = PopCommandResult(&((ctx)->reply)) - -struct BufIterator -{ - int n; - int cur_idx; - struct rdb_Buffer buf; -}; - -static void BufIterator_Init(struct BufIterator* it, int n, - struct rdb_Buffer b) -{ - it->n = n; - it->cur_idx = -1; - - // Make a copy of reply buffer so we can make additional calls within loop. - static uint8_t it_buf[REPLY_BUF_SIZE]; - it->buf.data = it_buf; - it->buf.curr = it_buf + (b.curr - b.data); - it->buf.capacity = b.capacity; - it->buf.err = b.err; - if (!b.err) - { - memcpy(it->buf.data, b.data, b.capacity); - } -} - -struct SessionConfig -{ - rdbg_Id id; - struct rdbg_String* command; - struct rdbg_String* command_args; - struct rdbg_String* working_dir; - struct rdbg_String* environment_vars; - rdbg_Bool inherit_environment_vars_from_parent; - rdbg_Bool break_at_nominal_entry_point; -}; - -static bool SessionConfigIt_Next(struct BufIterator* it, - struct SessionConfig* cfg) -{ - bool result = false; - if (++it->cur_idx < it->n) - { - struct rdb_Buffer* b = &it->buf; - - cfg->id = PopId(b); - PopString(b, &cfg->command); - PopString(b, &cfg->command_args); - PopString(b, &cfg->working_dir); - PopString(b, &cfg->environment_vars); - cfg->inherit_environment_vars_from_parent = PopBool(b); - cfg->break_at_nominal_entry_point = PopBool(b); - - result = true; - } - return result; -} - -struct File -{ - rdbg_Id id; - struct rdbg_String* filename; - uint32_t line_num; -}; - -static bool FileIt_Next(struct BufIterator* it, struct File* file) -{ - bool result = false; - if (++it->cur_idx < it->n) - { - struct rdb_Buffer* b = &it->buf; - - file->id = PopId(b); - PopString(b, &file->filename); - file->line_num = PopBuffer(b, uint32_t); - - result = true; - } - return result; -} - -struct Breakpoint -{ - rdbg_Id uid; - rdbg_Bool enabled; - struct rdbg_String* module_name; - struct rdbg_String* condition_expr; - enum rdbg_BreakpointKind kind; - union - { - struct - { - struct rdbg_String* function_name; - rdbg_Id overload_id; - }; - struct - { - struct rdbg_String* filename; - uint32_t line_num; - }; - uint64_t address; - struct - { - struct rdbg_String* expression; - uint8_t num_bytes; - enum rdbg_InternalProcessorBreakpointType access_kind; - }; - }; -}; - -struct BreakpointLocation -{ - uint64_t address; - struct rdbg_String* module_name; - struct rdbg_String* filename; - uint32_t actual_line_num; -}; - -static char* BreakpointKindToString(enum rdbg_BreakpointKind kind) -{ - char* result = ""; - switch (kind) - { - case RDBG_BREAKPOINT_KIND_FUNCTION_NAME: - result = "RDBG_BREAKPOINT_KIND_FUNCTION_NAME"; - break; - case RDBG_BREAKPOINT_KIND_FILENAME_LINE: - result = "RDBG_BREAKPOINT_KIND_FILENAME_LINE"; - break; - case RDBG_BREAKPOINT_KIND_ADDRESS: - result = "RDBG_BREAKPOINT_KIND_ADDRESS"; - break; - case RDBG_BREAKPOINT_KIND_PROCESSOR: - result = "RDBG_BREAKPOINT_KIND_PROCESSOR"; - break; - } - return result; -} - -char *ProcessorBreakpointAccessKindToString( - enum rdbg_ProcessorBreakpointAccessKind kind) -{ - char* result = ""; - switch (kind) - { - case RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_WRITE: - result = "RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_WRITE"; - break; - case RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_READ_WRITE: - result = "RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_READ_WRITE"; - break; - case RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_EXECUTE: - result = "RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_EXECUTE"; - break; - } - return result; -} - -static void PopBreakpoint(struct rdb_Buffer* b, struct Breakpoint* bp) -{ - bp->uid = PopId(b); - bp->enabled = PopBool(b); - PopString(b, &bp->module_name); - PopString(b, &bp->condition_expr); - bp->kind = PopBreakpointKind(b); - switch (bp->kind) - { - case RDBG_BREAKPOINT_KIND_FUNCTION_NAME: - PopString(b, &bp->function_name); - bp->overload_id = PopId(b); - break; - case RDBG_BREAKPOINT_KIND_FILENAME_LINE: - PopString(b, &bp->filename); - bp->line_num = PopU32(b); - break; - case RDBG_BREAKPOINT_KIND_ADDRESS: - bp->address = PopU64(b); - break; - case RDBG_BREAKPOINT_KIND_PROCESSOR: - PopString(b, &bp->expression); - bp->num_bytes = PopU8(b); - bp->access_kind = (enum rdbg_InternalProcessorBreakpointType)PopProcessorBreakpointAccessKind(b); - break; - } -} - -static bool BreakpointIt_Next(struct BufIterator* it, struct Breakpoint* bp) -{ - bool result = false; - if (++it->cur_idx < it->n) - { - PopBreakpoint(&it->buf, bp); - result = true; - } - return result; -} - -struct FunctionOverload -{ - rdbg_Id id; - struct rdbg_String* fn_sig; -}; - -static bool FunctionOverloadIt_Next(struct BufIterator* it, - struct FunctionOverload* overload) -{ - bool result = false; - if (++it->cur_idx < it->n) - { - struct rdb_Buffer* b = &it->buf; - - overload->id = PopId(b); - PopString(b, &overload->fn_sig); - result = true; - } - return result; -} - -struct Watch -{ - rdbg_Id uid; - struct rdbg_String* expression; - struct rdbg_String* comment; -}; - -static bool WatchExpressionIt_Next(struct BufIterator* it, - struct Watch* watch) -{ - bool result = false; - if (++it->cur_idx < it->n) - { - struct rdb_Buffer* b = &it->buf; - - watch->uid = PopId(b); - PopString(b, &watch->expression); - PopString(b, &watch->comment); - - result = true; - } - return result; -} - -static void MaybePrintField(struct rdbg_String* str, char* field_name) -{ - if (str && str->len) - { - fprintf(stderr, "\t%s: %.*s\n", field_name, str->len, - (char*)str->data); - } -} - -static char* SourceLocChangedReasonToString(enum rdbg_SourceLocChangedReason reason) -{ - char* result = ""; - switch (reason) - { - case RDBG_SOURCE_LOC_CHANGED_REASON_UNSPECIFIED: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_UNSPECIFIED"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_BY_COMMAND_LINE: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_BY_COMMAND_LINE"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_BY_DRIVER: - result = "RDBG_SOURCE_LOCATION_CHANGED_REASON_BY_DRIVER"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_BREAKPOINT_SELECTED: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_BREAKPOINT_SELECTED"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_CURRENT_FRAME_CHANGED: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_CURRENT_FRAME_CHANGED"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_ACTIVE_THREAD_CHANGED: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_ACTIVE_THREAD_CHANGED"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_BREAKPOINT_HIT: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_BREAKPOINT_HIT"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_EXCEPTION_HIT: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_EXCEPTION_HIT"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_STEP_OVER: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_STEP_OVER"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_STEP_IN: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_STEP_IN"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_STEP_OUT: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_STEP_OUT"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_NON_USER_BREAKPOINT: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_NON_USER_BREAKPOINT"; - break; - case RDBG_SOURCE_LOC_CHANGED_REASON_DEBUG_BREAK: - result = "RDBG_SOURCE_LOC_CHANGED_REASON_DEBUG_BREAK"; - break; - } - return result; -} - -static void WriteDebugEvent(struct rdb_Buffer* eb) -{ - struct rdbg_String* str; - - enum rdbg_DebugEventKind kind = PopDebugEventKind(eb); - switch (kind) - { - case RDBG_DEBUG_EVENT_KIND_EXIT_PROCESS: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_EXIT_PROCESS\n"); - fprintf(stderr, "\texit_code: %u\n", PopU32(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_TARGET_STARTED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_TARGET_STARTED\n"); - fprintf(stderr, "\tprocess_id: %u\n", PopU32(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_TARGET_ATTACHED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_TARGET_ATTACHED\n"); - fprintf(stderr, "\tprocess_id: %u\n", PopU32(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_TARGET_DETACHED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_TARGET_DETACHED\n"); - fprintf(stderr, "\tprocess_id: %u\n", PopU32(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_TARGET_CONTINUED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_TARGET_CONTINUED\n"); - break; - case RDBG_DEBUG_EVENT_KIND_SOURCE_LOCATION_CHANGED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_SOURCE_LOCATION_CHANGED\n"); - PopString(eb, &str); - if (str && str->len) - { - fprintf(stderr, "\tfilename: %.*s\n", str->len, (char*)str->data); - } - fprintf(stderr, "\tline num: %u\n", PopU32(eb)); - fprintf(stderr, "\treason: %s\n", SourceLocChangedReasonToString((rdbg_SourceLocChangedReason)PopU16(eb))); - break; - case RDBG_DEBUG_EVENT_KIND_EXTERNAL_TEXT_EDITOR_LAUNCHED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_EXTERNAL_TEXT_EDITOR_LAUNCHED\n"); - PopString(eb, &str); - if (str && str->len) - { - fprintf(stderr, "\tfilename: %.*s\n", str->len, (char*)str->data); - } - fprintf(stderr, "\tline num: %u\n", PopU32(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_BREAKPOINT_HIT: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_BREAKPOINT_HIT\n"); - fprintf(stderr, "\tuid: %u\n", PopId(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_BREAKPOINT_RESOLVED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_BREAKPOINT_RESOLVED\n"); - fprintf(stderr, "\tuid: %u\n", PopId(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_BREAKPOINT_ADDED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_BREAKPOINT_ADDED\n"); - fprintf(stderr, "\tuid: %u\n", PopId(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_BREAKPOINT_MODIFIED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_BREAKPOINT_MODIFIED\n"); - fprintf(stderr, "\tuid: %u\n", PopId(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_BREAKPOINT_REMOVED: - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_BREAKPOINT_REMOVED\n"); - fprintf(stderr, "\tuid: %u\n", PopId(eb)); - break; - case RDBG_DEBUG_EVENT_KIND_OUTPUT_DEBUG_STRING: - PopString(eb, &str); - - fprintf(stderr, "RDBG_DEBUG_EVENT_KIND_OUTPUT_DEBUG_STRING\n"); - if (str && str->len) - { - fprintf(stderr, "\tstr: %.*s\n", str->len, (char*)str->data); - } - break; - - default: - fprintf(stderr, "warning: unknown debug event kind received\n"); - } -} - -void DebugControlSample(char* server_name) -{ - static uint8_t command_buf[COMMAND_BUF_SIZE]; - static uint8_t reply_buf[REPLY_BUF_SIZE]; - struct ClientContext ctx = {}; - ctx.cmd.data = command_buf; - ctx.cmd.capacity = sizeof(command_buf); - ctx.reply.data = reply_buf; - ctx.reply.capacity = sizeof(reply_buf); - ctx.dbg_target_behavior = RDBG_IF_DEBUGGING_TARGET_STOP_DEBUGGING; - ctx.mod_session_behavior = RDBG_IF_SESSION_IS_MODIFIED_CONTINUE_WITHOUT_SAVING; - ctx.last_error[0] = 0; - - if (InitConnection(server_name, DebugControlPipe, sizeof(ctx.last_error), - ctx.last_error, &ctx.command_pipe_handle)) - { - /* Sample calls to each debug control command (commented out). - * - enum rdbg_CommandResult res; - StartDebugging(&ctx, false, &res); - BringDebuggerToForeground(&ctx, &res); - SetDebuggerWindowPos(&ctx, 20, 20, 100, 100, &res); - - SetBringToForegroundOnSuspended(&ctx, false, &res); - int x, y, width, height; - bool is_maximized; - GetDebuggerWindowPos(&ctx, &res, &x, &y, &width, &height, &is_maximized); - printf("Window pos: (%d, %d) %d x %d; is maximized: %s\n", - x, y, width, height, is_maximized ? "true" : "false"); - bool is_modified; - GetIsSessionModified(&ctx, &res, &is_modified); - struct rdbg_String* filename; - GetSessionFilename(&ctx, &res, &filename); - if (filename && filename->len) - { - printf("Session filename: %.*s\n", filename->len, filename->data); - } - NewSession(&ctx, &res); - OpenSession(&ctx, "c:\\path\\to\\session.rdbg", &res); - SaveSession(&ctx, &res); - SaveAsSession(&ctx, "c:\\path\\to\\session.rdbg", &res); - struct BufIterator cfg_it; - struct SessionConfig cfg; - GetSessionConfigs(&ctx, &res, &cfg_it); - while (SessionConfigIt_Next(&cfg_it, &cfg)) - { - fprintf(stderr, "Config #%d\n", cfg_it.cur_idx); - fprintf(stderr, "\tuid: %hu\n", cfg.id); - if (cfg.command && cfg.command->len) - { - fprintf(stderr, "\tcommand: %.*s\n", cfg.command->len, - (char*)cfg.command->data); - } - if (cfg.command_args && cfg.command_args->len) - { - fprintf(stderr, "\tcommand_args: %.*s\n", cfg.command_args->len, - (char*)cfg.command_args->data); - } - if (cfg.working_dir && cfg.working_dir->len) - { - fprintf(stderr, "\tworking_dir: %.*s\n", cfg.working_dir->len, - (char*)cfg.working_dir->data); - } - if (cfg.environment_vars && cfg.environment_vars->len) - { - fprintf(stderr, "\tenvironment_vars:\n%.*s\n", - cfg.environment_vars->len, - (char*)cfg.environment_vars->data); - } - fprintf(stderr, "\tinherit_environment_vars_from_parent: %s\n", - cfg.inherit_environment_vars_from_parent ? "true" : "false"); - fprintf(stderr, "\tbreak_at_nominal_entry_point: %s\n", - cfg.break_at_nominal_entry_point ? "true" : "false"); - } - rdbg_Id cfg_id; - AddSessionConfig(&ctx, - "C:\\windows\\system32\\whoami.exe", "/USER", 0, - "A=1\nBB=2\nCCC=3", true, true, &res, &cfg_id); - fprintf(stderr, "Added session conf (ID: %u).\n", cfg_id); - SetActiveSessionConfig(&ctx, cfg_id, &res); - DeleteSessionConfig(&ctx, cfg.id, &res); - DeleteAllSessionConfigs(&ctx, &res); - rdbg_Id cur_file_id; - struct rdbg_String* cur_filename = 0; - uint32_t line_num; - GetCurrentFile(&ctx, &res, &cur_file_id, &cur_filename, &line_num); - if (cur_filename && cur_filename->len) - { - fprintf(stderr, "Topmost file: (%u) %.*s Ln %u\n", - cur_file_id, cur_filename->len, (char*)cur_filename->data, - line_num); - } - rdbg_Id file_id; - GoToFileAtLine(&ctx, "C:\\full\\path\\to\\README.txt", 121, &res, &file_id); - CloseFileById(&ctx, file_id, &res); - CloseAllFiles(&ctx, &res); - struct BufIterator file_it; - struct File file; - GetOpenFiles(&ctx, &res, &file_it); - while (FileIt_Next(&file_it, &file)) - { - fprintf(stderr, "File #%d\n", file_it.cur_idx); - fprintf(stderr, "\tId: %u\n", file.id); - if (file.filename && file.filename->len) - { - fprintf(stderr, "\tfilename: %.*s\n", file.filename->len, - (char*)file.filename->data); - } - fprintf(stderr, "\tLn: %u\n", file.line_num); - } - StopDebugging(&ctx, &res); - RestartDebugging(&ctx, &res); - AttachToProcessById(&ctx, 14368, true, &res); - NewSession(&ctx, &res); - AttachToProcessByName(&ctx, "Calculator.exe", true, &res); - DetachFromProcess(&ctx, &res); - StepIntoByLine(&ctx, &res); - StepIntoByInstruction(&ctx, &res); - StepOverByLine(&ctx, &res); - StepOverByInstruction(&ctx, &res); - StepOut(&ctx, &res); - ContinueExecution(&ctx, &res); - RunToFileAtLine(&ctx, "C:\\full\\path\\to\\test.cpp", 13, &res); - ContinueExecution(&ctx, &res); - BreakExecution(&ctx, &res); - enum rdbg_TargetState state; - GetTargetState(&ctx, &res, &state); - fprintf(stderr, "target state: %hu\n", state); - struct BufIterator bp_it; - struct Breakpoint bp; - GetAllBreakpoints(&ctx, &res, &bp_it); - int idx = 0; - while (BreakpointIt_Next(&bp_it, &bp)) - { - fprintf(stderr, "Breakpoint # %d\n", ++idx); - fprintf(stderr, "\tUID: %u\n", bp.uid); - fprintf(stderr, "\tEnabled: %s\n", bp.enabled ? "true" : "false"); - MaybePrintField(bp.module_name, "Module"); - MaybePrintField(bp.condition_expr, "Condition"); - fprintf(stderr, "\tKind: %s\n", BreakpointKindToString(bp.kind)); - switch (bp.kind) - { - case RDBG_BREAKPOINT_KIND_FUNCTION_NAME: - MaybePrintField(bp.function_name, "Function"); - fprintf(stderr, "\tOverload: %u\n", bp.overload_id); - break; - case RDBG_BREAKPOINT_KIND_FILENAME_LINE: - MaybePrintField(bp.filename, "Filename"); - fprintf(stderr, "\tLine: %u\n", bp.line_num); - break; - case RDBG_BREAKPOINT_KIND_ADDRESS: - fprintf(stderr, "\tAddress: 0x%llx\n", bp.address); - break; - case RDBG_BREAKPOINT_KIND_PROCESSOR: - MaybePrintField(bp.expression, "Expression"); - fprintf(stderr, "\tBytes: %hhu\n", bp.num_bytes); - fprintf(stderr, "\tAccess kind: %s\n", - ProcessorBreakpointAccessKindToString(bp.access_kind)); - break; - } - // Test for call to get information on a single user breakpoint - struct Breakpoint _bp; - GetBreakpoint(&ctx, bp.uid, &res, &_bp); - // See if the breakpoint has been resolved. Not using an iterator - // here, at the moment, because we can only get back one or zero. - uint16_t num_locs; - GetBreakpointLocations(&ctx, bp.uid, &res, &num_locs); - if (num_locs == 1) - { - struct BreakpointLocation loc; - loc.address = PopU64(&ctx.reply); - PopString(&ctx.reply, &loc.module_name); - PopString(&ctx.reply, &loc.filename); - loc.actual_line_num = PopU32(&ctx.reply); - fprintf(stderr, "\t---------\n"); - fprintf(stderr, "\tResolved address: 0x%llx\n", loc.address); - MaybePrintField(loc.module_name, "Module"); - MaybePrintField(loc.module_name, "Filename"); - fprintf(stderr, "\tActual line number: %u\n", - loc.actual_line_num); - } - else - { - fprintf(stderr, "\tUnresolved\n"); - } - } - struct BufIterator fn_overload_it; - struct FunctionOverload overload; - GetFunctionOverloads(&ctx, &res, "SomeFunction", &fn_overload_it); - while (FunctionOverloadIt_Next(&fn_overload_it, &overload)) - { - fprintf(stderr, "Overload %u; sig: ", overload.id); - if (overload.fn_sig && overload.fn_sig->len) - { - fprintf(stderr, "%.*s\n", overload.fn_sig->len, - (char*)overload.fn_sig->data); - } - } - rdbg_Id bp_id; - AddBreakpointAtFn(&ctx, "SomeFunction", 0, "", &res, &bp_id); - AddBreakpointAtFilenameLine(&ctx, "C:\\path\\to\\fn_overloads.cpp", 21, - "", &res, &bp_id); - AddBreakpointAtAddress(&ctx, 0x7FF7F592B703, "", &res, &bp_id); - AddProcessorBreakpoint(&ctx, "&var", 4, - RDBG_PROCESSOR_BREAKPOINT_ACCESS_KIND_WRITE, "", &res, &bp_id); - SetBreakpointCondition(&ctx, bp_id, "$rax == 0", &res); - UpdateBreakpointLine(&ctx, bp_id, 22, &res); - EnableBreakpoint(&ctx, bp_id, false, &res); - EnableBreakpoint(&ctx, bp_id, true, &res); - DeleteBreakpoint(&ctx, bp_id, &res); - DeleteAllBreakpoints(&ctx, &res); - rdbg_Id watch_id; - AddWatch(&ctx, 1, "0xf0c / 0xa", "testing\nblah", &res, &watch_id); - struct BufIterator watch_it; - GetWatches(&ctx, 1, &res, &watch_it); - struct Watch watch; - while (WatchExpressionIt_Next(&watch_it, &watch)) - { - fprintf(stderr, "Watch %hu\n", watch.uid); - if (watch.expression && watch.expression->len) - { - fprintf(stderr, "\tWatch expression: '%.*s'\n", - watch.expression->len, - (char*)watch.expression->data); - } - if (watch.comment && watch.comment->len) - { - fprintf(stderr, "\tWatch comment: '%.*s'\n", - watch.comment->len, - (char*)watch.comment->data); - } - } - UpdateWatchExpression(&ctx, 37, "expr * expr", &res); - UpdateWatchComment(&ctx, 37, "something left after", &res); - DeleteWatch(&ctx, 42, &res); - DeleteAllWatches(&ctx, 1, &res); - ExitDebugger(&ctx, &res); - */ - - if (ContextHadError(&ctx)) - { - fprintf(stderr, "[ERROR] %s (cmd-err:%s)(reply-err:%s)\n", - ctx.last_error, - ctx.cmd.err ? "true" : "false", - ctx.reply.err ? "true" : "false"); - } - CloseConnection(&ctx); - } - else - { - fprintf(stderr, ctx.last_error); - } -} - -void DebugEventsSample(char* server_name) -{ - HANDLE pipe_handle; - char last_error[ERROR_MSG_LEN]; - last_error[0] = 0; - - if (InitConnection(server_name, DebugEventsPipe, sizeof(last_error), - last_error, &pipe_handle)) - { - // blocking read for testing events - while (1) - { - static uint8_t dbg_evt_buf[REPLY_BUF_SIZE]; - struct rdb_Buffer dbg_evt = {}; - dbg_evt.data = dbg_evt_buf; - dbg_evt.capacity = sizeof(dbg_evt_buf); - - DWORD bytes_read = 0; - if (ReadFile(pipe_handle, dbg_evt.data, REPLY_BUF_SIZE, &bytes_read, - NULL)) - { - dbg_evt.curr = dbg_evt.data; - WriteDebugEvent(&dbg_evt); - } - else - { - fprintf(stderr, "ReadFile FAIL: err=%u\n", GetLastError()); - } - } - } - else - { - fprintf(stderr, last_error); - } -} - -///////////////////////////////////////////////////////////////// - -uint8_t command_buf[COMMAND_BUF_SIZE]; -uint8_t reply_buf[REPLY_BUF_SIZE]; -ClientContext RDBG_Ctx; - - -bool RDBG_InitConnection() { - enum rdbg_CommandResult res; - if (RDBG_Ctx.command_pipe_handle != NULL) { - enum rdbg_TargetState state; - GetTargetState(&RDBG_Ctx, &res, &state); - if (!ContextHadError(&RDBG_Ctx)) { - return true; - } - } - Scratch scratch; - String session_name = Format(scratch, "te%llu", GetTimeNanos()); - String remedy_string = Format(scratch, "%S --servername %S", RemedyBGPath, session_name); - Exec(NullViewID, true, remedy_string, GetMainDir()); - MemoryZero(&RDBG_Ctx, sizeof(RDBG_Ctx)); - RDBG_Ctx.cmd.data = command_buf; - RDBG_Ctx.cmd.capacity = sizeof(command_buf); - RDBG_Ctx.reply.data = reply_buf; - RDBG_Ctx.reply.capacity = sizeof(reply_buf); - RDBG_Ctx.dbg_target_behavior = RDBG_IF_DEBUGGING_TARGET_STOP_DEBUGGING; - RDBG_Ctx.mod_session_behavior = RDBG_IF_SESSION_IS_MODIFIED_CONTINUE_WITHOUT_SAVING; - RDBG_Ctx.last_error[0] = 0; - - bool result = false; - for (int i = 0; i < 64; i += 1) { - Sleep(10); - result = InitConnection(session_name.data, DebugControlPipe, sizeof(RDBG_Ctx.last_error), RDBG_Ctx.last_error, &RDBG_Ctx.command_pipe_handle); - if (result) { - break; - } - } - - if (result == false) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - RDBG_Ctx = {}; - return false; - } - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - - rdbg_Id cfg_id; - char *exe = Format(scratch, "%S/%S", WorkDir, BinaryUnderDebug).data; - char *args = NULL; - char *work_dir = WorkDir.data; - char *env = NULL; - AddSessionConfig(&RDBG_Ctx, exe, args, work_dir, env, true, true, &res, &cfg_id); - if (ContextHadError(&RDBG_Ctx)) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return true; - } - - SetActiveSessionConfig(&RDBG_Ctx, cfg_id, &res); - if (ContextHadError(&RDBG_Ctx)) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return true; - } - - return true; -} - -void CMD_StartDebugging(HookParam param) { - bool conn = RDBG_InitConnection(); - if (!conn) { - return; - } - - enum rdbg_CommandResult res; - enum rdbg_TargetState state; - GetTargetState(&RDBG_Ctx, &res, &state); - if (ContextHadError(&RDBG_Ctx)) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return; - } - - if (state == RDBG_TARGET_STATE_NONE) { - StartDebugging(&RDBG_Ctx, false, &res); - if (ContextHadError(&RDBG_Ctx)) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return; - } - } else if (state == RDBG_TARGET_STATE_SUSPENDED) { - ContinueExecution(&RDBG_Ctx, &res); - if (ContextHadError(&RDBG_Ctx)) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return; - } - } - BringDebuggerToForeground(&RDBG_Ctx, &res); - if (ContextHadError(&RDBG_Ctx)) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return; - } -} RegisterCommand(CMD_StartDebugging, "f5", "Start debugging, if debugger not active it starts it, uses BinaryUnderDebug"); - -void CMD_RunToLineInDebugger(HookParam param) { - bool conn = RDBG_InitConnection(); - if (!conn) { - return; - } - - BSet prim = GetBSet(PrimaryWindowID); - enum rdbg_CommandResult res; - Int line = PosToLine(prim.buffer, GetFront(prim.view->carets[0])); - RunToFileAtLine(&RDBG_Ctx, prim.buffer->name.data, (uint32_t)line + 1, &res); - if (res != RDBG_COMMAND_RESULT_OK) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return; - } -} RegisterCommand(CMD_RunToLineInDebugger, "ctrl-f10", "Instruct debugger to execute until line and column under caret"); - -void CMD_StopDebugging(HookParam param) { - bool conn = RDBG_InitConnection(); - if (!conn) { - return; - } - - enum rdbg_CommandResult res; - StopDebugging(&RDBG_Ctx, &res); - if (res != RDBG_COMMAND_RESULT_OK) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return; - } -} RegisterCommand(CMD_StopDebugging, "shift-f5", "Stop debugging"); - -void CMD_AddBreakpoint(HookParam param) { - if (!RDBG_InitConnection()) { - return; - } - - BSet prim = GetBSet(PrimaryWindowID); - Int line = PosToLine(prim.buffer, GetFront(prim.view->carets[0])); - enum rdbg_CommandResult res; - rdbg_Id bp_id; - AddBreakpointAtFilenameLine(&RDBG_Ctx, prim.buffer->name.data, (uint32_t)line + 1, "", &res, &bp_id); - if (res != RDBG_COMMAND_RESULT_OK) { - ReportErrorf("Remedy error: %s", RDBG_Ctx.last_error); - MemoryZero(RDBG_Ctx.last_error, sizeof(RDBG_Ctx.last_error)); - return; - } -} RegisterCommand(CMD_AddBreakpoint, "f9", "Add a breakpoint at filename + line"); - -void HOOK_QuitDebugger(HookParam param) { - if (RDBG_Ctx.command_pipe_handle == NULL) { - return; - } - - enum rdbg_CommandResult res; - ExitDebugger(&RDBG_Ctx, &res); - CloseConnection(&RDBG_Ctx); -} RegisterHook(HOOK_QuitDebugger, HookKind_AppQuit, "", "exit the connected debugger"); - - -#endif \ No newline at end of file diff --git a/src/text_editor/window_build.cpp b/src/text_editor/window_build.cpp deleted file mode 100644 index f3bfd0f..0000000 --- a/src/text_editor/window_build.cpp +++ /dev/null @@ -1,39 +0,0 @@ -void LayoutBuildWindow(HookParam param) { - auto p = param.layout; - Rect2I copy_rect = *p.rect; - if (!p.window->visible) { - p.rect = ©_rect; - } - Int barsize = p.window->font->line_spacing * 10; - p.window->document_rect = p.window->total_rect = CutBottom(p.rect, barsize); -} - -void CMD_ShowBuildWindow(HookParam param) { - BSet main = GetBSet(BuildWindowID); - if (ActiveWindowID != BuildWindowID) { - main.window->visible = true; - NextActiveWindowID = BuildWindowID; - } else { - main.window->visible = false; - } -} RegisterCommand(CMD_ShowBuildWindow, "ctrl-grave"); - -void InitBuildWindow(HookParam param) { - Window *window = CreateWind(); - BuildWindowID = window->id; - Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "build")); - buffer->special = true; - buffer->no_history = true; - BuildBufferID = buffer->id; - View *view = CreateView(buffer->id); - view->special = true; - BuildViewID = view->id; - window->active_view = view->id; - window->secondary_window_style = true; - window->draw_line_highlight = true; - window->primary = false; - window->visible = false; - window->lose_visibility_on_escape = true; - window->jump_history = false; - AddHook(&window->hooks, HookKind_HandleWindowLayout, "LayoutBuildWindow", "", LayoutBuildWindow); -} RegisterHook(InitBuildWindow, HookKind_AppInit, "", "Init the build window"); diff --git a/src/text_editor/window_command.cpp b/src/text_editor/window_command.cpp deleted file mode 100644 index 4fd5377..0000000 --- a/src/text_editor/window_command.cpp +++ /dev/null @@ -1,252 +0,0 @@ -void CMD_ShowCommands(HookParam param) { - // @todo: maybe redo this, similar behavior but use View stored information - // if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == CMD_ShowCommands) { - // NextActiveWindowID = PrimaryWindowID; - // return; - // } - - BSet command_bar = GetBSet(CommandWindowID); - command_bar.window->visible = true; - NextActiveWindowID = command_bar.window->id; - ResetBuffer(command_bar.buffer); - For (GlobalHooks) { - if (it.name == "OpenCommand") { - continue; - } - // RawAppendf(command_bar.buffer, "\n:%-30S <|| :Set %-30S '%-30S'", it.name, it.name, it.binding); - RawAppendf(command_bar.buffer, "\n:%-30S <|| ", it.name); - if (it.docs.len) { - RawAppendf(command_bar.buffer, "%S", it.docs); - } - } - command_bar.view->update_scroll = true; - SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer)); -} RegisterCommand(CMD_ShowCommands, "ctrl-shift-p", "List available commands and their documentation inside the command window"); - -void CMD_ShowDebugBufferList(HookParam param) { - // @todo: maybe redo this, similar behavior but use View stored information - // if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == CMD_ShowDebugBufferList) { - // NextActiveWindowID = PrimaryWindowID; - // return; - // } - - BSet command_bar = GetBSet(CommandWindowID); - command_bar.window->visible = true; - NextActiveWindowID = command_bar.window->id; - ResetBuffer(command_bar.buffer); - For (Buffers) { - bool is_special = it->special || it->temp || it->is_dir || it->dont_try_to_save_in_bulk_ops; - if (!is_special) { - continue; - } - RawAppendf(command_bar.buffer, "\n%S", it->name); - } - command_bar.view->update_scroll = true; - SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer)); -} RegisterCommand(CMD_ShowDebugBufferList, "ctrl-shift-alt-p", "Show full list of buffers, including the special ones that normally just clutter list"); - -void CMD_ShowBufferList(HookParam param) { - // @todo: maybe redo this, similar behavior but use View stored information - // if (ActiveWindowID == CommandWindowID && LastExecutedManualCommand == CMD_ShowBufferList) { - // NextActiveWindowID = PrimaryWindowID; - // return; - // } - BSet command_bar = GetBSet(CommandWindowID); - command_bar.window->visible = true; - NextActiveWindowID = command_bar.window->id; - ResetBuffer(command_bar.buffer); - For (Buffers) { - bool is_special = it->special || it->temp || it->is_dir || it->dont_try_to_save_in_bulk_ops; - if (is_special) { - continue; - } - RawAppendf(command_bar.buffer, "\n%S", it->name); - } - command_bar.view->update_scroll = true; - SelectRange(command_bar.view, GetBufferBeginAsRange(command_bar.buffer)); -} RegisterCommand(CMD_ShowBufferList, "ctrl-p", "List open buffers inside the command window that you can fuzzy search over"); - -void OpenCommand(BSet active) { - String16 string = FetchFuzzyViewLoadLine(active.view); - Open(string); -} - -struct SearchProjectParams { - String16 needle; - BufferID buffer; -}; - -void Coro_SearchProject(mco_coro *co) { - SearchProjectParams *param = (SearchProjectParams *)CoCurr->user_ctx; - - Array buffers = {CoCurr->arena}; - For (Buffers) { - Add(&buffers, it->id); - } - - ForItem (id, buffers) { - Buffer *it = GetBuffer(id, NULL); - if (it == NULL || it->special || it->is_dir || it->temp || it->dont_try_to_save_in_bulk_ops) { - continue; - } - - { - Scratch scratch; - Array occurences = FindAll(scratch, it, param->needle); - Buffer *out_buffer = GetBuffer(param->buffer); - ForItem (caret, occurences) { - Int pos = caret.range.min; - Int line = PosToLine(it, pos); - Range range = GetLineRangeWithoutNL(it, line); - Int column = pos - range.min; - String16 line_string = GetString(it, range); - String line_string8 = ToString(scratch, line_string); - RawAppendf(out_buffer, "%S ||> %S:%lld:%lld\n", line_string8, it->name, (long long)line + 1, (long long)column + 1); - } - } - CoYield(co); - } -} - -float NewFuzzyRate(String16 s, String16 p) { - float score = 0; - // try to do this: https://github.com/junegunn/fzf/blob/master/src/algo/algo.go - return score; -} - -float FuzzyRate(String16 s, String16 p) { - float score = 0; - for (Int outer_pi = 0; outer_pi < p.len; outer_pi += 1) { - String16 pit = Skip(p, outer_pi); - if (IsWhitespace(At(pit, 0))) { - continue; - } - - float matching = 0; - for (Int outer_si = 0; outer_si < s.len; outer_si += 1) { - String16 sit = Skip(s, outer_si); - if (IsWhitespace(At(sit, 0))) { - continue; - } - - Int si = 0; - Int pi = 0; - for (;si < sit.len && pi < pit.len;) { - while (si < sit.len && IsWhitespace(sit[si])) si += 1; - while (pi < pit.len && IsWhitespace(pit[pi])) pi += 1; - if (pi >= pit.len) break; - if (si >= sit.len) break; - - if (ToLowerCase(sit[si]) == ToLowerCase(pit[pi])) { - matching += 1.0f; - } else { - break; - } - si += 1; - pi += 1; - } - } - score += matching; - } - score = score / (float)s.len; - return score; -} - -inline bool MergeSortCompare(FuzzyPair *a, FuzzyPair *b) { - bool result = a->rating > b->rating; - return result; -} - -Array FuzzySearchLines(Allocator allocator, Buffer *buffer, Int line_min, Int line_max, String16 needle) { - ProfileFunction(); - if (line_min < 0 || line_min >= buffer->line_starts.len) return {}; - if (line_max < 0 || line_min > buffer->line_starts.len) return {}; - Array ratings = {allocator}; - Reserve(&ratings, line_max - line_min + 4); - for (Int i = line_min; i < line_max; i += 1) { - String16 s = GetLineStringWithoutNL(buffer, i); - - Int idx = 0; - if (Seek(s, u"||>", &idx, SeekFlag_None)) { - s = GetPrefix(s, idx); - } else if (Seek(s, u"<||", &idx, SeekFlag_None)) { - s = GetPrefix(s, idx); - } - s = Trim(s); - - float rating = FuzzyRate(s, needle); - Add(&ratings, {(int32_t)i, rating}); - } - Array temp = Copy(allocator, ratings); - MergeSort(ratings.len, ratings.data, temp.data); - return ratings; -} - -void UpdateFuzzySearchView(HookParam param) { - Scratch scratch; - BSet active = GetBSet(ActiveWindowID); - String16 line_string = GetLineStringWithoutNL(active.buffer, 0); - uint64_t hash = HashBytes(line_string.data, line_string.len * sizeof(char16_t)); - if (active.view->prev_search_line_hash != hash) { - active.view->prev_search_line_hash = hash; - Array ratings = FuzzySearchLines(scratch, active.buffer, 1, active.buffer->line_starts.len, line_string); - - Buffer *scratch_buff = CreateScratchBuffer(scratch, active.buffer->cap); - RawAppend(scratch_buff, line_string); - For(IterateInReverse(&ratings)) { - String16 s = GetLineStringWithoutNL(active.buffer, it.index); - if (s.len == 0) continue; - RawAppend(scratch_buff, u"\n"); - RawAppend(scratch_buff, s); - } - - Caret caret = active.view->carets[0]; - SaveCaretHistoryBeforeBeginEdit(active.buffer, active.view->carets); - SelectEntireBuffer(active.view); - Replace(active.view, GetString(scratch_buff)); - active.view->carets[0] = caret; - } -} - -void SetFuzzy(View *view) { - AddCommand(&view->hooks, "Open", "ctrl-q | enter | f12", [](HookParam){ - BSet active = GetBSet(ActiveWindowID); - BSet main = GetBSet(PrimaryWindowID); - NextActiveWindowID = main.window->id; - String16 string = FetchFuzzyViewLoadLine(active.view); - Open(string); - }); - AddHook(&view->hooks, HookKind_AppUpdate, "UpdateFuzzySearchView", "", UpdateFuzzySearchView); -} - -void LayoutCommandWindow(HookParam param) { - auto p = param.layout; - Rect2I copy_rect = *p.rect; - if (!p.window->visible) { - p.rect = ©_rect; - } - Int barsize = Clamp((Int)p.window->font->line_spacing*10, (Int)0, (Int)p.wx - 100); - p.window->document_rect = p.window->total_rect = CutBottom(p.rect, barsize); -} - -void InitCommandWindow(HookParam param) { - Window *window = CreateWind(); - CommandWindowID = window->id; - Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "command_bar")); - buffer->special = true; - buffer->no_history = true; - View *view = CreateView(buffer->id); - view->special = true; - SetFuzzy(view); - window->active_view = view->id; - window->draw_line_numbers = false; - window->draw_scrollbar = false; - window->secondary_window_style = true; - window->draw_line_highlight = true; - window->primary = false; - window->visible = false; - window->sync_visibility_with_focus = true; - window->lose_focus_on_escape = true; - window->jump_history = false; - AddHook(&window->hooks, HookKind_HandleWindowLayout, "LayoutCommandWindow", "", LayoutCommandWindow); -} RegisterHook(InitCommandWindow, HookKind_AppInit, "", "Init command window"); diff --git a/src/text_editor/window_debug.cpp b/src/text_editor/window_debug.cpp deleted file mode 100644 index ff3b828..0000000 --- a/src/text_editor/window_debug.cpp +++ /dev/null @@ -1,87 +0,0 @@ -void LayoutDebugWindow(HookParam param) { - auto p = param.layout; - Rect2 screen_rect = Rect0Size((float)p.wx, (float)p.wy); - Vec2 size = GetSize(screen_rect); - - Rect2 a = CutRight(&screen_rect, 0.3f * size.x); - Rect2 b = CutTop(&a, 0.4f * size.y); - Rect2 c = Shrink(b, 20); - p.window->document_rect = p.window->total_rect = ToRect2I(c); -} - -void UpdateDebugWindow(HookParam param) { - ProfileFunction(); - BSet set = GetBSet(DebugWindowID); - if (!set.window->visible) { - return; - } - - BSet active = GetBSet(ActiveWindowID); - if (active.buffer->id.id == set.buffer->id.id) { - return; - } - - BSet main = GetBSet(PrimaryWindowID); - - Scratch scratch; - String s = Format(scratch, "wid: %d\nvid: %d\nbid: %d\nframe: %lld\n", (int)main.window->id.id, (int)main.view->id.id, (int)main.buffer->id.id, (long long)FrameID); - String16 string = ToString16(scratch, s); - RawReplaceText(set.buffer, GetRange(set.buffer), string); - - float xmouse, ymouse; - SDL_GetMouseState(&xmouse, &ymouse); - RawAppendf(set.buffer, "mouse: [%f, %f]\n", roundf(DPIScale * xmouse), roundf(DPIScale * ymouse)); - - RawAppendf(set.buffer, "BufferID id = %d\n", main.buffer->id.id); - RawAppendf(set.buffer, "String name = %S\n", main.buffer->name); - RawAppendf(set.buffer, "Int change_id = %lld\n", (long long)main.buffer->change_id); - RawAppendf(set.buffer, "Int user_change_id = %lld\n", (long long)main.buffer->user_change_id); - RawAppendf(set.buffer, "Int file_mod_time = %lld\n", (long long)main.buffer->file_mod_time); - RawAppendf(set.buffer, "\n"); - - RawAppendf(set.buffer, "U16 *data = %zu\n", main.buffer->data); - RawAppendf(set.buffer, "Int len = %lld\n", (long long)main.buffer->len); - RawAppendf(set.buffer, "Int cap = %lld\n", (long long)main.buffer->cap); - RawAppendf(set.buffer, "Array line_starts = {len = %lld, cap = %lld, data = %zu}\n", (long long)main.buffer->line_starts.len, (long long)main.buffer->line_starts.cap, main.buffer->line_starts.data); - RawAppendf(set.buffer, "\n"); - - RawAppendf(set.buffer, "Array undo_stack = {len = %lld, cap = %lld, data = %zu}\n", (long long)main.buffer->undo_stack.len, (long long)main.buffer->undo_stack.cap, main.buffer->undo_stack.data); - RawAppendf(set.buffer, "Array redo_stack = {len = %lld, cap = %lld, data = %zu}\n", (long long)main.buffer->redo_stack.len, (long long)main.buffer->redo_stack.cap, main.buffer->redo_stack.data); - RawAppendf(set.buffer, "int edit_phase = %d", main.buffer->edit_phase); - RawAppendf(set.buffer, "\n"); - - RawAppendf(set.buffer, "int no_history = %d\n", main.buffer->no_history); - RawAppendf(set.buffer, "int no_line_starts = %d\n", main.buffer->no_line_starts); - RawAppendf(set.buffer, "int dirty = %d\n", main.buffer->dirty); - RawAppendf(set.buffer, "int changed_on_disk = %d\n", main.buffer->changed_on_disk); - RawAppendf(set.buffer, "int temp = %d\n", main.buffer->temp); -} RegisterHook(UpdateDebugWindow, HookKind_AppUpdate, "", "Update the debug window"); - -void InitDebugWindow(HookParam param) { - Window *window = CreateWind(); - DebugWindowID = window->id; - window->draw_line_numbers = false; - window->draw_scrollbar = false; - window->visible = false; - window->z = 2; - window->primary = false; - window->jump_history = false; - - Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "debug")); - DebugBufferID = buffer->id; - buffer->no_history = true; - buffer->special = true; - - View *view = CreateView(buffer->id); - view->special = true; - DebugViewID = view->id; - window->active_view = view->id; - window->visible = false; - - AddHook(&window->hooks, HookKind_HandleWindowLayout, "@todo: LayoutDebugWindow", "", LayoutDebugWindow); -} RegisterHook(InitDebugWindow, HookKind_AppInit, "", "Init the debug window"); - -void CMD_ToggleDebug(HookParam param) { - Window *window = GetWindow(DebugWindowID); - window->visible = !window->visible; -} RegisterCommand(CMD_ToggleDebug, "ctrl-0", "Open a floating window that might become useful for debugging"); diff --git a/src/text_editor/window_search.cpp b/src/text_editor/window_search.cpp deleted file mode 100644 index b149927..0000000 --- a/src/text_editor/window_search.cpp +++ /dev/null @@ -1,103 +0,0 @@ -void CMD_Search(HookParam param) { - BSet main = GetBSet(ActiveWindowID); - String16 string = {}; - if (main.view->carets.len == 1 && GetSize(main.view->carets[0]) > 0) { - string = GetString(main.buffer, main.view->carets[0].range); - } - BSet set = GetBSet(SearchWindowID); - set.window->visible = true; - NextActiveWindowID = SearchWindowID; - SelectEntireBuffer(set.view); - if (string.len > 0) { - Replace(set.view, string); - SelectEntireBuffer(set.view); - } -} RegisterCommand(CMD_Search, "ctrl-f", "Open up a search window"); - -void SearchWindowFindNext(bool forward = true) { - BSet main = GetBSet(PrimaryWindowID); - BSet set = GetBSet(SearchWindowID); - String16 seek = GetString(set.buffer, GetRange(set.buffer)); - Find(main.view, seek, forward); - main.window->search_bar_anchor = main.view->carets[0]; - CenterView(PrimaryWindowID); -} - -void CMD_SearchNextInSearch(HookParam param) { - SearchWindowFindNext(true); -} - -void CMD_SearchPrevInSearch(HookParam param) { - SearchWindowFindNext(false); -} - -void CMD_SearchNext(HookParam param) { - SearchWindowFindNext(true); -} RegisterCommand(CMD_SearchNext, "f3", "Go to the next occurence of the search window needle"); - -void CMD_SearchPrev(HookParam param) { - SearchWindowFindNext(false); -} RegisterCommand(CMD_SearchPrev, "shift-f3", "Go to the previous occurence of the search window needle"); - -void CMD_SearchAll(HookParam param) { - BSet main = GetBSet(PrimaryWindowID); - BSet set = GetBSet(SearchWindowID); - String16 needle = GetString(set.buffer, GetRange(set.buffer)); - SelectAllOccurences(main.view, needle); - set.window->visible = false; -} RegisterCommand(CMD_SearchAll, "alt-f3", "Use the search window needle and seek all the possible occurences in current buffer"); - -void CMD_ToggleCaseSensitiveSearch(HookParam param) { - SearchCaseSensitive = !SearchCaseSensitive; -} RegisterCommand(CMD_ToggleCaseSensitiveSearch, "alt-c", "Text editor wide search toggle, should apply to most search things"); - -void CMD_ToggleSearchWordBoundary(HookParam param) { - SearchWordBoundary = !SearchWordBoundary; -} RegisterCommand(CMD_ToggleSearchWordBoundary, "alt-w", "Text editor wide search toggle, should apply to most search things"); - -void UpdateSearchWindow(HookParam param) { - BSet active = GetBSet(ActiveWindowID); - if (active.window->id == SearchWindowID && active.buffer->begin_frame_change_id != active.buffer->change_id) { - BSet main = GetBSet(PrimaryWindowID); - BSet set = GetBSet(SearchWindowID); - main.view->carets[0] = main.window->search_bar_anchor; - String16 seek = GetString(set.buffer, GetRange(set.buffer)); - Find(main.view, seek, true); - CenterView(main.window->id); - } -} RegisterHook(UpdateSearchWindow, HookKind_AppUpdate, "", "Update the search window"); - -void LayoutSearchWindow(HookParam param) { - auto p = param.layout; - Rect2I copy_rect = *p.rect; - if (!p.window->visible) { - p.rect = ©_rect; - } - Int barsize = GetExpandingBarSize(p.window); - p.window->document_rect = p.window->total_rect = CutBottom(p.rect, barsize); - p.window->line_numbers_rect = CutLeft(&p.window->document_rect, p.window->font->char_spacing * 6); -} - -void InitSearchWindow(HookParam param) { - Window *window = CreateWind(); - SearchWindowID = window->id; - Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "search")); - buffer->special = true; - SearchBufferID = buffer->id; - View *view = CreateView(buffer->id); - view->special = true; - SearchViewID = view->id; - window->active_view = view->id; - window->draw_line_numbers = false; - window->draw_scrollbar = false; - window->secondary_window_style = true; - window->draw_line_highlight = false; - window->primary = false; - window->visible = false; - window->lose_visibility_on_escape = true; - window->jump_history = false; - AddCommand(&view->hooks, "SearchAll", "alt-enter", CMD_SearchAll); - AddCommand(&view->hooks, "SearchPrevInSearch", "shift-enter", CMD_SearchPrevInSearch); - AddCommand(&view->hooks, "SearchNextInSearch", "enter", CMD_SearchNextInSearch); - AddHook(&window->hooks, HookKind_HandleWindowLayout, "LayoutSearchWindow", "", LayoutSearchWindow); -} RegisterHook(InitSearchWindow, HookKind_AppInit, "", "Init the search window"); diff --git a/src/text_editor/window_status.cpp b/src/text_editor/window_status.cpp deleted file mode 100644 index 996be4f..0000000 --- a/src/text_editor/window_status.cpp +++ /dev/null @@ -1,99 +0,0 @@ -void StatusWindowUpdate(HookParam param) { - ProfileFunction(); - Window *status_bar_window = GetWindow(StatusBarWindowID, NULL); - Scratch scratch; - BSet main = GetBSet(PrimaryWindowID); - BSet title = GetBSet(status_bar_window); - title.view->scroll.y = 0; - - String16 buffer_string = GetString(title.buffer); - Range replace_range = {0, title.buffer->len}; - bool found_separator = Seek(buffer_string, u" |", &replace_range.max); - - // Parse the title and line - if (title.window->id == ActiveWindowID) { - if (title.buffer->change_id == title.buffer->begin_frame_change_id) { - return; - } - String16 buffer_name = GetString(title.buffer, replace_range); - buffer_name = Trim(buffer_name); - - Int column = ChopNumber(&buffer_name); - if (column == -1) return; - - Chop(&buffer_name, u":"); - Int line = ChopNumber(&buffer_name); - if (line == -1) { - line = column; - column = 0; - } - Chop(&buffer_name, u":"); - - Int buffer_pos = XYToPos(main.buffer, {column, line}); - Caret &caret = main.view->carets[0]; - if (GetFront(caret) != buffer_pos) { - caret = MakeCaret(buffer_pos); - } - return; - } - - Caret caret = main.view->carets[0]; - XY xy = PosToXY(main.buffer, GetFront(caret)); - - // add separator at the end of buffer - if (!found_separator) { - SelectRange(title.view, GetBufferEndAsRange(title.buffer)); - ReplaceEx(scratch, title.view, u" | :Prev :Next :Close"); - } - - // replace data up to separator with filename and stuff - const char *reopen = main.buffer->changed_on_disk ? " :Reopen" : ""; - const char *case_sens = SearchCaseSensitive ? " C" : ""; - const char *word_bound = SearchWordBoundary ? " W" : ""; - const char *dirty = main.buffer->dirty ? " !" : ""; - String s = Format(scratch, "%S:%lld:%lld%s%s%s", main.buffer->name, (long long)xy.line + 1ll, (long long)xy.col + 1ll, dirty, case_sens, word_bound, reopen); - For (ActiveProcesses) { - if (it.view_id == main.view->id.id) { - s = Format(scratch, "%S %lld :KillProcess", s, (long long)it.id); - } - } - - String16 string = ToString16(scratch, s); - String16 string_to_replace = GetString(title.buffer, replace_range); - if (string_to_replace != string) { - SelectRange(title.view, replace_range); - ReplaceEx(scratch, title.view, string); - } - - SelectRange(title.view, MakeRange(0)); - ResetHistory(title.buffer); -} RegisterHook(StatusWindowUpdate, HookKind_AppUpdate, "", ""); - -void LayoutStatusWindow(HookParam param) { - auto p = param.layout; - Rect2I copy_rect = *p.rect; - if (!p.window->visible) { - p.rect = ©_rect; - } - Int barsize = GetExpandingBarSize(p.window); - p.window->document_rect = p.window->total_rect = CutBottom(p.rect, barsize); -} RegisterHook(LayoutStatusWindow, HookKind_HandleWindowLayout, "", "Layout the status window"); - -void StatusWindowInit(HookParam param) { - Window *window = CreateWind(); - StatusBarWindowID = window->id; - Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "status_bar")); - buffer->special = true; - View *view = CreateView(buffer->id); - view->special = true; - window->active_view = view->id; - // window->font = &SecondaryFont; - window->draw_line_numbers = false; - window->draw_scrollbar = false; - window->draw_line_highlight = true; - window->secondary_window_style = true; - window->primary = false; - window->jump_history = false; - window->lose_focus_on_escape = true; - AddHook(&window->hooks, HookKind_HandleWindowLayout, "@todo LayoutStatusWindow", "", LayoutStatusWindow); -} RegisterHook(StatusWindowInit, HookKind_AppInit, "", "Init the status window"); \ No newline at end of file