Mercurial > octave
diff libinterp/corefcn/toplev.cc @ 22094:9203833cab7d
move new interpreter class to separate file
* libinterp/corefcn/interpreter.cc, libinterp/corefcn/interpreter.h:
New files. Move interpreter class and some supporting functions here
from octave.h, octave.cc, toplev.h, and toplev.cc. Move main_loop
into the interpreter class. Handle exiting with a separate exception
object from interrupts, passing the exit status with the object.
Update other files as needed to remove toplev.h or include
interpreter.h instead of toplev.h.
* libinterp/corefcn/module.mk: Update.
* toplev.h: Deprecate.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Mon, 11 Jul 2016 18:05:53 -0400 |
parents | 0f6fc2ec3b1a |
children | 9b78fda78300 |
line wrap: on
line diff
--- a/libinterp/corefcn/toplev.cc Tue Jul 12 10:17:45 2016 +0200 +++ b/libinterp/corefcn/toplev.cc Mon Jul 11 18:05:53 2016 -0400 @@ -24,14 +24,10 @@ # include "config.h" #endif -#include <cassert> #include <cerrno> #include <cstdlib> -#include <cstring> #include <new> -#include <fstream> -#include <iostream> #include <sstream> #include <string> @@ -40,18 +36,11 @@ # include <windows.h> #endif -#include "cmd-edit.h" -#include "cmd-hist.h" -#include "file-ops.h" +#include "child-list.h" #include "lo-error.h" -#include "lo-mappers.h" -#include "oct-env.h" #include "oct-fftw.h" #include "oct-locbuf.h" #include "oct-syscalls.h" -#include "quit.h" -#include "signal-wrappers.h" -#include "singleton-cleanup.h" #include "str-vec.h" #include "wait-for-input.h" @@ -62,366 +51,21 @@ #include "defun.h" #include "error.h" #include "file-io.h" -#include "graphics.h" -#include "input.h" -#include "lex.h" -#include "load-save.h" #include "octave.h" -#include "octave-link.h" -#include "oct-hist.h" #include "oct-map.h" #include "ovl.h" #include "ov.h" #include "pager.h" -#include "parse.h" -#include "pathsearch.h" #include "procstream.h" -#include "pt-eval.h" -#include "pt-jump.h" -#include "pt-stmt.h" -#include "sighandlers.h" #include "sysdep.h" -#include "toplev.h" #include "unwind-prot.h" #include "utils.h" -#include "variables.h" -#include "version.h" +#include <version.h> #if ! defined (SHELL_PATH) # define SHELL_PATH "/bin/sh" #endif -void (*octave_exit) (int) = ::exit; - -// TRUE means the quit() call is allowed. -bool quit_allowed = true; - -// TRUE means we are exiting via the builtin exit or quit functions. -bool quitting_gracefully = false; -// This stores the exit status. -int exit_status = 0; - -// TRUE means we are ready to interpret commands, but not everything -// is ready for interactive use. -bool octave_interpreter_ready = false; - -// TRUE means we've processed all the init code and we are good to go. -bool octave_initialized = false; - -void -recover_from_exception (void) -{ - octave::can_interrupt = true; - octave_interrupt_immediately = 0; - octave_interrupt_state = 0; - octave_signal_caught = 0; - octave_exception_state = octave_no_exception; - octave_restore_signal_mask (); - octave::catch_interrupts (); -} - -int -main_loop (void) -{ - octave_save_signal_mask (); - - octave::can_interrupt = true; - - octave_signal_hook = octave::signal_handler; - octave_interrupt_hook = 0; - octave_bad_alloc_hook = 0; - - octave::catch_interrupts (); - - octave_initialized = true; - - // The big loop. - - octave_lexer *lxr = (octave::application::interactive () - ? new octave_lexer () - : new octave_lexer (stdin)); - - octave_parser parser (*lxr); - - int retval = 0; - do - { - try - { - reset_error_handler (); - - parser.reset (); - - if (symbol_table::at_top_level ()) - tree_evaluator::reset_debug_state (); - - retval = parser.run (); - - if (retval == 0) - { - if (parser.stmt_list) - { - parser.stmt_list->accept (*current_evaluator); - - octave_quit (); - - if (! octave::application::interactive ()) - { - bool quit = (tree_return_command::returning - || tree_break_command::breaking); - - if (tree_return_command::returning) - tree_return_command::returning = 0; - - if (tree_break_command::breaking) - tree_break_command::breaking--; - - if (quit) - break; - } - - if (octave_completion_matches_called) - octave_completion_matches_called = false; - else - octave::command_editor::increment_current_command_number (); - } - else if (parser.lexer.end_of_input) - break; - } - } - catch (const octave_interrupt_exception&) - { - recover_from_exception (); - - if (quitting_gracefully) - return exit_status; - - // Required newline when the user does Ctrl+C at the prompt. - if (octave::application::interactive ()) - octave_stdout << "\n"; - } - catch (const index_exception& e) - { - recover_from_exception (); - - std::cerr << "error: unhandled index exception: " - << e.message () << " -- trying to return to prompt" - << std::endl; - } - catch (const octave_execution_exception& e) - { - std::string stack_trace = e.info (); - - if (! stack_trace.empty ()) - std::cerr << stack_trace; - - if (octave::application::interactive ()) - recover_from_exception (); - else - { - // We should exit with a nonzero status. - retval = 1; - break; - } - } - catch (const std::bad_alloc&) - { - recover_from_exception (); - - std::cerr << "error: out of memory -- trying to return to prompt" - << std::endl; - } - -#if defined (DBSTOP_NANINF) - if (Vdebug_on_naninf) - { - if (setjump (naninf_jump) != 0) - debug_or_throw_exception (true); // true = stack trace - } -#endif - } - while (retval == 0); - - if (octave::application::interactive ()) - octave_stdout << "\n"; - - if (retval == EOF) - retval = 0; - - return retval; -} - -// Fix up things before exiting. - -static std::list<std::string> octave_atexit_functions; - -static void -do_octave_atexit (void) -{ - static bool deja_vu = false; - - OCTAVE_SAFE_CALL (remove_input_event_hook_functions, ()); - - while (! octave_atexit_functions.empty ()) - { - std::string fcn = octave_atexit_functions.front (); - - octave_atexit_functions.pop_front (); - - OCTAVE_SAFE_CALL (reset_error_handler, ()); - - OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0)); - - OCTAVE_SAFE_CALL (flush_octave_stdout, ()); - } - - if (! deja_vu) - { - deja_vu = true; - - // Process pending events and disasble octave_link event - // processing with this call. - - octave_link::process_events (true); - - // Do this explicitly so that destructors for mex file objects - // are called, so that functions registered with mexAtExit are - // called. - OCTAVE_SAFE_CALL (clear_mex_functions, ()); - - OCTAVE_SAFE_CALL (octave::command_editor::restore_terminal_state, ()); - - // FIXME: is this needed? Can it cause any trouble? - OCTAVE_SAFE_CALL (raw_mode, (0)); - - OCTAVE_SAFE_CALL (octave_history_write_timestamp, ()); - - if (! octave::command_history::ignoring_entries ()) - OCTAVE_SAFE_CALL (octave::command_history::clean_up_and_save, ()); - - OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ()); - - OCTAVE_SAFE_CALL (gtk_manager::unload_all_toolkits, ()); - - OCTAVE_SAFE_CALL (close_files, ()); - - OCTAVE_SAFE_CALL (cleanup_tmp_files, ()); - - OCTAVE_SAFE_CALL (symbol_table::cleanup, ()); - - OCTAVE_SAFE_CALL (sysdep_cleanup, ()); - - OCTAVE_SAFE_CALL (octave_finalize_hdf5, ()); - - OCTAVE_SAFE_CALL (flush_octave_stdout, ()); - - if (! quitting_gracefully && octave::application::interactive ()) - { - octave_stdout << "\n"; - - // Yes, we want this to be separate from the call to - // flush_octave_stdout above. - - OCTAVE_SAFE_CALL (flush_octave_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, ()); - - OCTAVE_SAFE_CALL (octave_chunk_buffer::clear, ()); - } -} - -void -clean_up_and_exit (int status, bool safe_to_return) -{ - do_octave_atexit (); - - if (octave_link::exit (status)) - { - if (safe_to_return) - return; - else - { - // What should we do here? We might be called from some - // location other than the end of octave_execute_interpreter, - // so it might not be safe to return. - - // We have nothing else to do at this point, and the - // octave_link::exit function is supposed to take care of - // exiting for us. Assume that job won't take more than a - // day... - - octave_sleep (86400); // FIXME: really needed? - } - } - else - { - if (octave_exit) - (*octave_exit) (status); - } -} - -DEFUN (quit, args, , - doc: /* -*- texinfo -*- -@deftypefn {} {} exit -@deftypefnx {} {} exit (@var{status}) -@deftypefnx {} {} quit -@deftypefnx {} {} quit (@var{status}) -Exit the current Octave session. - -If the optional integer value @var{status} is supplied, pass that value to -the operating system as Octave's exit status. The default value is zero. - -When exiting, Octave will attempt to run the m-file @file{finish.m} if it -exists. User commands to save the workspace or clean up temporary files -may be placed in that file. Alternatively, another m-file may be scheduled -to run using @code{atexit}. -@seealso{atexit} -@end deftypefn */) -{ - // Confirm OK to shutdown. Note: A dynamic function installation similar - // to overriding polymorphism for which the GUI can install its own "quit" - // yet call this base "quit" could be nice. No link would be needed here. - if (! octave_link::confirm_shutdown ()) - return ovl (); - - if (! quit_allowed) - error ("quit: not supported in embedded mode"); - - if (args.length () > 0) - { - int tmp = args(0).nint_value (); - - exit_status = tmp; - } - - // Instead of simply calling exit, we simulate an interrupt - // with a request to exit cleanly so that no matter where the - // call to quit occurs, we will run the unwind_protect stack, - // clear the OCTAVE_LOCAL_BUFFER allocations, etc. before - // exiting. - - quitting_gracefully = true; - - octave_interrupt_state = -1; - - octave_throw_interrupt_exception (); - - return ovl (); -} - -DEFALIAS (exit, quit); - DEFUN (warranty, , , doc: /* -*- texinfo -*- @deftypefn {} {} warranty () @@ -669,97 +313,6 @@ %!error system (1, 2, 3) */ -void -octave_add_atexit_function (const std::string& fname) -{ - octave_atexit_functions.push_front (fname); -} - -bool -octave_remove_atexit_function (const std::string& fname) -{ - bool found = false; - - for (std::list<std::string>::iterator p = octave_atexit_functions.begin (); - p != octave_atexit_functions.end (); p++) - { - if (*p == fname) - { - octave_atexit_functions.erase (p); - found = true; - break; - } - } - - return found; -} - -DEFUN (atexit, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {} atexit (@var{fcn}) -@deftypefnx {} {} atexit (@var{fcn}, @var{flag}) -Register a function to be called when Octave exits. - -For example, - -@example -@group -function last_words () - disp ("Bye bye"); -endfunction -atexit ("last_words"); -@end group -@end example - -@noindent -will print the message @qcode{"Bye bye"} when Octave exits. - -The additional argument @var{flag} will register or unregister @var{fcn} -from the list of functions to be called when Octave exits. If @var{flag} is -true, the function is registered, and if @var{flag} is false, it is -unregistered. For example, after registering the function @code{last_words} -above, - -@example -atexit ("last_words", false); -@end example - -@noindent -will remove the function from the list and Octave will not call -@code{last_words} when it exits. - -Note that @code{atexit} only removes the first occurrence of a function -from the list, so if a function was placed in the list multiple times with -@code{atexit}, it must also be removed from the list multiple times. -@seealso{quit} -@end deftypefn */) -{ - int nargin = args.length (); - - if (nargin < 1 || nargin > 2) - print_usage (); - - 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; - - octave_value_list retval; - - if (add_mode) - octave_add_atexit_function (arg); - else - { - bool found = octave_remove_atexit_function (arg); - - if (nargout > 0) - retval = ovl (found); - } - - return retval; -} - static octave_value find_config_info (const octave_scalar_map& m, const std::string& key) {