Mercurial > octave
diff libinterp/corefcn/interpreter.cc @ 29254:11343ca3c125
allow Octave to operate as a server, executing commands from a queue
* event-manager.h (interpreter_events::interpreter_output):
New virtual fucntion.
(event_manager::interpreter_output): New function.
* interpreter.cc (interpeter::m_parser, interpeter::m_exit_status,
interpeter::m_server_mode): New data members.
(interpreter::parse_and_execute, interpreter::server_loop,
(interpreter::parse_and_execute): New functions.
(interpreter::execute): If server option is set, execute server_loop
instead of main_loop.
* pager.cc (output_system::sync): Also bypass pager if running in
server mode.
(output_system::do_sync): Send output to event manager if running in
server mode and bypass_pager is true.
* options-usage.h, octave.h, octave.cc, main.in.cc:
Handle new --server option.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 17 Dec 2020 20:18:51 -0500 |
parents | 28913793f678 |
children | 6dd456257d81 |
line wrap: on
line diff
--- a/libinterp/corefcn/interpreter.cc Sun Jan 03 14:39:31 2021 -0500 +++ b/libinterp/corefcn/interpreter.cc Thu Dec 17 20:18:51 2020 -0500 @@ -467,7 +467,10 @@ m_cdef_manager (*this), m_gtk_manager (), m_event_manager (*this), + m_parser (), m_gh_manager (nullptr), + m_exit_status (0), + m_server_mode (false), m_interactive (false), m_read_site_files (true), m_read_init_files (m_app_context != nullptr), @@ -755,6 +758,53 @@ m_initialized = true; } + void interpreter::parse_and_execute (const std::string& input, + bool& incomplete_parse) + { + incomplete_parse = false; + + unwind_protect_var<bool> upv (m_in_top_level_repl, true); + + if (m_evaluator.at_top_level ()) + { + m_evaluator.dbstep_flag (0); + m_evaluator.reset_debug_state (); + } + + bool eof = false; + + if (command_history::add (input)) + m_event_manager.append_history (input); + + m_exit_status = m_parser->run (input, eof); + + if (m_exit_status == 0) + { + std::shared_ptr<tree_statement_list> + stmt_list = m_parser->statement_list (); + + if (stmt_list) + { + command_editor::increment_current_command_number (); + + m_evaluator.eval (stmt_list, m_interactive); + + m_event_manager.set_workspace (); + } + else if (m_parser->at_end_of_input ()) + m_exit_status = EOF; + } + else + incomplete_parse = true; + + if (m_exit_status == -1) + m_exit_status = 0; + else + m_parser->reset (); + + m_event_manager.pre_input_event (); + } + // FIXME: this function is intended to be executed only once. Should // we enforce that restriction? @@ -801,7 +851,10 @@ if (options.forced_interactive ()) command_editor::blink_matching_paren (false); - exit_status = main_loop (); + if (options.server ()) + exit_status = server_loop (); + else + exit_status = main_loop (); } } catch (const exit_exception& xe) @@ -1335,6 +1388,91 @@ return exit_status; } + int interpreter::server_loop (void) + { + // Process events from the event queue. + + unwind_protect_var<bool> upv (m_server_mode, true); + + m_exit_status = 0; + + if (! m_parser) + m_parser = std::shared_ptr<push_parser> (new push_parser (*this)); + + do + { + try + { + // FIXME: Running the event queue should be decoupled from + // the command_editor. We should also use a condition + // variable to manage the execution of entries in the queue + // and eliminate the need for the busy-wait loop. + + command_editor::run_event_hooks (); + + octave::sleep (0.1); + } + catch (const interrupt_exception&) + { + recover_from_exception (); + + m_parser->reset (); + + // Required newline when the user does Ctrl+C at the prompt. + if (m_interactive) + octave_stdout << "\n"; + } + catch (const index_exception& e) + { + recover_from_exception (); + + m_parser->reset (); + + std::cerr << "error: unhandled index exception: " + << e.message () << " -- trying to return to prompt" + << std::endl; + } + catch (const execution_exception& ee) + { + m_error_system.save_exception (ee); + m_error_system.display_exception (ee, std::cerr); + + if (m_interactive) + { + recover_from_exception (); + + m_parser->reset (); + } + else + { + // We should exit with a nonzero status. + m_exit_status = 1; + break; + } + } + catch (const std::bad_alloc&) + { + recover_from_exception (); + + m_parser->reset (); + + std::cerr << "error: out of memory -- trying to return to prompt" + << std::endl; + } + } + while (m_exit_status == 0); + + if (m_exit_status == EOF) + { + if (m_interactive) + octave_stdout << "\n"; + + m_exit_status = 0; + } + + return m_exit_status; + } + tree_evaluator& interpreter::get_evaluator (void) { return m_evaluator;