Mercurial > octave
changeset 29306:0231189f630d
provide interpreter methods for pausing, resuming, and stopping evaluation
* interpreter.h, interpreter.cc (interpreter::pause,
interpreter::resume, interpreter::stop): New methods.
* pt-eval.h, pt-eval.cc (tree_evaluator::m_break_on_next_stmt):
New member variable.
(tree_evaluator::do_breakpoint): Also check m_break_on_next_stmt.
(tree_evaluator::break_on_next_statement): New functions.
(tree_evaluator::reset_debug_state):
Also set m_debug_mode if m_break_on_next_stmt is true.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 20 Jan 2021 16:53:16 -0500 |
parents | 477f7d6c61e4 |
children | b2d62cfac9e6 |
files | libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h |
diffstat | 4 files changed, 90 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/interpreter.cc Wed Jan 20 16:45:45 2021 -0500 +++ b/libinterp/corefcn/interpreter.cc Wed Jan 20 16:53:16 2021 -0500 @@ -1719,22 +1719,55 @@ first = false; } - // Send SIGINT to all other processes in our process group. The - // signal handler for SIGINT will set a global variable indicating - // an interrupt has happened. That variable is checked in many - // places in the Octave interpreter and eventually results in an - // interrupt_exception being thrown. Finally, that exception is - // caught and returns control to one of the read-eval-print loops or - // to the server loop. We use a signal instead of just setting the - // global variables here so that we will probably send interrupt - // signals to any subprocesses as well as interrupt execution of the - // interpreter. + // Send SIGINT to Octave and (optionally) all other processes in its + // process group. The signal handler for SIGINT will set a global + // variable indicating an interrupt has happened. That variable is + // checked in many places in the Octave interpreter and eventually + // results in an interrupt_exception being thrown. Finally, that + // exception is caught and returns control to one of the + // read-eval-print loops or to the server loop. We use a signal + // instead of just setting the global variables here so that we will + // probably send interrupt signals to any subprocesses as well as + // interrupt execution of the interpreter. - pid_t pid = m_interrupt_all_in_process_group ? 0 : octave_getpid_wrapper (); + pid_t pid + = m_interrupt_all_in_process_group ? 0 : octave_getpid_wrapper (); octave_kill_wrapper (pid, sigint); } + void interpreter::pause (void) + { + // FIXME: To be reliable, these tree_evaluator functions must be + // made thread safe. + + m_evaluator.break_on_next_statement (true); + m_evaluator.reset_debug_state (); + } + + void interpreter::stop (void) + { + // FIXME: To be reliable, these tree_evaluator functions must be + // made thread safe. + + if (m_evaluator.in_debug_repl ()) + m_evaluator.dbquit (true); + else + interrupt (); + } + + void interpreter::resume (void) + { + // FIXME: To be reliable, these tree_evaluator functions must be + // made thread safe. + + // FIXME: Should there be any feeback about not doing anything if + // not in debug mode? + + if (m_evaluator.in_debug_repl ()) + m_evaluator.dbcont (); + } + void interpreter::handle_exception (const execution_exception& ee) { m_error_system.save_exception (ee);
--- a/libinterp/corefcn/interpreter.h Wed Jan 20 16:45:45 2021 -0500 +++ b/libinterp/corefcn/interpreter.h Wed Jan 20 16:53:16 2021 -0500 @@ -479,6 +479,17 @@ void interrupt (void); + // Pause interpreter execution at the next available statement and + // enter the debugger. + void pause (void); + + // Exit debugger or stop execution and return to the top-level REPL + // or server loop. + void stop (void); + + // Resume interpreter execution if paused. + void resume (void); + void handle_exception (const execution_exception& ee); void recover_from_exception (void);
--- a/libinterp/parse-tree/pt-eval.cc Wed Jan 20 16:45:45 2021 -0500 +++ b/libinterp/parse-tree/pt-eval.cc Wed Jan 20 16:53:16 2021 -0500 @@ -117,10 +117,7 @@ bool in_debug_repl (void) const { return m_in_debug_repl; } - void dbcont (void) - { - m_execution_mode = EX_CONTINUE; - } + void dbcont (void) { m_execution_mode = EX_CONTINUE; } void dbquit (bool all = false) { @@ -1191,7 +1188,9 @@ void tree_evaluator::reset_debug_state (void) { - m_debug_mode = (m_bp_table.have_breakpoints () || m_dbstep_flag != 0 + m_debug_mode = (m_bp_table.have_breakpoints () + || m_dbstep_flag != 0 + || m_break_on_next_stmt || in_debug_repl ()); } @@ -4151,6 +4150,11 @@ m_dbstep_flag = -1; } + if (! break_on_this_statement) + break_on_this_statement = m_break_on_next_stmt; + + m_break_on_next_stmt = false; + if (break_on_this_statement) { m_dbstep_flag = 0;
--- a/libinterp/parse-tree/pt-eval.h Wed Jan 20 16:45:45 2021 -0500 +++ b/libinterp/parse-tree/pt-eval.h Wed Jan 20 16:53:16 2021 -0500 @@ -134,8 +134,8 @@ m_debug_mode (false), m_quiet_breakpoint_flag (false), m_debugger_stack (), m_exit_status (0), m_max_recursion_depth (256), m_whos_line_format (" %a:4; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;\n"), - m_silent_functions (false), m_string_fill_char (' '), - m_PS4 ("+ "), m_dbstep_flag (0), m_echo (ECHO_OFF), + m_silent_functions (false), m_string_fill_char (' '), m_PS4 ("+ "), + m_dbstep_flag (0), m_break_on_next_stmt (false), m_echo (ECHO_OFF), m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1), m_echo_files (), m_in_top_level_repl (false), m_server_mode (false), m_in_loop_command (false), @@ -642,6 +642,9 @@ void dbcont (void); + // Return true if we are in the debug repl and m_execution_mode is + // set to exit the debugger. Otherwise, do nothing. + void dbquit (bool all = false); octave_value PS4 (const octave_value_list& args, int nargout); @@ -748,6 +751,23 @@ void set_dbstep_flag (int step) { m_dbstep_flag = step; } + bool break_on_next_statement (void) const + { + return m_break_on_next_stmt; + } + + bool break_on_next_statement (bool val) + { + bool old_val = m_break_on_next_stmt; + m_break_on_next_stmt = val; + return old_val; + } + + void set_break_on_next_statement (bool val) + { + m_break_on_next_stmt = val; + } + octave_value echo (const octave_value_list& args, int nargout); int echo (void) const { return m_echo; } @@ -871,6 +891,10 @@ // If < 0, stop executing at the next possible stopping point. int m_dbstep_flag; + // If TRUE, and we are not stopping for another reason (dbstep or a + // breakpoint) then stop at next statement and enter the debugger. + bool m_break_on_next_stmt; + // Echo commands as they are executed? // // 1 ==> echo commands read from script files