Mercurial > octave
diff libinterp/corefcn/interpreter.cc @ 31608:23664317f0d3
maint: merge stable to default
author | Rik <rik@octave.org> |
---|---|
date | Thu, 01 Dec 2022 20:05:44 -0800 |
parents | aac27ad79be6 |
children | d9970470108a |
line wrap: on
line diff
--- a/libinterp/corefcn/interpreter.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/interpreter.cc Thu Dec 01 20:05:44 2022 -0800 @@ -287,8 +287,8 @@ std::string arg = args(0).xstring_value ("atexit: FCN argument must be a string"); bool add_mode = (nargin == 2) - ? args(1).xbool_value ("atexit: FLAG argument must be a logical value") - : true; + ? args(1).xbool_value ("atexit: FLAG argument must be a logical value") + : true; octave_value_list retval; @@ -314,622 +314,622 @@ return ovl (interp.traditional ()); } - temporary_file_list::~temporary_file_list (void) - { - cleanup (); - } +temporary_file_list::~temporary_file_list (void) +{ + cleanup (); +} - void temporary_file_list::insert (const std::string& file) - { - m_files.insert (file); - } +void temporary_file_list::insert (const std::string& file) +{ + m_files.insert (file); +} - void temporary_file_list::cleanup (void) - { - while (! m_files.empty ()) - { - auto it = m_files.begin (); +void temporary_file_list::cleanup (void) +{ + while (! m_files.empty ()) + { + auto it = m_files.begin (); - octave_unlink_wrapper (it->c_str ()); + octave_unlink_wrapper (it->c_str ()); - m_files.erase (it); - } - } + m_files.erase (it); + } +} - // The time we last time we changed directories. - sys::time Vlast_chdir_time = 0.0; +// The time we last time we changed directories. +sys::time Vlast_chdir_time = 0.0; - // Execute commands from a file and catch potential exceptions in a consistent - // way. This function should be called anywhere we might parse and execute - // commands from a file before we have entered the main loop in - // toplev.cc. +// Execute commands from a file and catch potential exceptions in a consistent +// way. This function should be called anywhere we might parse and execute +// commands from a file before we have entered the main loop in +// toplev.cc. - static int safe_source_file (const std::string& file_name, - const std::string& context = "", - bool verbose = false, - bool require_file = true) - { - interpreter& interp = __get_interpreter__ (); +static int safe_source_file (const std::string& file_name, + const std::string& context = "", + bool verbose = false, + bool require_file = true) +{ + interpreter& interp = __get_interpreter__ (); - try - { - source_file (file_name, context, verbose, require_file); - } - catch (const interrupt_exception&) - { - interp.recover_from_exception (); + try + { + source_file (file_name, context, verbose, require_file); + } + catch (const interrupt_exception&) + { + interp.recover_from_exception (); - return 1; - } - catch (const execution_exception& ee) - { - interp.handle_exception (ee); + return 1; + } + catch (const execution_exception& ee) + { + interp.handle_exception (ee); - return 1; - } + return 1; + } - return 0; - } + return 0; +} - static void initialize_version_info (void) - { - octave_value_list args; +static void initialize_version_info (void) +{ + octave_value_list args; - args(3) = OCTAVE_RELEASE_DATE; - args(2) = config::release (); - args(1) = OCTAVE_VERSION; - args(0) = "GNU Octave"; + args(3) = OCTAVE_RELEASE_DATE; + args(2) = config::release (); + args(1) = OCTAVE_VERSION; + args(0) = "GNU Octave"; - F__version_info__ (args, 0); - } + F__version_info__ (args, 0); +} - static void xerbla_abort (void) - { - error ("Fortran procedure terminated by call to XERBLA"); - } +static void xerbla_abort (void) +{ + error ("Fortran procedure terminated by call to XERBLA"); +} - static void initialize_xerbla_error_handler (void) - { - // The idea here is to force xerbla to be referenced so that we will - // link to our own version instead of the one provided by the BLAS - // library. But numeric_limits<double>::NaN () should never be -1, so - // we should never actually call xerbla. FIXME (again!): If this - // becomes a constant expression the test might be optimized away and - // then the reference to the function might also disappear. +static void initialize_xerbla_error_handler (void) +{ + // The idea here is to force xerbla to be referenced so that we will + // link to our own version instead of the one provided by the BLAS + // library. But numeric_limits<double>::NaN () should never be -1, so + // we should never actually call xerbla. FIXME (again!): If this + // becomes a constant expression the test might be optimized away and + // then the reference to the function might also disappear. - if (numeric_limits<double>::NaN () == -1) - F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6)); + if (numeric_limits<double>::NaN () == -1) + F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6)); - typedef void (*xerbla_handler_ptr) (void); + typedef void (*xerbla_handler_ptr) (void); - typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr); + typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr); - dynamic_library libs (""); + dynamic_library libs (""); - if (libs) - { - octave_set_xerbla_handler_ptr octave_set_xerbla_handler - = reinterpret_cast<octave_set_xerbla_handler_ptr> - (libs.search ("octave_set_xerbla_handler")); + if (libs) + { + octave_set_xerbla_handler_ptr octave_set_xerbla_handler + = reinterpret_cast<octave_set_xerbla_handler_ptr> + (libs.search ("octave_set_xerbla_handler")); - if (octave_set_xerbla_handler) - octave_set_xerbla_handler (xerbla_abort); - } - } + if (octave_set_xerbla_handler) + octave_set_xerbla_handler (xerbla_abort); + } +} - OCTAVE_NORETURN static void - lo_error_handler (const char *fmt, ...) - { - va_list args; - va_start (args, fmt); - verror_with_cfn (fmt, args); - va_end (args); +OCTAVE_NORETURN static void +lo_error_handler (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + verror_with_cfn (fmt, args); + va_end (args); - throw execution_exception (); - } + throw execution_exception (); +} - OCTAVE_NORETURN static void - lo_error_with_id_handler (const char *id, const char *fmt, ...) - { - va_list args; - va_start (args, fmt); - verror_with_id_cfn (id, fmt, args); - va_end (args); +OCTAVE_NORETURN static void +lo_error_with_id_handler (const char *id, const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + verror_with_id_cfn (id, fmt, args); + va_end (args); - throw execution_exception (); - } + throw execution_exception (); +} - static void initialize_error_handlers (void) - { - set_liboctave_error_handler (lo_error_handler); - set_liboctave_error_with_id_handler (lo_error_with_id_handler); - set_liboctave_warning_handler (warning); - set_liboctave_warning_with_id_handler (warning_with_id); - } +static void initialize_error_handlers (void) +{ + set_liboctave_error_handler (lo_error_handler); + set_liboctave_error_with_id_handler (lo_error_with_id_handler); + set_liboctave_warning_handler (warning); + set_liboctave_warning_with_id_handler (warning_with_id); +} - // Create an interpreter object and perform initialization up to the - // point of setting reading command history and setting the load - // path. +// Create an interpreter object and perform initialization up to the +// point of setting reading command history and setting the load +// path. - interpreter::interpreter (application *app_context) - : m_app_context (app_context), - m_tmp_files (), - m_atexit_fcns (), - m_display_info (), - m_environment (), - m_settings (), - m_error_system (*this), - m_evaluator (*this), - m_help_system (*this), - m_input_system (*this), - m_output_system (*this), - m_history_system (*this), - m_dynamic_loader (*this), - m_load_path (*this), - m_load_save_system (*this), - m_type_info (), - m_symbol_table (*this), - m_stream_list (*this), - m_child_list (), - m_url_handle_manager (), - m_cdef_manager (*this), - m_gtk_manager (), - m_event_manager (*this), - m_gh_manager (nullptr), - m_interactive (false), - m_read_site_files (true), - m_read_init_files (m_app_context != nullptr), - m_verbose (false), - m_traditional (false), - m_inhibit_startup_message (false), - m_load_path_initialized (false), - m_history_initialized (false), - m_interrupt_all_in_process_group (true), - m_cancel_quit (false), - m_executing_finish_script (false), - m_executing_atexit (false), - m_initialized (false) - { - // FIXME: When thread_local storage is used by default, this message - // should change to say something like - // - // only one Octave interpreter may be active in any given thread +interpreter::interpreter (application *app_context) + : m_app_context (app_context), + m_tmp_files (), + m_atexit_fcns (), + m_display_info (), + m_environment (), + m_settings (), + m_error_system (*this), + m_evaluator (*this), + m_help_system (*this), + m_input_system (*this), + m_output_system (*this), + m_history_system (*this), + m_dynamic_loader (*this), + m_load_path (*this), + m_load_save_system (*this), + m_type_info (), + m_symbol_table (*this), + m_stream_list (*this), + m_child_list (), + m_url_handle_manager (), + m_cdef_manager (*this), + m_gtk_manager (), + m_event_manager (*this), + m_gh_manager (nullptr), + m_interactive (false), + m_read_site_files (true), + m_read_init_files (m_app_context != nullptr), + m_verbose (false), + m_traditional (false), + m_inhibit_startup_message (false), + m_load_path_initialized (false), + m_history_initialized (false), + m_interrupt_all_in_process_group (true), + m_cancel_quit (false), + m_executing_finish_script (false), + m_executing_atexit (false), + m_initialized (false) +{ + // FIXME: When thread_local storage is used by default, this message + // should change to say something like + // + // only one Octave interpreter may be active in any given thread - if (m_instance) - throw std::runtime_error - ("only one Octave interpreter may be active"); + if (m_instance) + throw std::runtime_error + ("only one Octave interpreter may be active"); - m_instance = this; + m_instance = this; #if defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE) - // Force a UTF-8 locale on Windows if possible - std::setlocale (LC_ALL, ".UTF8"); + // Force a UTF-8 locale on Windows if possible + std::setlocale (LC_ALL, ".UTF8"); #else - std::setlocale (LC_ALL, ""); + std::setlocale (LC_ALL, ""); #endif - // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting - std::setlocale (LC_NUMERIC, "C"); - std::setlocale (LC_TIME, "C"); - sys::env::putenv ("LC_NUMERIC", "C"); - sys::env::putenv ("LC_TIME", "C"); + // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting + std::setlocale (LC_NUMERIC, "C"); + std::setlocale (LC_TIME, "C"); + sys::env::putenv ("LC_NUMERIC", "C"); + sys::env::putenv ("LC_TIME", "C"); + + // Initialize the default floating point unit control state. + octave_set_default_fpucw (); + + thread::init (); - // Initialize the default floating point unit control state. - octave_set_default_fpucw (); + octave_ieee_init (); - thread::init (); + initialize_xerbla_error_handler (); + + initialize_error_handlers (); - octave_ieee_init (); + if (m_app_context) + { + install_signal_handlers (); + octave_unblock_signal_by_name ("SIGTSTP"); + } + else + quit_allowed = false; - initialize_xerbla_error_handler (); + if (! m_app_context) + m_display_info.initialize (); - initialize_error_handlers (); + bool line_editing = false; - if (m_app_context) - { - install_signal_handlers (); - octave_unblock_signal_by_name ("SIGTSTP"); - } - else - quit_allowed = false; + if (m_app_context) + { + // Embedded interpreters don't execute command line options. + const cmdline_options& options = m_app_context->options (); + + // Make all command-line arguments available to startup files, + // including PKG_ADD files. + + string_vector args = options.all_args (); - if (! m_app_context) - m_display_info.initialize (); + m_app_context->intern_argv (args); + intern_nargin (args.numel () - 1); + + bool is_octave_program = m_app_context->is_octave_program (); + + std::list<std::string> command_line_path = options.command_line_path (); + + for (const auto& pth : command_line_path) + m_load_path.set_command_line_path (pth); - bool line_editing = false; + std::string exec_path = options.exec_path (); + if (! exec_path.empty ()) + m_environment.exec_path (exec_path); + + std::string image_path = options.image_path (); + if (! image_path.empty ()) + m_environment.image_path (image_path); - if (m_app_context) - { - // Embedded interpreters don't execute command line options. - const cmdline_options& options = m_app_context->options (); + if (! options.no_window_system ()) + m_display_info.initialize (); + + // Is input coming from a terminal? If so, we are probably + // interactive. - // Make all command-line arguments available to startup files, - // including PKG_ADD files. + // If stdin is not a tty, then we are reading commands from a + // pipe or a redirected file. + bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin)); - string_vector args = options.all_args (); + m_interactive = (! is_octave_program && stdin_is_tty + && octave_isatty_wrapper (fileno (stdout))); - m_app_context->intern_argv (args); - intern_nargin (args.numel () - 1); - - bool is_octave_program = m_app_context->is_octave_program (); + // Don't force interactive if we're already interactive (bug #60696). + bool forced_interactive = options.forced_interactive (); + if (m_interactive) + { + m_app_context->forced_interactive (false); + forced_interactive = false; + } - std::list<std::string> command_line_path = options.command_line_path (); + // Check if the user forced an interactive session. + if (forced_interactive) + m_interactive = true; - for (const auto& pth : command_line_path) - m_load_path.set_command_line_path (pth); + line_editing = options.line_editing (); + if ((! m_interactive || forced_interactive) + && ! options.forced_line_editing ()) + line_editing = false; + + m_traditional = options.traditional (); - std::string exec_path = options.exec_path (); - if (! exec_path.empty ()) - m_environment.exec_path (exec_path); + // FIXME: if possible, perform the following actions directly + // instead of using the interpreter-level functions. + + if (options.echo_commands ()) + m_evaluator.echo + (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS + | tree_evaluator::ECHO_ALL); - std::string image_path = options.image_path (); - if (! image_path.empty ()) - m_environment.image_path (image_path); + std::string docstrings_file = options.docstrings_file (); + if (! docstrings_file.empty ()) + Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file)); - if (! options.no_window_system ()) - m_display_info.initialize (); + std::string doc_cache_file = options.doc_cache_file (); + if (! doc_cache_file.empty ()) + Fdoc_cache_file (*this, octave_value (doc_cache_file)); - // Is input coming from a terminal? If so, we are probably - // interactive. + std::string info_file = options.info_file (); + if (! info_file.empty ()) + Finfo_file (*this, octave_value (info_file)); - // If stdin is not a tty, then we are reading commands from a - // pipe or a redirected file. - bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin)); + std::string info_program = options.info_program (); + if (! info_program.empty ()) + Finfo_program (*this, octave_value (info_program)); - m_interactive = (! is_octave_program && stdin_is_tty - && octave_isatty_wrapper (fileno (stdout))); + std::string texi_macros_file = options.texi_macros_file (); + if (! texi_macros_file.empty ()) + Ftexi_macros_file (*this, octave_value (texi_macros_file)); + } - // Don't force interactive if we're already interactive (bug #60696). - bool forced_interactive = options.forced_interactive (); - if (m_interactive) - { - m_app_context->forced_interactive (false); - forced_interactive = false; - } + // FIXME: we defer creation of the gh_manager object because it + // creates a root_figure object that requires the display_info + // object, but that is currently only accessible through the global + // interpreter object and that is not available until after the + // interpreter::instance pointer is set (above). It would be better + // if m_gh_manager could be an object value instead of a pointer and + // created as part of the interpreter initialization. To do that, + // we should either make the display_info object independent of the + // interpreter object (does it really need to cache any + // information?) or defer creation of the root_figure object until + // it is actually needed. + m_gh_manager = new gh_manager (*this); + + m_input_system.initialize (line_editing); - // Check if the user forced an interactive session. - if (forced_interactive) - m_interactive = true; + // These can come after command line args since none of them set any + // defaults that might be changed by command line options. + + initialize_version_info (); + + // This should be done before initializing the load path because + // some PKG_ADD files might need --traditional behavior. - line_editing = options.line_editing (); - if ((! m_interactive || forced_interactive) - && ! options.forced_line_editing ()) - line_editing = false; + if (m_traditional) + maximum_braindamage (); - m_traditional = options.traditional (); + octave_interpreter_ready = true; +} + +OCTAVE_THREAD_LOCAL interpreter *interpreter::m_instance = nullptr; - // FIXME: if possible, perform the following actions directly - // instead of using the interpreter-level functions. +interpreter::~interpreter (void) +{ + if (! m_app_context) + shutdown (); - if (options.echo_commands ()) - m_evaluator.echo - (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS - | tree_evaluator::ECHO_ALL); + delete m_gh_manager; +} - std::string docstrings_file = options.docstrings_file (); - if (! docstrings_file.empty ()) - Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file)); +void interpreter::intern_nargin (octave_idx_type nargs) +{ + m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs); +} + +// Read the history file unless a command-line option inhibits that. - std::string doc_cache_file = options.doc_cache_file (); - if (! doc_cache_file.empty ()) - Fdoc_cache_file (*this, octave_value (doc_cache_file)); +void interpreter::initialize_history (bool read_history_file) +{ + if (! m_history_initialized) + { + // Allow command-line option to override. + + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - std::string info_file = options.info_file (); - if (! info_file.empty ()) - Finfo_file (*this, octave_value (info_file)); + read_history_file = options.read_history_file (); - std::string info_program = options.info_program (); - if (! info_program.empty ()) - Finfo_program (*this, octave_value (info_program)); + if (! read_history_file) + command_history::ignore_entries (); + } + + m_history_system.initialize (read_history_file); + + if (! m_app_context) + command_history::ignore_entries (); - std::string texi_macros_file = options.texi_macros_file (); - if (! texi_macros_file.empty ()) - Ftexi_macros_file (*this, octave_value (texi_macros_file)); - } + m_history_initialized = true; + } +} + +// Set the initial path to the system default unless command-line +// option says to leave it empty. + +void interpreter::initialize_load_path (bool set_initial_path) +{ + if (! m_load_path_initialized) + { + // Allow command-line option to override. + + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); + + set_initial_path = options.set_initial_path (); + } - // FIXME: we defer creation of the gh_manager object because it - // creates a root_figure object that requires the display_info - // object, but that is currently only accessible through the global - // interpreter object and that is not available until after the - // interpreter::instance pointer is set (above). It would be better - // if m_gh_manager could be an object value instead of a pointer and - // created as part of the interpreter initialization. To do that, - // we should either make the display_info object independent of the - // interpreter object (does it really need to cache any - // information?) or defer creation of the root_figure object until - // it is actually needed. - m_gh_manager = new gh_manager (*this); + // Temporarily set the execute_pkg_add function to one that + // catches exceptions. This is better than wrapping + // load_path::initialize in a try-catch block because it will + // not stop executing PKG_ADD files at the first exception. + // It's also better than changing the default execute_pkg_add + // function to use safe_source file because that will normally + // be evaluated from the normal interpreter loop where exceptions + // are already handled. - m_input_system.initialize (line_editing); + unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path, + m_load_path.get_add_hook ()); + + m_load_path.set_add_hook ([=] (const std::string& dir) + { this->execute_pkg_add (dir); }); - // These can come after command line args since none of them set any - // defaults that might be changed by command line options. + m_load_path.initialize (set_initial_path); - initialize_version_info (); + m_load_path_initialized = true; + } +} + +// This may be called separately from execute - // This should be done before initializing the load path because - // some PKG_ADD files might need --traditional behavior. +void interpreter::initialize (void) +{ + if (m_initialized) + return; - if (m_traditional) - maximum_braindamage (); - - octave_interpreter_ready = true; - } - - OCTAVE_THREAD_LOCAL interpreter *interpreter::m_instance = nullptr; + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - interpreter::~interpreter (void) - { - if (! m_app_context) - shutdown (); + if (options.experimental_terminal_widget ()) + { + if (! options.gui ()) + display_startup_message (); + } + else + display_startup_message (); + } + else + display_startup_message (); + + // Wait to read the history file until the interpreter reads input + // files and begins evaluating commands. - delete m_gh_manager; - } + initialize_history (); + + // Initializing the load path may execute PKG_ADD files, so can't be + // done until the interpreter is ready to execute commands. - void interpreter::intern_nargin (octave_idx_type nargs) - { - m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs); - } + // Deferring it to the execute step also allows the path to be + // initialized between creating and execute the interpreter, for + // example, to set a custom path for an embedded interpreter. + + initialize_load_path (); + + octave_save_signal_mask (); + + can_interrupt = true; - // Read the history file unless a command-line option inhibits that. + octave_signal_hook = respond_to_pending_signals; + octave_interrupt_hook = nullptr; + + catch_interrupts (); + + // FIXME: could we eliminate this variable or make it not be global? + // Global used to communicate with signal handler. + octave_initialized = true; - void interpreter::initialize_history (bool read_history_file) - { - if (! m_history_initialized) - { - // Allow command-line option to override. + m_initialized = true; +} - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); +// Note: this function is currently only used with the new +// experimental terminal widget. + +void interpreter::get_line_and_eval (void) +{ + m_evaluator.get_line_and_eval (); +} - read_history_file = options.read_history_file (); +// Note: the following class is currently only used with the new +// experimental terminal widget. - if (! read_history_file) - command_history::ignore_entries (); - } +class cli_input_reader +{ +public: + + cli_input_reader (interpreter& interp) + : m_interpreter (interp), m_thread () { } - m_history_system.initialize (read_history_file); + cli_input_reader (const cli_input_reader&) = delete; + + cli_input_reader& operator = (const cli_input_reader&) = delete; - if (! m_app_context) - command_history::ignore_entries (); + ~cli_input_reader (void) + { + // FIXME: Would it be better to ensure that + // interpreter::get_line_and_eval exits and then call + // m_thread.join () here? - m_history_initialized = true; - } + m_thread.detach (); } - // Set the initial path to the system default unless command-line - // option says to leave it empty. - - void interpreter::initialize_load_path (bool set_initial_path) - { - if (! m_load_path_initialized) - { - // Allow command-line option to override. - - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - set_initial_path = options.set_initial_path (); - } - - // Temporarily set the execute_pkg_add function to one that - // catches exceptions. This is better than wrapping - // load_path::initialize in a try-catch block because it will - // not stop executing PKG_ADD files at the first exception. - // It's also better than changing the default execute_pkg_add - // function to use safe_source file because that will normally - // be evaluated from the normal interpreter loop where exceptions - // are already handled. - - unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path, - m_load_path.get_add_hook ()); - - m_load_path.set_add_hook ([=] (const std::string& dir) - { this->execute_pkg_add (dir); }); - - m_load_path.initialize (set_initial_path); - - m_load_path_initialized = true; - } - } - - // This may be called separately from execute - - void interpreter::initialize (void) + void start (void) { - if (m_initialized) - return; - - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - if (options.experimental_terminal_widget ()) - { - if (! options.gui ()) - display_startup_message (); - } - else - display_startup_message (); - } - else - display_startup_message (); - - // Wait to read the history file until the interpreter reads input - // files and begins evaluating commands. - - initialize_history (); - - // Initializing the load path may execute PKG_ADD files, so can't be - // done until the interpreter is ready to execute commands. - - // Deferring it to the execute step also allows the path to be - // initialized between creating and execute the interpreter, for - // example, to set a custom path for an embedded interpreter. - - initialize_load_path (); - - octave_save_signal_mask (); - - can_interrupt = true; - - octave_signal_hook = respond_to_pending_signals; - octave_interrupt_hook = nullptr; - - catch_interrupts (); - - // FIXME: could we eliminate this variable or make it not be global? - // Global used to communicate with signal handler. - octave_initialized = true; - - m_initialized = true; - } - - // Note: this function is currently only used with the new - // experimental terminal widget. - - void interpreter::get_line_and_eval (void) - { - m_evaluator.get_line_and_eval (); + m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter); } - // Note: the following class is currently only used with the new - // experimental terminal widget. +private: + + interpreter& m_interpreter; + + std::thread m_thread; +}; + +void interpreter::parse_and_execute (const std::string& input, + bool& incomplete_parse) +{ + m_evaluator.parse_and_execute (input, incomplete_parse); +} + +// FIXME: this function is intended to be executed only once. Should +// we enforce that restriction? + +int interpreter::execute (void) +{ + int exit_status = 0; + + try + { + initialize (); - class cli_input_reader - { - public: + execute_startup_files (); + + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); + + if (m_app_context->have_eval_option_code ()) + { + int status = execute_eval_option_code (); - cli_input_reader (interpreter& interp) - : m_interpreter (interp), m_thread () { } + if (status ) + exit_status = status; + + if (! options.persist ()) + { + shutdown (); - cli_input_reader (const cli_input_reader&) = delete; + return exit_status; + } + } + + // If there is an extra argument, see if it names a file to + // read. Additional arguments are taken as command line options + // for the script. - cli_input_reader& operator = (const cli_input_reader&) = delete; + if (m_app_context->have_script_file ()) + { + int status = execute_command_line_file (); + + if (status) + exit_status = status; + + if (! options.persist ()) + { + shutdown (); + + return exit_status; + } + } + + if (options.forced_interactive ()) + command_editor::blink_matching_paren (false); - ~cli_input_reader (void) + if (options.server ()) + exit_status = server_loop (); + else if (options.experimental_terminal_widget ()) + { + if (options.gui ()) + { + m_event_manager.start_gui (true); + + exit_status = server_loop (); + } + else + { + // Use an object so that the thread started for the + // reader will be cleaned up no matter how we exit + // this function. + + cli_input_reader reader (*this); + + reader.start (); + + exit_status = server_loop (); + } + } + else + exit_status = main_loop (); + + shutdown (); + } + } + catch (const exit_exception& xe) { - // FIXME: Would it be better to ensure that - // interpreter::get_line_and_eval exits and then call - // m_thread.join () here? + exit_status = xe.exit_status (); - m_thread.detach (); - } - - void start (void) - { - m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter); + shutdown (); } - private: - - interpreter& m_interpreter; - - std::thread m_thread; - }; - - void interpreter::parse_and_execute (const std::string& input, - bool& incomplete_parse) - { - m_evaluator.parse_and_execute (input, incomplete_parse); - } - - // FIXME: this function is intended to be executed only once. Should - // we enforce that restriction? - - int interpreter::execute (void) - { - int exit_status = 0; - - try - { - initialize (); - - execute_startup_files (); - - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - if (m_app_context->have_eval_option_code ()) - { - int status = execute_eval_option_code (); - - if (status ) - exit_status = status; - - if (! options.persist ()) - { - shutdown (); - - return exit_status; - } - } - - // If there is an extra argument, see if it names a file to - // read. Additional arguments are taken as command line options - // for the script. - - if (m_app_context->have_script_file ()) - { - int status = execute_command_line_file (); + return exit_status; +} - if (status) - exit_status = status; - - if (! options.persist ()) - { - shutdown (); - - return exit_status; - } - } - - if (options.forced_interactive ()) - command_editor::blink_matching_paren (false); - - if (options.server ()) - exit_status = server_loop (); - else if (options.experimental_terminal_widget ()) - { - if (options.gui ()) - { - m_event_manager.start_gui (true); - - exit_status = server_loop (); - } - else - { - // Use an object so that the thread started for the - // reader will be cleaned up no matter how we exit - // this function. - - cli_input_reader reader (*this); - - reader.start (); - - exit_status = server_loop (); - } - } - else - exit_status = main_loop (); - - shutdown (); - } - } - catch (const exit_exception& xe) - { - exit_status = xe.exit_status (); - - shutdown (); - } - - return exit_status; - } - - // Call a function with exceptions handled to avoid problems with - // errors while shutting down. +// Call a function with exceptions handled to avoid problems with +// errors while shutting down. #define OCTAVE_IGNORE_EXCEPTION(E) \ catch (E) \ @@ -965,1121 +965,1121 @@ } \ while (0) - void interpreter::shutdown (void) - { - // Attempt to prevent more than one call to shutdown. +void interpreter::shutdown (void) +{ + // Attempt to prevent more than one call to shutdown. - if (! m_initialized) - return; + if (! m_initialized) + return; - m_initialized = false; + m_initialized = false; - OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); + OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); - // Any atexit functions added after this function call won't be - // executed. Each atexit function is executed with - // OCTAVE_SAFE_CALL, so we don't need that here. + // Any atexit functions added after this function call won't be + // executed. Each atexit function is executed with + // OCTAVE_SAFE_CALL, so we don't need that here. - execute_atexit_fcns (); + execute_atexit_fcns (); - // Clear all functions and variables while the event manager is - // still processing events and notify the event manager. This way, - // the workspace model will be cleared before the GUI exits. + // Clear all functions and variables while the event manager is + // still processing events and notify the event manager. This way, + // the workspace model will be cleared before the GUI exits. - // FIXME: This approach seems a bit fragile since there could be - // other places in the GUI that have references to interpreter - // objects. How can we reliably ensure that they are all removed - // before the interpreter exits? Maybe the best solution is to - // always start the GUI from the interpreter and close it when the - // interpreter exits? However, the workspace model is owned by the - // base_qobject object not the workspace viewer or the main window, - // so simply closing the GUI window(s) is not sufficient. See also - // bug #61994. + // FIXME: This approach seems a bit fragile since there could be + // other places in the GUI that have references to interpreter + // objects. How can we reliably ensure that they are all removed + // before the interpreter exits? Maybe the best solution is to + // always start the GUI from the interpreter and close it when the + // interpreter exits? However, the workspace model is owned by the + // base_qobject object not the workspace viewer or the main window, + // so simply closing the GUI window(s) is not sufficient. See also + // bug #61994. - // Note that we don't force symbols to be cleared, so we will - // respect mlock at this point. Later, we'll force all variables - // and functions to be cleared. + // Note that we don't force symbols to be cleared, so we will + // respect mlock at this point. Later, we'll force all variables + // and functions to be cleared. - OCTAVE_SAFE_CALL (clear_all, ()); - OCTAVE_SAFE_CALL (m_event_manager.clear_workspace, ()); + OCTAVE_SAFE_CALL (clear_all, ()); + OCTAVE_SAFE_CALL (m_event_manager.clear_workspace, ()); - // If we are attached to a GUI, queue and event to close it (only - // works with the new terminal widget), process pending events and - // disable the link. + // If we are attached to a GUI, queue and event to close it (only + // works with the new terminal widget), process pending events and + // disable the link. - OCTAVE_SAFE_CALL (m_event_manager.close_gui, ()); - OCTAVE_SAFE_CALL (m_event_manager.process_events, (true)); - OCTAVE_SAFE_CALL (m_event_manager.disable, ()); + OCTAVE_SAFE_CALL (m_event_manager.close_gui, ()); + OCTAVE_SAFE_CALL (m_event_manager.process_events, (true)); + OCTAVE_SAFE_CALL (m_event_manager.disable, ()); - OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ()); - - // We may still have some figures. Close them. + OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ()); - OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); + // We may still have some figures. Close them. - // What is supposed to happen if a figure has a closerequestfcn or - // deletefcn callback registered that creates other figures or - // variables? What if those variables are classdef objects with - // destructors that can create figures? The possibilities are - // endless. At some point, we have to give up and force execution - // to end. + OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); - // Note that we again don't force symbols to be cleared, so we - // continue to respect mlock here. Later, we'll force all variables - // and functions to be cleared. + // What is supposed to happen if a figure has a closerequestfcn or + // deletefcn callback registered that creates other figures or + // variables? What if those variables are classdef objects with + // destructors that can create figures? The possibilities are + // endless. At some point, we have to give up and force execution + // to end. - OCTAVE_SAFE_CALL (clear_all, ()); + // Note that we again don't force symbols to be cleared, so we + // continue to respect mlock here. Later, we'll force all variables + // and functions to be cleared. - // Do this explicitly so that destructors for mex file objects - // are called, so that functions registered with mexAtExit are - // called. + OCTAVE_SAFE_CALL (clear_all, ()); - OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ()); + // Do this explicitly so that destructors for mex file objects + // are called, so that functions registered with mexAtExit are + // called. - OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ()); - - OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ()); + OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ()); - if (! command_history::ignoring_entries ()) - OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ()); + OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ()); + + OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ()); - OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ()); + if (! command_history::ignoring_entries ()) + OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ()); - // Now that the graphics toolkits have been unloaded, force all - // symbols to be cleared. + OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ()); - OCTAVE_SAFE_CALL (clear_all, (true)); + // Now that the graphics toolkits have been unloaded, force all + // symbols to be cleared. + + OCTAVE_SAFE_CALL (clear_all, (true)); - // FIXME: May still need something like this to ensure that - // destructors for class objects will run properly. Should that be - // done earlier? Before or after atexit functions are executed? - // What will happen if the destructor for an obect attempts to - // display a figure? + // FIXME: May still need something like this to ensure that + // destructors for class objects will run properly. Should that be + // done earlier? Before or after atexit functions are executed? + // What will happen if the destructor for an obect attempts to + // display a figure? - OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ()); + OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ()); - OCTAVE_SAFE_CALL (sysdep_cleanup, ()); + OCTAVE_SAFE_CALL (sysdep_cleanup, ()); - OCTAVE_SAFE_CALL (flush_stdout, ()); + OCTAVE_SAFE_CALL (flush_stdout, ()); - // Don't call singleton_cleanup_list::cleanup until we have the - // problems with registering/unregistering types worked out. For - // example, uncomment the following line, then use the make_int - // function from the examples directory to create an integer - // object and then exit Octave. Octave should crash with a - // segfault when cleaning up the typinfo singleton. We need some - // way to force new octave_value_X types that are created in - // .oct files to be unregistered when the .oct file shared library - // is unloaded. - // - // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); - } + // Don't call singleton_cleanup_list::cleanup until we have the + // problems with registering/unregistering types worked out. For + // example, uncomment the following line, then use the make_int + // function from the examples directory to create an integer + // object and then exit Octave. Octave should crash with a + // segfault when cleaning up the typinfo singleton. We need some + // way to force new octave_value_X types that are created in + // .oct files to be unregistered when the .oct file shared library + // is unloaded. + // + // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); +} - void interpreter::execute_atexit_fcns (void) - { - // Prevent atexit functions from adding new functions to the list. - m_executing_atexit = true; +void interpreter::execute_atexit_fcns (void) +{ + // Prevent atexit functions from adding new functions to the list. + m_executing_atexit = true; - while (! m_atexit_fcns.empty ()) - { - std::string fcn = m_atexit_fcns.front (); + while (! m_atexit_fcns.empty ()) + { + std::string fcn = m_atexit_fcns.front (); - m_atexit_fcns.pop_front (); + m_atexit_fcns.pop_front (); - OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0)); + OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0)); - OCTAVE_SAFE_CALL (flush_stdout, ()); - } - } + OCTAVE_SAFE_CALL (flush_stdout, ()); + } +} - void interpreter::display_startup_message (void) const - { - bool inhibit_startup_message = false; +void interpreter::display_startup_message (void) const +{ + bool inhibit_startup_message = false; - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - inhibit_startup_message = options.inhibit_startup_message (); - } + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - if (m_interactive && ! inhibit_startup_message) - std::cout << octave_startup_message () << "\n" << std::endl; - } + inhibit_startup_message = options.inhibit_startup_message (); + } - // Initialize by reading startup files. Return non-zero if an exception - // occurs when reading any of them, but don't exit early because of an - // exception. + if (m_interactive && ! inhibit_startup_message) + std::cout << octave_startup_message () << "\n" << std::endl; +} - int interpreter::execute_startup_files (void) - { - bool read_site_files = m_read_site_files; - bool read_init_files = m_read_init_files; - bool verbose = m_verbose; - bool inhibit_startup_message = m_inhibit_startup_message; +// Initialize by reading startup files. Return non-zero if an exception +// occurs when reading any of them, but don't exit early because of an +// exception. - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); +int interpreter::execute_startup_files (void) +{ + bool read_site_files = m_read_site_files; + bool read_init_files = m_read_init_files; + bool verbose = m_verbose; + bool inhibit_startup_message = m_inhibit_startup_message; - read_site_files = options.read_site_files (); - read_init_files = options.read_init_files (); - verbose = options.verbose_flag (); - inhibit_startup_message = options.inhibit_startup_message (); - } + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - verbose = (verbose && ! inhibit_startup_message); + read_site_files = options.read_site_files (); + read_init_files = options.read_init_files (); + verbose = options.verbose_flag (); + inhibit_startup_message = options.inhibit_startup_message (); + } - bool require_file = false; + verbose = (verbose && ! inhibit_startup_message); - std::string context; + bool require_file = false; - int exit_status = 0; + std::string context; + + int exit_status = 0; - if (read_site_files) - { - // Execute commands from the site-wide configuration file. - // First from the file $(prefix)/lib/octave/site/m/octaverc - // (if it exists), then from the file - // $(prefix)/share/octave/$(version)/m/octaverc (if it exists). + if (read_site_files) + { + // Execute commands from the site-wide configuration file. + // First from the file $(prefix)/lib/octave/site/m/octaverc + // (if it exists), then from the file + // $(prefix)/share/octave/$(version)/m/octaverc (if it exists). - int status = safe_source_file (config::local_site_defaults_file (), - context, verbose, require_file); + int status = safe_source_file (config::local_site_defaults_file (), + context, verbose, require_file); - if (status) - exit_status = status; + if (status) + exit_status = status; - status = safe_source_file (config::site_defaults_file (), - context, verbose, require_file); + status = safe_source_file (config::site_defaults_file (), + context, verbose, require_file); - if (status) - exit_status = status; - } + if (status) + exit_status = status; + } - if (read_init_files) - { - // Try to execute commands from the Matlab compatible startup.m file - // if it exists anywhere in the load path when starting Octave. - std::string ff_startup_m = file_in_path ("startup.m", ""); + if (read_init_files) + { + // Try to execute commands from the Matlab compatible startup.m file + // if it exists anywhere in the load path when starting Octave. + std::string ff_startup_m = file_in_path ("startup.m", ""); - if (! ff_startup_m.empty ()) - { - int parse_status = 0; + if (! ff_startup_m.empty ()) + { + int parse_status = 0; - try - { - eval_string (std::string ("startup"), false, parse_status, 0); - } - catch (const interrupt_exception&) - { - recover_from_exception (); - } - catch (const execution_exception& ee) - { - handle_exception (ee); - } - } - - // Try to execute commands from $CONFIG/octave/octaverc, where - // $CONFIG is the platform-dependent location for user local - // configuration files. + try + { + eval_string (std::string ("startup"), false, parse_status, 0); + } + catch (const interrupt_exception&) + { + recover_from_exception (); + } + catch (const execution_exception& ee) + { + handle_exception (ee); + } + } - std::string user_config_dir = sys::env::get_user_config_directory (); + // Try to execute commands from $CONFIG/octave/octaverc, where + // $CONFIG is the platform-dependent location for user local + // configuration files. - std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str () - + "octave"; + std::string user_config_dir = sys::env::get_user_config_directory (); - std::string cfg_rc = sys::env::make_absolute ("octaverc", cfg_dir); + std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str () + + "octave"; - if (! cfg_rc.empty ()) - { - int status = safe_source_file (cfg_rc, context, verbose, - require_file); + std::string cfg_rc = sys::env::make_absolute ("octaverc", cfg_dir); - if (status) - exit_status = status; - } + if (! cfg_rc.empty ()) + { + int status = safe_source_file (cfg_rc, context, verbose, + require_file); - // Try to execute commands from $HOME/$OCTAVE_INITFILE and - // $OCTAVE_INITFILE. If $OCTAVE_INITFILE is not set, - // .octaverc is assumed. + if (status) + exit_status = status; + } - bool home_rc_already_executed = false; - - std::string initfile = sys::env::getenv ("OCTAVE_INITFILE"); + // Try to execute commands from $HOME/$OCTAVE_INITFILE and + // $OCTAVE_INITFILE. If $OCTAVE_INITFILE is not set, + // .octaverc is assumed. - if (initfile.empty ()) - initfile = ".octaverc"; + bool home_rc_already_executed = false; - std::string home_dir = sys::env::get_home_directory (); + std::string initfile = sys::env::getenv ("OCTAVE_INITFILE"); - std::string home_rc = sys::env::make_absolute (initfile, home_dir); - - std::string local_rc; + if (initfile.empty ()) + initfile = ".octaverc"; - if (! home_rc.empty ()) - { - int status = safe_source_file (home_rc, context, verbose, - require_file); + std::string home_dir = sys::env::get_home_directory (); + + std::string home_rc = sys::env::make_absolute (initfile, home_dir); + + std::string local_rc; - if (status) - exit_status = status; + if (! home_rc.empty ()) + { + int status = safe_source_file (home_rc, context, verbose, + require_file); - // Names alone are not enough. - - sys::file_stat fs_home_rc (home_rc); + if (status) + exit_status = status; - if (fs_home_rc) - { - // We want to check for curr_dir after executing home_rc - // because doing that may change the working directory. + // Names alone are not enough. - local_rc = sys::env::make_absolute (initfile); + sys::file_stat fs_home_rc (home_rc); - home_rc_already_executed = same_file (home_rc, local_rc); - } - } + if (fs_home_rc) + { + // We want to check for curr_dir after executing home_rc + // because doing that may change the working directory. - if (! home_rc_already_executed) - { - if (local_rc.empty ()) local_rc = sys::env::make_absolute (initfile); - int status = safe_source_file (local_rc, context, verbose, - require_file); + home_rc_already_executed = same_file (home_rc, local_rc); + } + } - if (status) - exit_status = status; - } - } + if (! home_rc_already_executed) + { + if (local_rc.empty ()) + local_rc = sys::env::make_absolute (initfile); - if (m_interactive && verbose) - std::cout << std::endl; + int status = safe_source_file (local_rc, context, verbose, + require_file); - return exit_status; - } + if (status) + exit_status = status; + } + } - // Execute any code specified with --eval 'CODE' + if (m_interactive && verbose) + std::cout << std::endl; - int interpreter::execute_eval_option_code (void) - { - if (! m_app_context) - return 0; + return exit_status; +} + +// Execute any code specified with --eval 'CODE' - const cmdline_options& options = m_app_context->options (); - - std::string code_to_eval = options.code_to_eval (); +int interpreter::execute_eval_option_code (void) +{ + if (! m_app_context) + return 0; - unwind_protect_var<bool> upv (m_interactive, false); + const cmdline_options& options = m_app_context->options (); - int parse_status = 0; + std::string code_to_eval = options.code_to_eval (); + + unwind_protect_var<bool> upv (m_interactive, false); - try - { - eval_string (code_to_eval, false, parse_status, 0); - } - catch (const interrupt_exception&) - { - recover_from_exception (); + int parse_status = 0; - return 1; - } - catch (const execution_exception& ee) - { - handle_exception (ee); + try + { + eval_string (code_to_eval, false, parse_status, 0); + } + catch (const interrupt_exception&) + { + recover_from_exception (); - return 1; - } + return 1; + } + catch (const execution_exception& ee) + { + handle_exception (ee); - return parse_status; - } + return 1; + } - int interpreter::execute_command_line_file (void) - { - if (! m_app_context) - return 0; + return parse_status; +} - const cmdline_options& options = m_app_context->options (); +int interpreter::execute_command_line_file (void) +{ + if (! m_app_context) + return 0; - string_vector args = options.all_args (); + const cmdline_options& options = m_app_context->options (); - void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive; - unwind_action restore_interactive (interactive_fptr, this, m_interactive); + string_vector args = options.all_args (); - unwind_action restore_argv (&application::intern_argv, m_app_context, args); + void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive; + unwind_action restore_interactive (interactive_fptr, this, m_interactive); + + unwind_action restore_argv (&application::intern_argv, m_app_context, args); - unwind_action restore_nargin (&interpreter::intern_nargin, this, - args.numel () - 1); + unwind_action restore_nargin (&interpreter::intern_nargin, this, + args.numel () - 1); - void (application::*program_invocation_name_fptr) (const std::string&) - = &application::program_invocation_name; - unwind_action restore_program_invocation_name - (program_invocation_name_fptr, m_app_context, - application::program_invocation_name ()); + void (application::*program_invocation_name_fptr) (const std::string&) + = &application::program_invocation_name; + unwind_action restore_program_invocation_name + (program_invocation_name_fptr, m_app_context, + application::program_invocation_name ()); - void (application::*program_name_fptr) (const std::string&) - = &application::program_name; - unwind_action restore_program_name - (program_name_fptr, m_app_context, application::program_name ()); + void (application::*program_name_fptr) (const std::string&) + = &application::program_name; + unwind_action restore_program_name + (program_name_fptr, m_app_context, application::program_name ()); - m_interactive = false; + m_interactive = false; - // If we are running an executable script (#! /bin/octave) then - // we should only see the args passed to the script. + // If we are running an executable script (#! /bin/octave) then + // we should only see the args passed to the script. - string_vector script_args = options.remaining_args (); + string_vector script_args = options.remaining_args (); - m_app_context->intern_argv (script_args); - intern_nargin (script_args.numel () - 1); + m_app_context->intern_argv (script_args); + intern_nargin (script_args.numel () - 1); - std::string fname = script_args[0]; + std::string fname = script_args[0]; - m_app_context->set_program_names (fname); + m_app_context->set_program_names (fname); - std::string context; - bool verbose = false; - bool require_file = true; + std::string context; + bool verbose = false; + bool require_file = true; + + return safe_source_file (fname, context, verbose, require_file); +} - return safe_source_file (fname, context, verbose, require_file); - } +int interpreter::main_loop (void) +{ + command_editor::add_event_hook (release_unreferenced_dynamic_libraries); - int interpreter::main_loop (void) - { - command_editor::add_event_hook (release_unreferenced_dynamic_libraries); + return m_evaluator.repl (); +} - return m_evaluator.repl (); - } +int interpreter::server_loop (void) +{ + return m_evaluator.server_loop (); +} - int interpreter::server_loop (void) - { - return m_evaluator.server_loop (); - } +tree_evaluator& interpreter::get_evaluator (void) +{ + return m_evaluator; +} - tree_evaluator& interpreter::get_evaluator (void) - { - return m_evaluator; - } +stream_list& interpreter::get_stream_list (void) +{ + return m_stream_list; +} - stream_list& interpreter::get_stream_list (void) - { - return m_stream_list; - } +url_handle_manager& interpreter::get_url_handle_manager (void) +{ + return m_url_handle_manager; +} - url_handle_manager& interpreter::get_url_handle_manager (void) - { - return m_url_handle_manager; - } +symbol_scope +interpreter::get_top_scope (void) const +{ + return m_evaluator.get_top_scope (); +} - symbol_scope - interpreter::get_top_scope (void) const - { - return m_evaluator.get_top_scope (); - } +symbol_scope +interpreter::get_current_scope (void) const +{ + return m_evaluator.get_current_scope (); +} - symbol_scope - interpreter::get_current_scope (void) const - { - return m_evaluator.get_current_scope (); - } +symbol_scope +interpreter::require_current_scope (const std::string& who) const +{ + symbol_scope scope = get_current_scope (); + + if (! scope) + error ("%s: symbol table scope missing", who.c_str ()); - symbol_scope - interpreter::require_current_scope (const std::string& who) const - { - symbol_scope scope = get_current_scope (); + return scope; +} - if (! scope) - error ("%s: symbol table scope missing", who.c_str ()); +profiler& interpreter::get_profiler (void) +{ + return m_evaluator.get_profiler (); +} - return scope; - } +int interpreter::chdir (const std::string& dir) +{ + std::string xdir = sys::file_ops::tilde_expand (dir); - profiler& interpreter::get_profiler (void) - { - return m_evaluator.get_profiler (); - } + int cd_ok = sys::env::chdir (xdir); - int interpreter::chdir (const std::string& dir) - { - std::string xdir = sys::file_ops::tilde_expand (dir); + if (! cd_ok) + error ("%s: %s", dir.c_str (), std::strerror (errno)); + + Vlast_chdir_time.stamp (); - int cd_ok = sys::env::chdir (xdir); + // FIXME: should these actions be handled as a list of functions + // to call so users can add their own chdir handlers? - if (! cd_ok) - error ("%s: %s", dir.c_str (), std::strerror (errno)); - - Vlast_chdir_time.stamp (); + m_load_path.read_dir_config ("."); + m_load_path.update (); - // FIXME: should these actions be handled as a list of functions - // to call so users can add their own chdir handlers? + m_event_manager.directory_changed (sys::env::get_current_directory ()); - m_load_path.read_dir_config ("."); - m_load_path.update (); - - m_event_manager.directory_changed (sys::env::get_current_directory ()); + return cd_ok; +} - return cd_ok; - } +void interpreter::mlock (bool skip_first) const +{ + m_evaluator.mlock (skip_first); +} - void interpreter::mlock (bool skip_first) const - { - m_evaluator.mlock (skip_first); - } +void interpreter::munlock (bool skip_first) const +{ + m_evaluator.munlock (skip_first); +} - void interpreter::munlock (bool skip_first) const - { - m_evaluator.munlock (skip_first); - } +bool interpreter::mislocked (bool skip_first) const +{ + return m_evaluator.mislocked (skip_first); +} + +void interpreter::munlock (const char *nm) +{ + if (! nm) + error ("munlock: invalid value for NAME"); - bool interpreter::mislocked (bool skip_first) const - { - return m_evaluator.mislocked (skip_first); - } + munlock (std::string (nm)); +} - void interpreter::munlock (const char *nm) - { - if (! nm) - error ("munlock: invalid value for NAME"); +void interpreter::munlock (const std::string& nm) +{ + octave_value val = m_symbol_table.find_function (nm); - munlock (std::string (nm)); - } + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); - void interpreter::munlock (const std::string& nm) - { - octave_value val = m_symbol_table.find_function (nm); + if (fcn) + fcn->unlock (); + } +} - if (val.is_defined ()) - { - octave_function *fcn = val.function_value (); +bool interpreter::mislocked (const char *nm) +{ + if (! nm) + error ("mislocked: invalid value for NAME"); - if (fcn) - fcn->unlock (); - } - } + return mislocked (std::string (nm)); +} + +bool interpreter::mislocked (const std::string& nm) +{ + bool retval = false; - bool interpreter::mislocked (const char *nm) - { - if (! nm) - error ("mislocked: invalid value for NAME"); + octave_value val = m_symbol_table.find_function (nm); - return mislocked (std::string (nm)); - } + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); - bool interpreter::mislocked (const std::string& nm) - { - bool retval = false; - - octave_value val = m_symbol_table.find_function (nm); + if (fcn) + retval = fcn->islocked (); + } - if (val.is_defined ()) - { - octave_function *fcn = val.function_value (); + return retval; +} - if (fcn) - retval = fcn->islocked (); - } +std::string interpreter::mfilename (const std::string& opt) const +{ + return m_evaluator.mfilename (opt); +} - return retval; - } +octave_value_list interpreter::eval_string (const std::string& eval_str, + bool silent, int& parse_status, + int nargout) +{ + return m_evaluator.eval_string (eval_str, silent, parse_status, nargout); +} - std::string interpreter::mfilename (const std::string& opt) const - { - return m_evaluator.mfilename (opt); - } +octave_value interpreter::eval_string (const std::string& eval_str, + bool silent, int& parse_status) +{ + return m_evaluator.eval_string (eval_str, silent, parse_status); +} - octave_value_list interpreter::eval_string (const std::string& eval_str, - bool silent, int& parse_status, - int nargout) - { - return m_evaluator.eval_string (eval_str, silent, parse_status, nargout); - } +octave_value_list interpreter::eval_string (const octave_value& arg, + bool silent, int& parse_status, + int nargout) +{ + return m_evaluator.eval_string (arg, silent, parse_status, nargout); +} - octave_value interpreter::eval_string (const std::string& eval_str, - bool silent, int& parse_status) - { - return m_evaluator.eval_string (eval_str, silent, parse_status); - } +octave_value_list interpreter::eval (const std::string& try_code, + int nargout) +{ + return m_evaluator.eval (try_code, nargout); +} - octave_value_list interpreter::eval_string (const octave_value& arg, - bool silent, int& parse_status, - int nargout) - { - return m_evaluator.eval_string (arg, silent, parse_status, nargout); - } +octave_value_list interpreter::eval (const std::string& try_code, + const std::string& catch_code, + int nargout) +{ + return m_evaluator.eval (try_code, catch_code, nargout); +} - octave_value_list interpreter::eval (const std::string& try_code, +octave_value_list interpreter::evalin (const std::string& context, + const std::string& try_code, int nargout) - { - return m_evaluator.eval (try_code, nargout); - } +{ + return m_evaluator.evalin (context, try_code, nargout); +} - octave_value_list interpreter::eval (const std::string& try_code, +octave_value_list interpreter::evalin (const std::string& context, + const std::string& try_code, const std::string& catch_code, int nargout) - { - return m_evaluator.eval (try_code, catch_code, nargout); - } +{ + return m_evaluator.evalin (context, try_code, catch_code, nargout); +} - octave_value_list interpreter::evalin (const std::string& context, - const std::string& try_code, - int nargout) - { - return m_evaluator.evalin (context, try_code, nargout); - } +//! Evaluate an Octave function (built-in or interpreted) and return +//! the list of result values. +//! +//! @param name The name of the function to call. +//! @param args The arguments to the function. +//! @param nargout The number of output arguments expected. +//! @return A list of output values. The length of the list is not +//! necessarily the same as @c nargout. - octave_value_list interpreter::evalin (const std::string& context, - const std::string& try_code, - const std::string& catch_code, - int nargout) - { - return m_evaluator.evalin (context, try_code, catch_code, nargout); - } +octave_value_list interpreter::feval (const char *name, + const octave_value_list& args, + int nargout) +{ + return feval (std::string (name), args, nargout); +} - //! Evaluate an Octave function (built-in or interpreted) and return - //! the list of result values. - //! - //! @param name The name of the function to call. - //! @param args The arguments to the function. - //! @param nargout The number of output arguments expected. - //! @return A list of output values. The length of the list is not - //! necessarily the same as @c nargout. +octave_value_list interpreter::feval (const std::string& name, + const octave_value_list& args, + int nargout) +{ + octave_value fcn = m_symbol_table.find_function (name, args); + + if (fcn.is_undefined ()) + error ("feval: function '%s' not found", name.c_str ()); + + octave_function *of = fcn.function_value (); - octave_value_list interpreter::feval (const char *name, - const octave_value_list& args, - int nargout) - { - return feval (std::string (name), args, nargout); - } + return of->call (m_evaluator, nargout, args); +} - octave_value_list interpreter::feval (const std::string& name, - const octave_value_list& args, - int nargout) - { - octave_value fcn = m_symbol_table.find_function (name, args); +octave_value_list interpreter::feval (octave_function *fcn, + const octave_value_list& args, + int nargout) +{ + if (fcn) + return fcn->call (m_evaluator, nargout, args); - if (fcn.is_undefined ()) - error ("feval: function '%s' not found", name.c_str ()); - - octave_function *of = fcn.function_value (); + return octave_value_list (); +} - return of->call (m_evaluator, nargout, args); - } - - octave_value_list interpreter::feval (octave_function *fcn, - const octave_value_list& args, - int nargout) - { - if (fcn) - return fcn->call (m_evaluator, nargout, args); +octave_value_list interpreter::feval (const octave_value& val, + const octave_value_list& args, + int nargout) +{ + // FIXME: do we really want to silently return an empty ovl if + // the function object is undefined? It's essentially what the + // version above that accepts a pointer to an octave_function + // object does and some code was apparently written to rely on it + // (for example, __ode15__). - return octave_value_list (); - } + if (val.is_undefined ()) + return ovl (); - octave_value_list interpreter::feval (const octave_value& val, - const octave_value_list& args, - int nargout) - { - // FIXME: do we really want to silently return an empty ovl if - // the function object is undefined? It's essentially what the - // version above that accepts a pointer to an octave_function - // object does and some code was apparently written to rely on it - // (for example, __ode15__). + if (val.is_function ()) + { + return feval (val.function_value (), args, nargout); + } + else if (val.is_function_handle () || val.is_inline_function ()) + { + // This covers function handles, inline functions, and anonymous + // functions. - if (val.is_undefined ()) - return ovl (); + std::list<octave_value_list> arg_list; + arg_list.push_back (args); - if (val.is_function ()) - { - return feval (val.function_value (), args, nargout); - } - else if (val.is_function_handle () || val.is_inline_function ()) - { - // This covers function handles, inline functions, and anonymous - // functions. - - std::list<octave_value_list> arg_list; - arg_list.push_back (args); + // FIXME: could we make octave_value::subsref a const method? + // It would be difficult because there are instances of + // incrementing the reference count inside subsref methods, + // which means they can't be const with the current way of + // handling reference counting. - // FIXME: could we make octave_value::subsref a const method? - // It would be difficult because there are instances of - // incrementing the reference count inside subsref methods, - // which means they can't be const with the current way of - // handling reference counting. + octave_value xval = val; + return xval.subsref ("(", arg_list, nargout); + } + else if (val.is_string ()) + { + return feval (val.string_value (), args, nargout); + } + else + error ("feval: first argument must be a string, inline function, or a function handle"); - octave_value xval = val; - return xval.subsref ("(", arg_list, nargout); - } - else if (val.is_string ()) - { - return feval (val.string_value (), args, nargout); - } - else - error ("feval: first argument must be a string, inline function, or a function handle"); + return ovl (); +} - return ovl (); - } +//! Evaluate an Octave function (built-in or interpreted) and return +//! the list of result values. +//! +//! @param args The first element of @c args is the function to call. +//! It may be the name of the function as a string, a function +//! handle, or an inline function. The remaining arguments are +//! passed to the function. +//! @param nargout The number of output arguments expected. +//! @return A list of output values. The length of the list is not +//! necessarily the same as @c nargout. - //! Evaluate an Octave function (built-in or interpreted) and return - //! the list of result values. - //! - //! @param args The first element of @c args is the function to call. - //! It may be the name of the function as a string, a function - //! handle, or an inline function. The remaining arguments are - //! passed to the function. - //! @param nargout The number of output arguments expected. - //! @return A list of output values. The length of the list is not - //! necessarily the same as @c nargout. +octave_value_list interpreter::feval (const octave_value_list& args, + int nargout) +{ + if (args.length () == 0) + error ("feval: first argument must be a string, inline function, or a function handle"); - octave_value_list interpreter::feval (const octave_value_list& args, - int nargout) - { - if (args.length () == 0) - error ("feval: first argument must be a string, inline function, or a function handle"); + octave_value f_arg = args(0); + + octave_value_list tmp_args = args.slice (1, args.length () - 1, true); + + return feval (f_arg, tmp_args, nargout); +} - octave_value f_arg = args(0); +octave_value interpreter::make_function_handle (const std::string& name) +{ + return m_evaluator.make_fcn_handle (name); +} - octave_value_list tmp_args = args.slice (1, args.length () - 1, true); - - return feval (f_arg, tmp_args, nargout); - } +void interpreter::install_variable (const std::string& name, + const octave_value& value, bool global) +{ + m_evaluator.install_variable (name, value, global); +} - octave_value interpreter::make_function_handle (const std::string& name) - { - return m_evaluator.make_fcn_handle (name); - } +octave_value interpreter::global_varval (const std::string& name) const +{ + return m_evaluator.global_varval (name); +} - void interpreter::install_variable (const std::string& name, - const octave_value& value, bool global) - { - m_evaluator.install_variable (name, value, global); - } +void interpreter::global_assign (const std::string& name, + const octave_value& val) +{ + m_evaluator.global_assign (name, val); +} - octave_value interpreter::global_varval (const std::string& name) const - { - return m_evaluator.global_varval (name); - } +octave_value interpreter::top_level_varval (const std::string& name) const +{ + return m_evaluator.top_level_varval (name); +} - void interpreter::global_assign (const std::string& name, - const octave_value& val) - { - m_evaluator.global_assign (name, val); - } +void interpreter::top_level_assign (const std::string& name, + const octave_value& val) +{ + m_evaluator.top_level_assign (name, val); +} - octave_value interpreter::top_level_varval (const std::string& name) const - { - return m_evaluator.top_level_varval (name); - } +bool interpreter::is_variable (const std::string& name) const +{ + return m_evaluator.is_variable (name); +} - void interpreter::top_level_assign (const std::string& name, - const octave_value& val) - { - m_evaluator.top_level_assign (name, val); - } +bool interpreter::is_local_variable (const std::string& name) const +{ + return m_evaluator.is_local_variable (name); +} - bool interpreter::is_variable (const std::string& name) const - { - return m_evaluator.is_variable (name); - } +octave_value interpreter::varval (const std::string& name) const +{ + return m_evaluator.varval (name); +} - bool interpreter::is_local_variable (const std::string& name) const - { - return m_evaluator.is_local_variable (name); - } +void interpreter::assign (const std::string& name, + const octave_value& val) +{ + m_evaluator.assign (name, val); +} - octave_value interpreter::varval (const std::string& name) const - { - return m_evaluator.varval (name); - } +void interpreter::assignin (const std::string& context, + const std::string& name, + const octave_value& val) +{ + m_evaluator.assignin (context, name, val); +} - void interpreter::assign (const std::string& name, - const octave_value& val) - { - m_evaluator.assign (name, val); - } +void interpreter::source_file (const std::string& file_name, + const std::string& context, bool verbose, + bool require_file) +{ + m_evaluator.source_file (file_name, context, verbose, require_file); +} - void interpreter::assignin (const std::string& context, - const std::string& name, - const octave_value& val) - { - m_evaluator.assignin (context, name, val); - } +bool interpreter::at_top_level (void) const +{ + return m_evaluator.at_top_level (); +} + +bool interpreter::isglobal (const std::string& name) const +{ + return m_evaluator.is_global (name); +} - void interpreter::source_file (const std::string& file_name, - const std::string& context, bool verbose, - bool require_file) - { - m_evaluator.source_file (file_name, context, verbose, require_file); - } +octave_value interpreter::find (const std::string& name) +{ + return m_evaluator.find (name); +} - bool interpreter::at_top_level (void) const - { - return m_evaluator.at_top_level (); - } - - bool interpreter::isglobal (const std::string& name) const - { - return m_evaluator.is_global (name); - } +void interpreter::clear_all (bool force) +{ + m_evaluator.clear_all (force); +} - octave_value interpreter::find (const std::string& name) - { - return m_evaluator.find (name); - } +void interpreter::clear_objects (void) +{ + m_evaluator.clear_objects (); +} - void interpreter::clear_all (bool force) - { - m_evaluator.clear_all (force); - } +void interpreter::clear_variable (const std::string& name) +{ + m_evaluator.clear_variable (name); +} - void interpreter::clear_objects (void) - { - m_evaluator.clear_objects (); - } +void interpreter::clear_variable_pattern (const std::string& pattern) +{ + m_evaluator.clear_variable_pattern (pattern); +} - void interpreter::clear_variable (const std::string& name) - { - m_evaluator.clear_variable (name); - } +void interpreter::clear_variable_regexp (const std::string& pattern) +{ + m_evaluator.clear_variable_regexp (pattern); +} - void interpreter::clear_variable_pattern (const std::string& pattern) - { - m_evaluator.clear_variable_pattern (pattern); - } +void interpreter::clear_variables (void) +{ + m_evaluator.clear_variables (); +} - void interpreter::clear_variable_regexp (const std::string& pattern) - { - m_evaluator.clear_variable_regexp (pattern); - } +void interpreter::clear_global_variable (const std::string& name) +{ + m_evaluator.clear_global_variable (name); +} - void interpreter::clear_variables (void) - { - m_evaluator.clear_variables (); - } +void interpreter::clear_global_variable_pattern (const std::string& pattern) +{ + m_evaluator.clear_global_variable_pattern (pattern); +} - void interpreter::clear_global_variable (const std::string& name) - { - m_evaluator.clear_global_variable (name); - } +void interpreter::clear_global_variable_regexp (const std::string& pattern) +{ + m_evaluator.clear_global_variable_regexp (pattern); +} - void interpreter::clear_global_variable_pattern (const std::string& pattern) - { - m_evaluator.clear_global_variable_pattern (pattern); - } +void interpreter::clear_global_variables (void) +{ + m_evaluator.clear_global_variables (); +} - void interpreter::clear_global_variable_regexp (const std::string& pattern) - { - m_evaluator.clear_global_variable_regexp (pattern); - } +void interpreter::clear_functions (bool force) +{ + m_symbol_table.clear_functions (force); +} - void interpreter::clear_global_variables (void) - { - m_evaluator.clear_global_variables (); - } +void interpreter::clear_function (const std::string& name) +{ + m_symbol_table.clear_function (name); +} - void interpreter::clear_functions (bool force) - { - m_symbol_table.clear_functions (force); - } +void interpreter::clear_symbol (const std::string& name) +{ + m_evaluator.clear_symbol (name); +} - void interpreter::clear_function (const std::string& name) - { - m_symbol_table.clear_function (name); - } +void interpreter::clear_function_pattern (const std::string& pat) +{ + m_symbol_table.clear_function_pattern (pat); +} - void interpreter::clear_symbol (const std::string& name) - { - m_evaluator.clear_symbol (name); - } +void interpreter::clear_function_regexp (const std::string& pat) +{ + m_symbol_table.clear_function_regexp (pat); +} - void interpreter::clear_function_pattern (const std::string& pat) - { - m_symbol_table.clear_function_pattern (pat); - } +void interpreter::clear_symbol_pattern (const std::string& pat) +{ + return m_evaluator.clear_symbol_pattern (pat); +} - void interpreter::clear_function_regexp (const std::string& pat) - { - m_symbol_table.clear_function_regexp (pat); - } +void interpreter::clear_symbol_regexp (const std::string& pat) +{ + return m_evaluator.clear_symbol_regexp (pat); +} - void interpreter::clear_symbol_pattern (const std::string& pat) - { - return m_evaluator.clear_symbol_pattern (pat); - } +std::list<std::string> interpreter::global_variable_names (void) +{ + return m_evaluator.global_variable_names (); +} - void interpreter::clear_symbol_regexp (const std::string& pat) - { - return m_evaluator.clear_symbol_regexp (pat); - } +std::list<std::string> interpreter::top_level_variable_names (void) +{ + return m_evaluator.top_level_variable_names (); +} - std::list<std::string> interpreter::global_variable_names (void) - { - return m_evaluator.global_variable_names (); - } +std::list<std::string> interpreter::variable_names (void) +{ + return m_evaluator.variable_names (); +} - std::list<std::string> interpreter::top_level_variable_names (void) - { - return m_evaluator.top_level_variable_names (); - } +std::list<std::string> interpreter::user_function_names (void) +{ + return m_symbol_table.user_function_names (); +} - std::list<std::string> interpreter::variable_names (void) - { - return m_evaluator.variable_names (); - } +std::list<std::string> interpreter::autoloaded_functions (void) const +{ + return m_evaluator.autoloaded_functions (); +} + +// May be used to send an interrupt signal to the the interpreter from +// another thread (for example, the GUI). - std::list<std::string> interpreter::user_function_names (void) - { - return m_symbol_table.user_function_names (); - } +void interpreter::interrupt (void) +{ + static int sigint = 0; + static bool first = true; - std::list<std::string> interpreter::autoloaded_functions (void) const - { - return m_evaluator.autoloaded_functions (); - } - - // May be used to send an interrupt signal to the the interpreter from - // another thread (for example, the GUI). - - void interpreter::interrupt (void) - { - static int sigint = 0; - static bool first = true; + if (first) + { + octave_get_sig_number ("SIGINT", &sigint); + first = false; + } - if (first) - { - octave_get_sig_number ("SIGINT", &sigint); - first = false; - } + // 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. - // 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. - 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 (); +} - 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. - 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 (); +} - 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? - void interpreter::resume (void) - { - // FIXME: To be reliable, these tree_evaluator functions must be - // made thread safe. + if (m_evaluator.in_debug_repl ()) + m_evaluator.dbcont (); +} - // FIXME: Should there be any feeback about not doing anything if - // not in debug mode? - - if (m_evaluator.in_debug_repl ()) - m_evaluator.dbcont (); - } +// Provided for convenience. Will be removed once we eliminate the +// old terminal widget. +bool interpreter::experimental_terminal_widget (void) const +{ + if (! m_app_context) + return false; - // Provided for convenience. Will be removed once we eliminate the - // old terminal widget. - bool interpreter::experimental_terminal_widget (void) const - { - if (! m_app_context) - return false; + // Embedded interpreters don't execute command line options. + const cmdline_options& options = m_app_context->options (); + + return options.experimental_terminal_widget (); +} - // Embedded interpreters don't execute command line options. - const cmdline_options& options = m_app_context->options (); +void interpreter::add_debug_watch_expression (const std::string& expr) +{ + m_evaluator.add_debug_watch_expression (expr); +} - return options.experimental_terminal_widget (); - } - - void interpreter::add_debug_watch_expression (const std::string& expr) - { - m_evaluator.add_debug_watch_expression (expr); - } +void interpreter::remove_debug_watch_expression (const std::string& expr) +{ + m_evaluator.remove_debug_watch_expression (expr); +} - void interpreter::remove_debug_watch_expression (const std::string& expr) - { - m_evaluator.remove_debug_watch_expression (expr); - } +void interpreter::clear_debug_watch_expressions (void) +{ + m_evaluator.clear_debug_watch_expressions (); +} + +std::set<std::string> interpreter::debug_watch_expressions (void) const +{ + return m_evaluator.debug_watch_expressions (); +} - void interpreter::clear_debug_watch_expressions (void) - { - m_evaluator.clear_debug_watch_expressions (); - } +void interpreter::handle_exception (const execution_exception& ee) +{ + m_error_system.save_exception (ee); - std::set<std::string> interpreter::debug_watch_expressions (void) const - { - return m_evaluator.debug_watch_expressions (); - } + // FIXME: use a separate stream instead of std::cerr directly so that + // error messages can be redirected more easily? Pass the message + // to an event manager function? + m_error_system.display_exception (ee); - void interpreter::handle_exception (const execution_exception& ee) - { - m_error_system.save_exception (ee); + recover_from_exception (); +} - // FIXME: use a separate stream instead of std::cerr directly so that - // error messages can be redirected more easily? Pass the message - // to an event manager function? - m_error_system.display_exception (ee); +void interpreter::recover_from_exception (void) +{ + if (octave_interrupt_state) + m_event_manager.interpreter_interrupted (); - recover_from_exception (); - } - - void interpreter::recover_from_exception (void) - { - if (octave_interrupt_state) - m_event_manager.interpreter_interrupted (); + can_interrupt = true; + octave_interrupt_state = 0; + octave_signal_caught = 0; + octave_restore_signal_mask (); + catch_interrupts (); +} - can_interrupt = true; - octave_interrupt_state = 0; - octave_signal_caught = 0; - octave_restore_signal_mask (); - catch_interrupts (); - } +void interpreter::mark_for_deletion (const std::string& file) +{ + m_tmp_files.insert (file); +} - void interpreter::mark_for_deletion (const std::string& file) - { - m_tmp_files.insert (file); - } +void interpreter::cleanup_tmp_files (void) +{ + m_tmp_files.cleanup (); +} - void interpreter::cleanup_tmp_files (void) - { - m_tmp_files.cleanup (); - } +void interpreter::quit (int exit_status, bool force, bool confirm) +{ + if (! force) + { + try + { + bool cancel = false; - void interpreter::quit (int exit_status, bool force, bool confirm) - { - if (! force) - { - try - { - bool cancel = false; + if (symbol_exist ("finish.m", "file")) + { + unwind_protect_var<bool> upv1 (m_executing_finish_script, true); + unwind_protect_var<bool> upv2 (m_cancel_quit); + + evalin ("base", "finish", 0); - if (symbol_exist ("finish.m", "file")) - { - unwind_protect_var<bool> upv1 (m_executing_finish_script, true); - unwind_protect_var<bool> upv2 (m_cancel_quit); + cancel = m_cancel_quit; + } - evalin ("base", "finish", 0); + if (cancel) + return; - cancel = m_cancel_quit; - } - - if (cancel) - return; + // Check for confirmation. - // Check for confirmation. + if (confirm && ! m_event_manager.confirm_shutdown ()) + return; + } + catch (const execution_exception&) + { + // Catch execution_exceptions so we don't throw an + // exit_exception if there is an in finish.m. But throw it + // again so that will be handled as any other + // execution_exception by the evaluator. This way, errors + // will be ignored properly and we won't exit if quit is + // called recursively from finish.m. - if (confirm && ! m_event_manager.confirm_shutdown ()) - return; - } - catch (const execution_exception&) - { - // Catch execution_exceptions so we don't throw an - // exit_exception if there is an in finish.m. But throw it - // again so that will be handled as any other - // execution_exception by the evaluator. This way, errors - // will be ignored properly and we won't exit if quit is - // called recursively from finish.m. + throw; + } + } - throw; - } - } + throw exit_exception (exit_status); +} - throw exit_exception (exit_status); - } +void interpreter::add_atexit_fcn (const std::string& fname) +{ + if (m_executing_atexit) + return; - void interpreter::add_atexit_fcn (const std::string& fname) - { - if (m_executing_atexit) - return; + m_atexit_fcns.push_front (fname); +} - m_atexit_fcns.push_front (fname); - } - - bool interpreter::remove_atexit_fcn (const std::string& fname) - { - bool found = false; +bool interpreter::remove_atexit_fcn (const std::string& fname) +{ + bool found = false; - for (auto it = m_atexit_fcns.begin (); - it != m_atexit_fcns.end (); it++) - { - if (*it == fname) - { - m_atexit_fcns.erase (it); - found = true; - break; - } - } + for (auto it = m_atexit_fcns.begin (); + it != m_atexit_fcns.end (); it++) + { + if (*it == fname) + { + m_atexit_fcns.erase (it); + found = true; + break; + } + } + + return found; +} - return found; - } +// What internal options get configured by --traditional. - // What internal options get configured by --traditional. +void interpreter::maximum_braindamage (void) +{ + m_input_system.PS1 (">> "); + m_input_system.PS2 (""); - void interpreter::maximum_braindamage (void) - { - m_input_system.PS1 (">> "); - m_input_system.PS2 (""); + m_evaluator.PS4 (""); - m_evaluator.PS4 (""); + m_load_save_system.crash_dumps_octave_core (false); + m_load_save_system.save_default_options ("-mat-binary"); + + m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%"); - m_load_save_system.crash_dumps_octave_core (false); - m_load_save_system.save_default_options ("-mat-binary"); - - m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%"); - - m_error_system.beep_on_error (true); + m_error_system.beep_on_error (true); - Fconfirm_recursive_rmdir (octave_value (false)); - Foptimize_diagonal_matrix (octave_value (false)); - Foptimize_permutation_matrix (octave_value (false)); - Foptimize_range (octave_value (false)); - Ffixed_point_format (octave_value (true)); - Fprint_empty_dimensions (octave_value (false)); - Fprint_struct_array_contents (octave_value (true)); - Fstruct_levels_to_print (octave_value (0)); + Fconfirm_recursive_rmdir (octave_value (false)); + Foptimize_diagonal_matrix (octave_value (false)); + Foptimize_permutation_matrix (octave_value (false)); + Foptimize_range (octave_value (false)); + Ffixed_point_format (octave_value (true)); + Fprint_empty_dimensions (octave_value (false)); + Fprint_struct_array_contents (octave_value (true)); + Fstruct_levels_to_print (octave_value (0)); - m_error_system.disable_warning ("Octave:abbreviated-property-match"); - m_error_system.disable_warning ("Octave:colon-nonscalar-argument"); - m_error_system.disable_warning ("Octave:data-file-in-path"); - m_error_system.disable_warning ("Octave:empty-index"); - m_error_system.disable_warning ("Octave:function-name-clash"); - m_error_system.disable_warning ("Octave:possible-matlab-short-circuit-operator"); - } + m_error_system.disable_warning ("Octave:abbreviated-property-match"); + m_error_system.disable_warning ("Octave:colon-nonscalar-argument"); + m_error_system.disable_warning ("Octave:data-file-in-path"); + m_error_system.disable_warning ("Octave:empty-index"); + m_error_system.disable_warning ("Octave:function-name-clash"); + m_error_system.disable_warning ("Octave:possible-matlab-short-circuit-operator"); +} - void interpreter::execute_pkg_add (const std::string& dir) - { - try - { - m_load_path.execute_pkg_add (dir); - } - catch (const interrupt_exception&) - { - recover_from_exception (); - } - catch (const execution_exception& ee) - { - handle_exception (ee); - } - } +void interpreter::execute_pkg_add (const std::string& dir) +{ + try + { + m_load_path.execute_pkg_add (dir); + } + catch (const interrupt_exception&) + { + recover_from_exception (); + } + catch (const execution_exception& ee) + { + handle_exception (ee); + } +} OCTAVE_END_NAMESPACE(octave)