Mercurial > octave
diff libinterp/corefcn/interpreter.cc @ 23111:252975fdc444
more refactoring of interpreter and application classes
An embedded interperter is now just an interpreter that is running
without an application context.
* octave.h, octave.cc (embedded_application): Delete class.
(application::program_invocation_name, application::program_name,
application::argv, application::is_gui_running,
application::the_interpreter): Handle possibility that there is no
application instance.
* interpreter.h, interpreter.cc (interpreter::initialize_load_path):
Now a member function instead of a static file-scope function.
(interpreter::m_embedded): Delete data member.
(interpreter::m_read_site_files, interpreter::m_read_init_files,
interpreter::m_verbose, interpreter::m_inhibit_startup_message,
interpreter::m_load_path_initialized): New data members.
(interpreter::read_site_files, interpreter::read_init_files,
interpreter::verbose, interpreter::inhibit_startup_message):
New member functions.
(interpreter::interpreter): Eliminate embedded argument. Initialize
new data members. Refactor initialization sequence.
(interpreter::initialize_history): New function.
(interpreter::execute_internal, interpreter::display_startup_message,
interpreter::execute_startup_files): Refactor startup sequence.
(interpreter::main_loop): Handle EOF from parser.
(interpreter::cleanup): Don't print extra newline here.
(interpreter::recover_from_exception): Define as member function.
(interpreter::atexit_functions): Define as static member variable.
* embedded.cc: Update.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 28 Jan 2017 15:19:42 -0500 |
parents | af48d8be62b3 |
children | 17a3567a7b01 |
line wrap: on
line diff
--- a/libinterp/corefcn/interpreter.cc Fri Jan 27 18:15:48 2017 -0500 +++ b/libinterp/corefcn/interpreter.cc Sat Jan 28 15:19:42 2017 -0500 @@ -28,6 +28,7 @@ #include <iostream> #include "cmd-edit.h" +#include "cmd-hist.h" #include "file-ops.h" #include "file-stat.h" #include "fpucw-wrappers.h" @@ -354,37 +355,23 @@ } } -static void -initialize_load_path (bool 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 intepreter loop where - // exceptions are already handled. - - octave::unwind_protect frame; - - frame.add_fcn (load_path::set_add_hook, load_path::get_add_hook ()); - - load_path::set_add_hook (execute_pkg_add); - - load_path::initialize (set_initial_path); -} - namespace octave { tree_evaluator *current_evaluator = 0; - interpreter::interpreter (application *app_context, bool embedded) + interpreter::interpreter (application *app_context) : m_app_context (app_context), m_evaluator (new tree_evaluator (this)), - m_embedded (embedded), m_interactive (false) + m_interactive (false), m_read_site_files (true), + m_read_init_files (m_app_context != 0), m_verbose (false), + m_inhibit_startup_message (false), m_load_path_initialized (false) { current_evaluator = m_evaluator; - const cmdline_options& options = m_app_context->options (); + // This should probably happen early. + sysdep_init (); + + // Need to have global Vfoo variables defined early. + install_defaults (); // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting setlocale (LC_NUMERIC, "C"); @@ -395,8 +382,6 @@ // Initialize the default floating point unit control state. octave_set_default_fpucw (); - string_vector all_args = options.all_args (); - octave::thread::init (); set_default_prompts (); @@ -406,10 +391,9 @@ initialize_default_warning_state (); - if (options.traditional ()) - maximum_braindamage (); + octave_ieee_init (); - octave_ieee_init (); + octave_prepare_hdf5 (); // 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 @@ -423,7 +407,7 @@ initialize_error_handlers (); - if (! m_embedded) + if (app_context) octave::install_signal_handlers (); else quit_allowed = false; @@ -438,69 +422,82 @@ install_classdef (); - std::list<std::string> command_line_path = options.command_line_path (); + bool line_editing = false; + bool traditional = false; - for (const auto& pth : command_line_path) - load_path::set_command_line_path (pth); + if (app_context) + { + // Embedded interpeters don't execute command line options or + const cmdline_options& options = m_app_context->options (); - std::string exec_path = options.exec_path (); - if (! exec_path.empty ()) - set_exec_path (exec_path); + // Make all command-line arguments available to startup files, + // including PKG_ADD files. - std::string image_path = options.image_path (); - if (! image_path.empty ()) - set_image_path (image_path); + app_context->intern_argv (options.all_args ()); + + bool is_octave_program = m_app_context->is_octave_program (); + + std::list<std::string> command_line_path = options.command_line_path (); - if (options.no_window_system ()) - display_info::no_window_system (); + for (const auto& pth : command_line_path) + load_path::set_command_line_path (pth); - // Is input coming from a terminal? If so, we are probably interactive. + std::string exec_path = options.exec_path (); + if (! exec_path.empty ()) + set_exec_path (exec_path); - // 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 image_path = options.image_path (); + if (! image_path.empty ()) + set_image_path (image_path); + + if (options.no_window_system ()) + display_info::no_window_system (); - m_interactive = (! m_embedded - && ! m_app_context->is_octave_program () - && stdin_is_tty - && octave_isatty_wrapper (fileno (stdout))); + // Is input coming from a terminal? If so, we are probably + // interactive. + + // 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)); - // Check if the user forced an interactive session. - if (options.forced_interactive ()) - m_interactive = true; + m_interactive = (! is_octave_program && stdin_is_tty + && octave_isatty_wrapper (fileno (stdout))); + + // Check if the user forced an interactive session. + if (options.forced_interactive ()) + m_interactive = true; - bool line_editing = options.line_editing (); - if ((! m_interactive || options.forced_interactive ()) - && ! options.forced_line_editing ()) - line_editing = false; + line_editing = options.line_editing (); + if ((! m_interactive || options.forced_interactive ()) + && ! options.forced_line_editing ()) + line_editing = false; + + traditional = options.traditional (); + } // Force default line editor if we don't want readline editing. - if (! line_editing) + if (line_editing) + initialize_command_input (); + else octave::command_editor::force_default_editor (); // These can come after command line args since none of them set any // defaults that might be changed by command line options. - if (line_editing) - initialize_command_input (); - - octave_interpreter_ready = true; - initialize_version_info (); - // Make all command-line arguments available to startup files, - // including PKG_ADD files. + // This should be done before initializing the load path because + // some PKG_ADD files might need --traditional behavior. - app_context->intern_argv (options.all_args ()); + if (traditional) + maximum_braindamage (); - initialize_load_path (options.set_initial_path ()); - - initialize_history (options.read_history_file ()); + octave_interpreter_ready = true; } interpreter::~interpreter (void) { - if (m_embedded) + if (! m_app_context) cleanup (); current_evaluator = 0; @@ -521,17 +518,82 @@ exit_status = ex.exit_status (); } - if (! m_embedded) + if (m_app_context) cleanup (); return exit_status; } + // 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 intepreter loop where exceptions + // are already handled. + + octave::unwind_protect frame; + + frame.add_fcn (load_path::set_add_hook, load_path::get_add_hook ()); + + load_path::set_add_hook (execute_pkg_add); + + load_path::initialize (set_initial_path); + + m_load_path_initialized = true; + } + } + + 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 (); + + read_history_file = options.read_history_file (); + } + + ::initialize_history (read_history_file); + + if (! m_app_context) + octave::command_history::ignore_entries (); + + m_history_initialized = true; + } + } + int interpreter::execute_internal (void) { display_startup_message (); - octave_prepare_hdf5 (); + // Initializing the load path may execute PKG_ADD files. It also + // allows the path to be initialized between the calls to create and + // executeexecute the interpreter. + + initialize_load_path (); + + initialize_history (); // Don't fail, but return non-zero if there is an error in a startup // file. @@ -543,56 +605,67 @@ if (status) exit_status = status; - const cmdline_options& options = m_app_context->options (); + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - if (m_app_context->have_eval_option_code ()) - { - status = execute_eval_option_code (); + if (m_app_context->have_eval_option_code ()) + { + status = execute_eval_option_code (); - if (status ) - exit_status = status; + if (status ) + exit_status = status; - if (! options.persist ()) - return exit_status; - } + if (! options.persist ()) + 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 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 ()) + { + status = execute_command_line_file (); + + if (status) + exit_status = status; + + if (! options.persist ()) + return exit_status; + } - if (m_app_context->have_script_file ()) - { - status = execute_command_line_file (); + // Force input to be echoed if not really interactive, + // but the user has forced interactive behavior. - if (status) - exit_status = status; + if (options.forced_interactive ()) + { + octave::command_editor::blink_matching_paren (false); - if (! options.persist ()) - return exit_status; + // FIXME: is this the right thing to do? + Fecho_executing_commands (octave_value (ECHO_CMD_LINE)); + } } // Avoid counting commands executed from startup or script files. octave::command_editor::reset_current_command_number (1); - // Force input to be echoed if not really interactive, - // but the user has forced interactive behavior. - - if (options.forced_interactive ()) - { - octave::command_editor::blink_matching_paren (false); - - // FIXME: is this the right thing to do? - Fecho_executing_commands (octave_value (ECHO_CMD_LINE)); - } - return main_loop (); } void interpreter::display_startup_message (void) const { - const cmdline_options& options = m_app_context->options (); + bool inhibit_startup_message = false; - if (m_interactive && ! options.inhibit_startup_message ()) + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); + + inhibit_startup_message = options.inhibit_startup_message (); + } + + if (m_interactive && ! inhibit_startup_message) std::cout << octave_startup_message () << "\n" << std::endl; } @@ -602,14 +675,22 @@ int interpreter::execute_startup_files (void) const { - const cmdline_options& options = m_app_context->options (); + 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; - bool read_site_files = options.read_site_files (); - bool read_init_files = options.read_init_files (); - bool verbose_flag = options.verbose_flag (); - bool inhibit_startup_message = options.inhibit_startup_message (); + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - bool verbose = (verbose_flag && ! 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 (); + } + + verbose = (verbose && ! inhibit_startup_message); bool require_file = false; @@ -692,8 +773,7 @@ } } - if (m_interactive && ! options.inhibit_startup_message () - && options.verbose_flag ()) + if (m_interactive && verbose) std::cout << std::endl; return exit_status; @@ -801,7 +881,7 @@ int interpreter::main_loop (void) { - if (m_embedded) + if (! m_app_context) return 0; octave_save_signal_mask (); @@ -867,7 +947,10 @@ octave::command_editor::increment_current_command_number (); } else if (parser.lexer.end_of_input) - break; + { + retval = EOF; + break; + } } } catch (const octave::interrupt_exception&) @@ -921,7 +1004,12 @@ while (retval == 0); if (retval == EOF) - retval = 0; + { + if (octave::application::interactive ()) + octave_stdout << "\n"; + + retval = 0; + } return retval; } @@ -1017,16 +1105,6 @@ OCTAVE_SAFE_CALL (octave::flush_stdout, ()); - if (octave::application::interactive ()) - { - octave_stdout << "\n"; - - // Yes, we want this to be separate from the call to - // octave::flush_stdout above. - - OCTAVE_SAFE_CALL (octave::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 @@ -1043,7 +1121,7 @@ } } - void recover_from_exception (void) + void interpreter::recover_from_exception (void) { octave::can_interrupt = true; octave_interrupt_immediately = 0; @@ -1056,7 +1134,7 @@ // Functions to call when the interpreter exits. - std::list<std::string> atexit_functions; + std::list<std::string> interpreter::atexit_functions; void interpreter::add_atexit_function (const std::string& fname) {