changeset 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 6457ff946024
children 6119019d42f6
files libgui/graphics/__init_qt__.cc libinterp/corefcn/cellfun.cc libinterp/corefcn/debug.cc libinterp/corefcn/defaults.cc libinterp/corefcn/defun.cc libinterp/corefcn/dirfns.cc libinterp/corefcn/error.cc libinterp/corefcn/graphics.cc libinterp/corefcn/help.cc libinterp/corefcn/input.cc libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/load-path.cc libinterp/corefcn/ls-mat-ascii.cc libinterp/corefcn/ls-mat5.cc libinterp/corefcn/mex.cc libinterp/corefcn/module.mk libinterp/corefcn/oct-hist.cc libinterp/corefcn/oct-stream.cc libinterp/corefcn/octave-link.cc libinterp/corefcn/sighandlers.cc libinterp/corefcn/sysdep.cc libinterp/corefcn/toplev.cc libinterp/corefcn/toplev.h libinterp/corefcn/utils.cc libinterp/corefcn/variables.cc libinterp/dldfcn/__init_fltk__.cc libinterp/octave-value/ov-base.cc libinterp/octave-value/ov-builtin.cc libinterp/octave-value/ov-class.cc libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-fcn-handle.cc libinterp/octave-value/ov-fcn-inline.cc libinterp/octave-value/ov-mex-fcn.cc libinterp/octave-value/ov-oncleanup.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/octave.cc libinterp/octave.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-arg-list.cc libinterp/parse-tree/pt-bp.h libinterp/parse-tree/pt-eval.cc liboctave/cruft/misc/cquit.c liboctave/cruft/misc/quit.cc liboctave/cruft/misc/quit.h
diffstat 46 files changed, 1356 insertions(+), 1232 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/__init_qt__.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libgui/graphics/__init_qt__.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -32,7 +32,7 @@
 #include <QRegExp>
 
 #include "graphics.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "defun.h"
 
 #include "Backend.h"
--- a/libinterp/corefcn/cellfun.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/cellfun.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -39,11 +39,11 @@
 #include "Cell.h"
 #include "oct-map.h"
 #include "defun.h"
+#include "interpreter.h"
 #include "parse.h"
 #include "variables.h"
 #include "unwind-prot.h"
 #include "errwarn.h"
-#include "toplev.h"
 #include "utils.h"
 
 #include "ov-bool.h"
--- a/libinterp/corefcn/debug.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/debug.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -59,7 +59,7 @@
 #include "pt-exp.h"
 #include "pt-stmt.h"
 #include "sighandlers.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/defaults.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/defaults.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -47,7 +47,7 @@
 #include "ovl.h"
 #include "ov.h"
 #include "parse.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "variables.h"
 #include <version.h>
--- a/libinterp/corefcn/defun.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/defun.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -43,7 +43,7 @@
 #include "oct-lvalue.h"
 #include "pager.h"
 #include "symtab.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "variables.h"
 #include "parse.h"
 
--- a/libinterp/corefcn/dirfns.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/dirfns.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -54,7 +54,7 @@
 #include "pager.h"
 #include "procstream.h"
 #include "sysdep.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/error.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/error.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -47,7 +47,7 @@
 #include "pt-eval.h"
 #include "pt-pr-code.h"
 #include "pt-stmt.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "variables.h"
 
--- a/libinterp/corefcn/graphics.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/graphics.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -48,6 +48,7 @@
 #include "error.h"
 #include "graphics.h"
 #include "input.h"
+#include "interpreter.h"
 #include "ov.h"
 #include "ovl.h"
 #include "oct-map.h"
@@ -55,7 +56,6 @@
 #include "pager.h"
 #include "parse.h"
 #include "text-renderer.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "octave-default-image.h"
--- a/libinterp/corefcn/help.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/help.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -60,7 +60,7 @@
 #include "pt-pr-code.h"
 #include "sighandlers.h"
 #include "symtab.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/input.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/input.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -49,13 +49,14 @@
 #include "help.h"
 #include "hook-fcn.h"
 #include "input.h"
+#include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
 #include "octave.h"
 #include "octave-link.h"
 #include "oct-map.h"
 #include "oct-hist.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "octave-link.h"
 #include "ovl.h"
 #include "ov-fcn-handle.h"
@@ -68,7 +69,7 @@
 #include "sighandlers.h"
 #include "symtab.h"
 #include "sysdep.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/interpreter.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -0,0 +1,1097 @@
+/*
+
+Copyright (C) 1993-2015 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <string>
+#include <iostream>
+
+#include "cmd-edit.h"
+#include "f77-fcn.h"
+#include "file-ops.h"
+#include "file-stat.h"
+#include "fpucw-wrappers.h"
+#include "lo-error.h"
+#include "oct-env.h"
+#include "str-vec.h"
+#include "signal-wrappers.h"
+#include "unistd-wrappers.h"
+
+#include "builtins.h"
+#include "defaults.h"
+#include "Cell.h"
+#include "defun.h"
+#include "display.h"
+#include "error.h"
+#include "file-io.h"
+#include "graphics.h"
+#include "interpreter.h"
+#include "load-path.h"
+#include "load-save.h"
+#include "octave-link.h"
+#include "octave.h"
+#include "oct-hist.h"
+#include "oct-map.h"
+#include "oct-mutex.h"
+#include "ops.h"
+#include "ovl.h"
+#include "ov.h"
+#include "ov-classdef.h"
+#include "parse.h"
+#include "pt-eval.h"
+#include "pt-jump.h"
+#include "pt-stmt.h"
+#include "sighandlers.h"
+#include "sysdep.h"
+#include "unwind-prot.h"
+#include "utils.h"
+#include "variables.h"
+#include <version.h>
+
+void (*octave_exit) (int) = ::exit;
+
+// TRUE means the quit() call is allowed.
+bool quit_allowed = true;
+
+// 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;
+
+// Kluge.
+extern "C" F77_RET_T
+F77_FUNC (xerbla, XERBLA) (F77_CONST_CHAR_ARG_DECL,
+                           const octave_idx_type&
+                           F77_CHAR_ARG_LEN_DECL);
+
+DEFUN (__version_info__, args, ,
+       doc: /* -*- texinfo -*-
+@deftypefn {} {retval =} __version_info__ (@var{name}, @var{version}, @var{release}, @var{date})
+Undocumented internal function.
+@end deftypefn */)
+{
+  static octave_map vinfo;
+
+  int nargin = args.length ();
+
+  if (nargin != 0 && nargin != 4)
+    print_usage ();
+
+  octave_value retval;
+
+  if (nargin == 0)
+    retval = vinfo;
+  else if (nargin == 4)
+    {
+      if (vinfo.nfields () == 0)
+        {
+          vinfo.assign ("Name", args(0));
+          vinfo.assign ("Version", args(1));
+          vinfo.assign ("Release", args(2));
+          vinfo.assign ("Date", args(3));
+        }
+      else
+        {
+          octave_idx_type n = vinfo.numel () + 1;
+
+          vinfo.resize (dim_vector (n, 1));
+
+          octave_value idx (n);
+
+          vinfo.assign (idx, "Name", Cell (octave_value (args(0))));
+          vinfo.assign (idx, "Version", Cell (octave_value (args(1))));
+          vinfo.assign (idx, "Release", Cell (octave_value (args(2))));
+          vinfo.assign (idx, "Date", Cell (octave_value (args(3))));
+        }
+    }
+
+  return retval;
+}
+
+static void
+initialize_version_info (void)
+{
+  octave_value_list args;
+
+  args(3) = OCTAVE_RELEASE_DATE;
+  args(2) = OCTAVE_RELEASE;
+  args(1) = OCTAVE_VERSION;
+  args(0) = "GNU Octave";
+
+  F__version_info__ (args, 0);
+}
+
+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_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_throw_execution_exception ();
+}
+
+static void
+initialize_error_handlers ()
+{
+  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);
+}
+
+// What internal options get configured by --traditional.
+
+static void
+maximum_braindamage (void)
+{
+  FPS1 (octave_value (">> "));
+  FPS2 (octave_value (""));
+  FPS4 (octave_value (""));
+  Fbeep_on_error (octave_value (true));
+  Fconfirm_recursive_rmdir (octave_value (false));
+  Fcrash_dumps_octave_core (octave_value (false));
+  Fdisable_diagonal_matrix (octave_value (true));
+  Fdisable_permutation_matrix (octave_value (true));
+  Fdisable_range (octave_value (true));
+  Ffixed_point_format (octave_value (true));
+  Fhistory_timestamp_format_string (octave_value ("%%-- %D %I:%M %p --%%"));
+  Fpage_screen_output (octave_value (false));
+  Fprint_empty_dimensions (octave_value (false));
+  Fsave_default_options (octave_value ("-mat-binary"));
+  Fstruct_levels_to_print (octave_value (0));
+
+  disable_warning ("Octave:abbreviated-property-match");
+  disable_warning ("Octave:data-file-in-path");
+  disable_warning ("Octave:function-name-clash");
+  disable_warning ("Octave:possible-matlab-short-circuit-operator");
+}
+
+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 ();
+}
+
+// Fix up things before exiting.
+
+static std::list<std::string> octave_atexit_functions;
+
+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");
+
+  int exit_status = 0;
+
+  if (args.length () > 0)
+    exit_status = args(0).nint_value ();
+
+  // Instead of simply calling exit, we thrown an exception 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.
+
+  clean_up_and_exit (exit_status);
+
+  return ovl ();
+}
+
+DEFALIAS (exit, quit);
+
+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;
+}
+
+// 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 before we have entered the main loop in
+// toplev.cc.
+
+static void
+safe_source_file (const std::string& file_name,
+                  const std::string& context = "",
+                  bool verbose = false, bool require_file = true,
+                  const std::string& warn_for = "")
+{
+  try
+    {
+      source_file (file_name, context, verbose, require_file, warn_for);
+    }
+  catch (const index_exception& e)
+    {
+      recover_from_exception ();
+
+      std::cerr << "error: index exception in " << file_name << ": "
+                << e.message () << std::endl;
+    }
+  catch (const octave_exit_exception& ex)
+    {
+      recover_from_exception ();
+
+      clean_up_and_exit (ex.exit_status (), ex.safe_to_return ());
+    }
+  catch (const octave_interrupt_exception&)
+    {
+      recover_from_exception ();
+    }
+  catch (const octave_execution_exception&)
+    {
+      recover_from_exception ();
+
+      std::cerr << "error: execution exception in " << file_name << std::endl;
+    }
+}
+
+static void
+execute_pkg_add (const std::string& dir)
+{
+  std::string file_name = octave::sys::file_ops::concat (dir, "PKG_ADD");
+
+  try
+    {
+      load_path::execute_pkg_add (dir);
+    }
+  catch (const index_exception& e)
+    {
+      recover_from_exception ();
+
+      std::cerr << "error: index exception in " << file_name << ": "
+                << e.message () << std::endl;
+    }
+  catch (const octave_exit_exception& ex)
+    {
+      recover_from_exception ();
+
+      clean_up_and_exit (ex.exit_status (), ex.safe_to_return ());
+    }
+  catch (const octave_interrupt_exception&)
+    {
+      recover_from_exception ();
+    }
+  catch (const octave_execution_exception&)
+    {
+      recover_from_exception ();
+
+      std::cerr << "error: execution exception in " << file_name << std::endl;
+    }
+}
+
+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);
+}
+
+// Initialize by reading startup files.
+
+static void
+execute_startup_files (bool read_site_files, bool read_init_files,
+                       bool verbose_flag, bool inhibit_startup_message)
+{
+  octave::unwind_protect frame;
+
+  std::string context;
+
+  bool verbose = (verbose_flag && ! inhibit_startup_message);
+
+  bool require_file = false;
+
+  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).
+
+      safe_source_file (Vlocal_site_defaults_file, context, verbose,
+                        require_file);
+
+      safe_source_file (Vsite_defaults_file, context, verbose, require_file);
+    }
+
+  if (read_init_files)
+    {
+      // Try to execute commands from $HOME/$OCTAVE_INITFILE and
+      // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set,
+      // .octaverc is assumed.
+
+      bool home_rc_already_executed = false;
+
+      std::string initfile = octave::sys::env::getenv ("OCTAVE_INITFILE");
+
+      if (initfile.empty ())
+        initfile = ".octaverc";
+
+      std::string home_dir = octave::sys::env::get_home_directory ();
+
+      std::string home_rc = octave::sys::env::make_absolute (initfile, home_dir);
+
+      std::string local_rc;
+
+      if (! home_rc.empty ())
+        {
+          safe_source_file (home_rc, context, verbose, require_file);
+
+          // Names alone are not enough.
+
+          octave::sys::file_stat fs_home_rc (home_rc);
+
+          if (fs_home_rc)
+            {
+              // We want to check for curr_dir after executing home_rc
+              // because doing that may change the working directory.
+
+              local_rc = octave::sys::env::make_absolute (initfile);
+
+              home_rc_already_executed = same_file (home_rc, local_rc);
+            }
+        }
+
+      if (! home_rc_already_executed)
+        {
+          if (local_rc.empty ())
+            local_rc = octave::sys::env::make_absolute (initfile);
+
+          safe_source_file (local_rc, context, verbose, require_file);
+        }
+    }
+}
+
+namespace octave
+{
+  interpreter::interpreter (application *app_context, bool embedded)
+    : m_app_context (app_context), m_embedded (embedded),
+      m_interactive (false), m_quitting_gracefully (false)
+  {
+    cmdline_options options = m_app_context->options ();
+
+    sysdep_init ();
+
+    install_defaults ();
+
+    // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
+    setlocale (LC_NUMERIC, "C");
+    setlocale (LC_TIME, "C");
+    octave::sys::env::putenv ("LC_NUMERIC", "C");
+    octave::sys::env::putenv ("LC_TIME", "C");
+
+    // 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 ();
+
+    // Initialize default warning state before --traditional option
+    // that may reset them.
+
+    initialize_default_warning_state ();
+
+    if (options.traditional ())
+      maximum_braindamage ();
+
+    octave_ieee_init ();
+
+    // 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
+    // octave::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 (octave::numeric_limits<double>::NaN () == -1)
+      F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6));
+
+    initialize_error_handlers ();
+
+    if (! m_embedded)
+      octave::install_signal_handlers ();
+    else
+      quit_allowed = false;
+
+    initialize_file_io ();
+
+    install_types ();
+
+    install_ops ();
+
+    install_builtins ();
+
+    install_classdef ();
+
+    std::list<std::string> command_line_path = options.command_line_path ();
+
+    for (std::list<std::string>::const_iterator it = command_line_path.begin ();
+         it != command_line_path.end (); it++)
+      load_path::set_command_line_path (*it);
+
+    std::string exec_path = options.exec_path ();
+    if (! exec_path.empty ())
+      set_exec_path (exec_path);
+
+    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 ();
+
+    // 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));
+
+    m_interactive = (! m_embedded
+                     && ! m_app_context->is_octave_program ()
+                     && stdin_is_tty
+                     && octave_isatty_wrapper (fileno (stdout)));
+
+    // Check if the user forced an interactive session.  If he
+    // unnecessarily did so, reset forced_interactive to false.
+    if (options.forced_interactive ())
+      {
+        if (m_interactive)
+          options.forced_interactive (false);
+        else
+          m_interactive = true;
+      }
+
+    if ((! m_interactive || options.forced_interactive ())
+        && ! options.forced_line_editing ())
+      options.line_editing (false);
+
+    // Also skip start-up message unless session is interactive.
+    if (! m_interactive)
+      options.inhibit_startup_message (true);
+
+    // Force default line editor if we don't want readline editing.
+    if (! options.line_editing ())
+      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 (options.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.
+
+    app_context->intern_argv (options.all_args ());
+
+    initialize_load_path (options.set_initial_path ());
+
+    initialize_history (options.read_history_file ());
+  }
+
+  int interpreter::execute (void)
+  {
+    cmdline_options options = m_app_context->options ();
+
+    if (! options.inhibit_startup_message ())
+      std::cout << octave_startup_message () << "\n" << std::endl;
+
+    octave_prepare_hdf5 ();
+
+    execute_startup_files (options.read_site_files (),
+                           options.read_init_files (),
+                           options.verbose_flag (),
+                           options.inhibit_startup_message ());
+
+    if (! options.inhibit_startup_message ()
+        && reading_startup_message_printed)
+      std::cout << std::endl;
+
+    // Execute any code specified with --eval 'CODE'
+    std::string code_to_eval = options.code_to_eval ();
+
+    if (! code_to_eval.empty ())
+      {
+        int parse_status = 0;
+
+        try
+          {
+            parse_status = execute_eval_option_code (code_to_eval);
+          }
+        catch (const octave_execution_exception&)
+          {
+            recover_from_exception ();
+
+            parse_status = 1;
+          }
+
+        if (! options.persist ())
+          {
+            m_quitting_gracefully = true;
+
+            clean_up_and_exit (parse_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 ())
+      {
+        // If we are running an executable script (#! /bin/octave) then
+        // we should only see the args passed to the script.
+
+        int exit_status = 0;
+
+        try
+          {
+            string_vector script_args = options.remaining_args ();
+
+            m_app_context->intern_argv (script_args);
+
+            execute_command_line_file (script_args[0]);
+          }
+        catch (const octave_execution_exception&)
+          {
+            recover_from_exception ();
+
+            exit_status = 1;
+          }
+
+        // Restore full set of args.
+        m_app_context->intern_argv (options.all_args ());
+
+        if (! options.persist ())
+          {
+            m_quitting_gracefully = true;
+
+            clean_up_and_exit (exit_status);
+          }
+      }
+
+    // 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));
+      }
+
+    if (m_embedded)
+      {
+        // FIXME: Do we need to do any cleanup here before returning?
+        // If we don't, what will happen to Octave functions that have been
+        // registered to execute with atexit, for example?
+
+        return 1;
+      }
+
+    int retval = main_loop ();
+
+    m_quitting_gracefully = true;
+
+    clean_up_and_exit (retval, true);
+
+    return retval;
+  }
+
+  int interpreter::execute_eval_option_code (const std::string& code)
+  {
+    octave::unwind_protect frame;
+
+    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;
+
+    frame.add_method (this, &interpreter::interactive, m_interactive);
+
+    m_interactive = false;
+
+    int parse_status = 0;
+
+    try
+      {
+        eval_string (code, false, parse_status, 0);
+      }
+    catch (const octave_exit_exception& ex)
+      {
+        recover_from_exception ();
+
+        clean_up_and_exit (ex.exit_status (), ex.safe_to_return ());
+      }
+    catch (const octave_interrupt_exception&)
+      {
+        recover_from_exception ();
+      }
+    catch (const octave_execution_exception&)
+      {
+        recover_from_exception ();
+
+        std::cerr << "error: unhandled execution exception -- eval failed"
+                  << std::endl;
+      }
+
+    return parse_status;
+  }
+
+  void interpreter::execute_command_line_file (const std::string& fname)
+  {
+    octave::unwind_protect frame;
+
+    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;
+
+    frame.add_method (this, &interpreter::interactive, m_interactive);
+
+    frame.add_method (m_app_context,
+                      &application::program_invocation_name,
+                      application::program_invocation_name ());
+
+    frame.add_method (m_app_context,
+                      &application::program_name,
+                      application::program_name ());
+
+    m_interactive = false;
+
+    m_app_context->set_program_names (fname);
+
+    std::string context;
+    bool verbose = false;
+    bool require_file = true;
+
+    safe_source_file (fname, context, verbose, require_file, "octave");
+  }
+
+  int interpreter::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_exit_exception& ex)
+          {
+            recover_from_exception ();
+
+            clean_up_and_exit (ex.exit_status (), ex.safe_to_return ());
+          }
+        catch (const octave_interrupt_exception&)
+          {
+            recover_from_exception ();
+
+            // 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;
+  }
+
+  void interpreter::clean_up_and_exit (int status, bool safe_to_return)
+  {
+    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 (! m_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, ());
+      }
+
+    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);
+      }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/interpreter.h	Mon Jul 11 18:05:53 2016 -0400
@@ -0,0 +1,135 @@
+/*
+
+Copyright (C) 2002-2015 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_interpreter_h)
+#define octave_interpreter_h 1
+
+#include "octave-config.h"
+
+#include <string>
+
+#include "quit.h"
+#include "str-vec.h"
+
+typedef void (*octave_exit_func) (int);
+extern OCTINTERP_API octave_exit_func octave_exit;
+
+extern OCTINTERP_API bool quit_allowed;
+
+extern OCTINTERP_API bool quitting_gracefully;
+
+extern OCTINTERP_API void recover_from_exception (void);
+
+extern OCTINTERP_API void
+octave_add_atexit_function (const std::string& fname);
+
+extern OCTINTERP_API bool
+octave_remove_atexit_function (const std::string& fname);
+
+// TRUE means we are ready to interpret commands, but not everything
+// is ready for interactive use.
+extern OCTINTERP_API bool octave_interpreter_ready;
+
+// TRUE means we've processed all the init code and we are good to go.
+extern OCTINTERP_API bool octave_initialized;
+
+// Call a function with exceptions handled to avoid problems with
+// errors while shutting down.
+
+#define OCTAVE_IGNORE_EXCEPTION(E) \
+  catch (E) \
+    { \
+      std::cerr << "error: ignoring " #E " while preparing to exit" << std::endl; \
+      recover_from_exception (); \
+    }
+
+#define OCTAVE_SAFE_CALL(F, ARGS) \
+  do \
+    { \
+      try \
+        { \
+          octave::unwind_protect frame; \
+ \
+          frame.protect_var (Vdebug_on_error); \
+          frame.protect_var (Vdebug_on_warning); \
+ \
+          Vdebug_on_error = false; \
+          Vdebug_on_warning = false; \
+ \
+          F ARGS; \
+        } \
+      OCTAVE_IGNORE_EXCEPTION (const octave_interrupt_exception&) \
+      OCTAVE_IGNORE_EXCEPTION (const octave_execution_exception&) \
+      OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&) \
+    } \
+  while (0)
+
+namespace octave
+{
+  // The application object contains a pointer to the current
+  // interpreter and the interpreter contains a pointer back to the
+  // application context so we need a forward declaration for one (or
+  // both) of them...
+
+  class application;
+
+  class OCTINTERP_API interpreter
+  {
+  public:
+
+    interpreter (application *app_context = 0, bool embedded = false);
+
+    ~interpreter (void) { }
+
+    int execute (void);
+
+    int execute_eval_option_code (const std::string& code);
+
+    void execute_command_line_file (const std::string& fname);
+
+    bool interactive (void) const { return m_interactive; }
+    void interactive (bool arg) { m_interactive = arg; }
+
+  private:
+
+    // No copying, at least not yet...
+
+    interpreter (const interpreter&);
+
+    interpreter& operator = (const interpreter&);
+
+    int main_loop (void);
+
+    void clean_up_and_exit (int status, bool safe_to_return = false);
+    
+    application *m_app_context;
+
+    bool m_embedded;
+
+    // TRUE means this is an interactive interpreter (forced or not).
+    bool m_interactive;
+
+    bool m_quitting_gracefully;
+  };
+}
+
+#endif
--- a/libinterp/corefcn/load-path.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/load-path.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -37,11 +37,11 @@
 #include "defaults.h"
 #include "defun.h"
 #include "input.h"
+#include "interpreter.h"
 #include "load-path.h"
 #include "ov-usr-fcn.h"
 #include "pager.h"
 #include "parse.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
 
--- a/libinterp/corefcn/ls-mat-ascii.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/ls-mat-ascii.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -49,6 +49,7 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "interpreter.h"
 #include "lex.h"
 #include "load-save.h"
 #include "ls-ascii-helper.h"
@@ -59,7 +60,6 @@
 #include "pager.h"
 #include "pt-exp.h"
 #include "sysdep.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/ls-mat5.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/ls-mat5.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -65,7 +65,7 @@
 #include "pager.h"
 #include "pt-exp.h"
 #include "sysdep.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/mex.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/mex.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -40,6 +40,7 @@
 #include "Cell.h"
 #include "call-stack.h"
 #include "error.h"
+#include "interpreter.h"
 // mxArray must be declared as a class before including mexproto.h.
 #include "mxarray.h"
 #include "mexproto.h"
@@ -50,7 +51,6 @@
 #include "ov-usr-fcn.h"
 #include "pager.h"
 #include "parse.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/module.mk	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/module.mk	Mon Jul 11 18:05:53 2016 -0400
@@ -48,6 +48,7 @@
   libinterp/corefcn/help.h \
   libinterp/corefcn/hook-fcn.h \
   libinterp/corefcn/input.h \
+  libinterp/corefcn/interpreter.h \
   libinterp/corefcn/load-path.h \
   libinterp/corefcn/load-save.h \
   libinterp/corefcn/ls-ascii-helper.h \
@@ -179,6 +180,7 @@
   libinterp/corefcn/hook-fcn.cc \
   libinterp/corefcn/input.cc \
   libinterp/corefcn/inv.cc \
+  libinterp/corefcn/interpreter.cc \
   libinterp/corefcn/kron.cc \
   libinterp/corefcn/load-path.cc \
   libinterp/corefcn/load-save.cc \
--- a/libinterp/corefcn/oct-hist.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/oct-hist.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -61,7 +61,7 @@
 #include "parse.h"
 #include "sighandlers.h"
 #include "sysdep.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/oct-stream.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/oct-stream.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -50,12 +50,12 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "interpreter.h"
 #include "octave.h"
 #include "oct-stdstrm.h"
 #include "oct-stream.h"
 #include "ov.h"
 #include "ovl.h"
-#include "toplev.h"
 #include "utils.h"
 
 // Programming Note: There are two very different error functions used
--- a/libinterp/corefcn/octave-link.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/octave-link.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -32,7 +32,7 @@
 #include "oct-mutex.h"
 #include "pager.h"
 #include "singleton-cleanup.h"
-#include "toplev.h"
+#include "interpreter.h"
 
 #include "octave-link.h"
 
--- a/libinterp/corefcn/sighandlers.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/sighandlers.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -45,6 +45,7 @@
 #include "defun.h"
 #include "error.h"
 #include "input.h"
+#include "interpreter.h"
 #include "load-save.h"
 #include "octave.h"
 #include "oct-map.h"
@@ -53,7 +54,6 @@
 #include "pt-eval.h"
 #include "sighandlers.h"
 #include "sysdep.h"
-#include "toplev.h"
 #include "utils.h"
 #include "variables.h"
 
--- a/libinterp/corefcn/sysdep.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/sysdep.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -85,7 +85,7 @@
 #include "parse.h"
 #include "sighandlers.h"
 #include "sysdep.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "utils.h"
 #include "file-stat.h"
 
--- 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)
 {
--- a/libinterp/corefcn/toplev.h	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/toplev.h	Mon Jul 11 18:05:53 2016 -0400
@@ -25,68 +25,8 @@
 
 #include "octave-config.h"
 
-#include <string>
-
-#include "quit.h"
-
-typedef void (*octave_exit_func) (int);
-extern OCTINTERP_API octave_exit_func octave_exit;
-
-extern OCTINTERP_API bool quit_allowed;
-
-extern OCTINTERP_API bool quitting_gracefully;
-
-extern OCTINTERP_API int exit_status;
-
-extern OCTINTERP_API void
-clean_up_and_exit (int status, bool safe_to_return = false);
-
-extern OCTINTERP_API void recover_from_exception (void);
-
-extern OCTINTERP_API int main_loop (void);
-
-extern OCTINTERP_API void
-octave_add_atexit_function (const std::string& fname);
-
-extern OCTINTERP_API bool
-octave_remove_atexit_function (const std::string& fname);
-
-// TRUE means we are ready to interpret commands, but not everything
-// is ready for interactive use.
-extern OCTINTERP_API bool octave_interpreter_ready;
+#warning "toplev.h has been deprecated; use interpreter.h instead"
 
-// TRUE means we've processed all the init code and we are good to go.
-extern OCTINTERP_API bool octave_initialized;
-
-// Call a function with exceptions handled to avoid problems with
-// errors while shutting down.
-
-#define OCTAVE_IGNORE_EXCEPTION(E) \
-  catch (E) \
-    { \
-      std::cerr << "error: ignoring " #E " while preparing to exit" << std::endl; \
-      recover_from_exception (); \
-    }
-
-#define OCTAVE_SAFE_CALL(F, ARGS) \
-  do \
-    { \
-      try \
-        { \
-          octave::unwind_protect frame; \
- \
-          frame.protect_var (Vdebug_on_error); \
-          frame.protect_var (Vdebug_on_warning); \
- \
-          Vdebug_on_error = false; \
-          Vdebug_on_warning = false; \
- \
-          F ARGS; \
-        } \
-      OCTAVE_IGNORE_EXCEPTION (const octave_interrupt_exception&) \
-      OCTAVE_IGNORE_EXCEPTION (const octave_execution_exception&) \
-      OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&) \
-    } \
-  while (0)
+#include "interpreter.h"
 
 #endif
--- a/libinterp/corefcn/utils.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/utils.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -54,6 +54,7 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
 #include "oct-errno.h"
@@ -63,7 +64,6 @@
 #include "pager.h"
 #include "parse.h"
 #include "sysdep.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/corefcn/variables.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/corefcn/variables.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -48,6 +48,7 @@
 #include "errwarn.h"
 #include "help.h"
 #include "input.h"
+#include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
 #include "octave-link.h"
@@ -60,7 +61,6 @@
 #include "pager.h"
 #include "parse.h"
 #include "symtab.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
--- a/libinterp/dldfcn/__init_fltk__.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/dldfcn/__init_fltk__.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -89,7 +89,7 @@
 #include "gl2ps-print.h"
 #include "graphics.h"
 #include "parse.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "variables.h"
 
 #define FLTK_GRAPHICS_TOOLKIT_NAME "fltk"
--- a/libinterp/octave-value/ov-base.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-base.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -54,7 +54,7 @@
 #include "parse.h"
 #include "pr-output.h"
 #include "utils.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "variables.h"
 
 builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y)
--- a/libinterp/octave-value/ov-builtin.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-builtin.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -31,7 +31,7 @@
 #include "ov-builtin.h"
 #include "ov.h"
 #include "profiler.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 
 
--- a/libinterp/octave-value/ov-class.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-class.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -38,6 +38,7 @@
 #include "error.h"
 #include "file-ops.h"
 #include "errwarn.h"
+#include "interpreter.h"
 #include "load-path.h"
 #include "ls-hdf5.h"
 #include "ls-oct-text.h"
@@ -52,7 +53,6 @@
 #include "pager.h"
 #include "parse.h"
 #include "pr-output.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 #include "variables.h"
 
--- a/libinterp/octave-value/ov-classdef.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -42,7 +42,7 @@
 #include "pt-walk.h"
 #include "singleton-cleanup.h"
 #include "symtab.h"
-#include "toplev.h"
+#include "interpreter.h"
 
 // Define to 1 to enable debugging statements.
 #define DEBUG_TRACE 0
--- a/libinterp/octave-value/ov-fcn-handle.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -39,6 +39,7 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "interpreter.h"
 #include "oct-hdf5.h"
 #include "oct-map.h"
 #include "ov-base.h"
--- a/libinterp/octave-value/ov-fcn-inline.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -47,7 +47,7 @@
 #include "pr-output.h"
 #include "variables.h"
 #include "parse.h"
-#include "toplev.h"
+#include "interpreter.h"
 
 #include "byte-swap.h"
 #include "ls-ascii-helper.h"
--- a/libinterp/octave-value/ov-mex-fcn.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-mex-fcn.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -35,7 +35,7 @@
 #include "ov-mex-fcn.h"
 #include "ov.h"
 #include "profiler.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 
 
--- a/libinterp/octave-value/ov-oncleanup.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-oncleanup.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -25,11 +25,11 @@
 #endif
 
 #include "defun.h"
+#include "interpreter.h"
 #include "ov-oncleanup.h"
 #include "ov-fcn.h"
 #include "ov-usr-fcn.h"
 #include "pt-misc.h"
-#include "toplev.h"
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_oncleanup, "onCleanup",
                                      "onCleanup");
--- a/libinterp/octave-value/ov-usr-fcn.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -48,7 +48,7 @@
 #include "pt-stmt.h"
 #include "pt-walk.h"
 #include "symtab.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "parse.h"
--- a/libinterp/octave.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -26,346 +26,28 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-#include <clocale>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
+#include <string>
 
-#include <iostream>
-
-#include "cmd-edit.h"
-#include "f77-fcn.h"
 #include "file-ops.h"
-#include "file-stat.h"
-#include "fpucw-wrappers.h"
 #include "getopt-wrapper.h"
 #include "lo-error.h"
 #include "oct-env.h"
 #include "str-vec.h"
-#include "signal-wrappers.h"
-#include "unistd-wrappers.h"
 
-#include "build-env.h"
-#include "builtins.h"
-#include "defaults.h"
+#include "builtin-defun-decls.h"
 #include "Cell.h"
 #include "defun.h"
 #include "display.h"
 #include "error.h"
-#include "file-io.h"
-#include "help.h"
 #include "input.h"
-#include "lex.h"
-#include "load-path.h"
-#include "load-save.h"
+#include "interpreter.h"
 #include "octave.h"
 #include "oct-hist.h"
 #include "oct-map.h"
-#include "oct-mutex.h"
 #include "ovl.h"
-#include "ops.h"
 #include "options-usage.h"
 #include "ov.h"
-#include "ov-classdef.h"
-#include "ov-range.h"
-#include "toplev.h"
 #include "parse.h"
-#include "procstream.h"
-#include "sighandlers.h"
-#include "sysdep.h"
-#include "unwind-prot.h"
-#include "utils.h"
-#include "variables.h"
-#include <version.h>
-
-// Kluge.
-extern "C" F77_RET_T
-F77_FUNC (xerbla, XERBLA) (F77_CONST_CHAR_ARG_DECL,
-                           const octave_idx_type&
-                           F77_CHAR_ARG_LEN_DECL);
-
-extern void install_builtins (void);
-
-// Store the command-line options for later use.
-
-static void
-execute_pkg_add (const std::string& dir)
-{
-  std::string file_name = octave::sys::file_ops::concat (dir, "PKG_ADD");
-
-  try
-    {
-      load_path::execute_pkg_add (dir);
-    }
-  catch (const index_exception& e)
-    {
-      recover_from_exception ();
-
-      std::cerr << "error: index exception in " << file_name << ": "
-                << e.message () << std::endl;
-    }
-  catch (const octave_interrupt_exception&)
-    {
-      recover_from_exception ();
-
-      if (quitting_gracefully)
-        clean_up_and_exit (exit_status);
-    }
-  catch (const octave_execution_exception&)
-    {
-      recover_from_exception ();
-
-      std::cerr << "error: execution exception in " << file_name << std::endl;
-    }
-}
-
-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);
-}
-
-DEFUN (__version_info__, args, ,
-       doc: /* -*- texinfo -*-
-@deftypefn {} {retval =} __version_info__ (@var{name}, @var{version}, @var{release}, @var{date})
-Undocumented internal function.
-@end deftypefn */)
-{
-  static octave_map vinfo;
-
-  int nargin = args.length ();
-
-  if (nargin != 0 && nargin != 4)
-    print_usage ();
-
-  octave_value retval;
-
-  if (nargin == 0)
-    retval = vinfo;
-  else if (nargin == 4)
-    {
-      if (vinfo.nfields () == 0)
-        {
-          vinfo.assign ("Name", args(0));
-          vinfo.assign ("Version", args(1));
-          vinfo.assign ("Release", args(2));
-          vinfo.assign ("Date", args(3));
-        }
-      else
-        {
-          octave_idx_type n = vinfo.numel () + 1;
-
-          vinfo.resize (dim_vector (n, 1));
-
-          octave_value idx (n);
-
-          vinfo.assign (idx, "Name", Cell (octave_value (args(0))));
-          vinfo.assign (idx, "Version", Cell (octave_value (args(1))));
-          vinfo.assign (idx, "Release", Cell (octave_value (args(2))));
-          vinfo.assign (idx, "Date", Cell (octave_value (args(3))));
-        }
-    }
-
-  return retval;
-}
-
-static void
-initialize_version_info (void)
-{
-  octave_value_list args;
-
-  args(3) = OCTAVE_RELEASE_DATE;
-  args(2) = OCTAVE_RELEASE;
-  args(1) = OCTAVE_VERSION;
-  args(0) = "GNU Octave";
-
-  F__version_info__ (args, 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 before we have entered the main loop in
-// toplev.cc.
-
-static void
-safe_source_file (const std::string& file_name,
-                  const std::string& context = "",
-                  bool verbose = false, bool require_file = true,
-                  const std::string& warn_for = "")
-{
-  try
-    {
-      source_file (file_name, context, verbose, require_file, warn_for);
-    }
-  catch (const index_exception& e)
-    {
-      recover_from_exception ();
-
-      std::cerr << "error: index exception in " << file_name << ": "
-                << e.message () << std::endl;
-    }
-  catch (const octave_interrupt_exception&)
-    {
-      recover_from_exception ();
-
-      if (quitting_gracefully)
-        clean_up_and_exit (exit_status);
-    }
-  catch (const octave_execution_exception&)
-    {
-      recover_from_exception ();
-
-      std::cerr << "error: execution exception in " << file_name << std::endl;
-    }
-}
-
-// Initialize by reading startup files.
-
-static void
-execute_startup_files (bool read_site_files, bool read_init_files,
-                       bool verbose_flag, bool inhibit_startup_message)
-{
-  octave::unwind_protect frame;
-
-  std::string context;
-
-  bool verbose = (verbose_flag && ! inhibit_startup_message);
-
-  bool require_file = false;
-
-  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).
-
-      safe_source_file (Vlocal_site_defaults_file, context, verbose,
-                        require_file);
-
-      safe_source_file (Vsite_defaults_file, context, verbose, require_file);
-    }
-
-  if (read_init_files)
-    {
-      // Try to execute commands from $HOME/$OCTAVE_INITFILE and
-      // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set,
-      // .octaverc is assumed.
-
-      bool home_rc_already_executed = false;
-
-      std::string initfile = octave::sys::env::getenv ("OCTAVE_INITFILE");
-
-      if (initfile.empty ())
-        initfile = ".octaverc";
-
-      std::string home_dir = octave::sys::env::get_home_directory ();
-
-      std::string home_rc = octave::sys::env::make_absolute (initfile, home_dir);
-
-      std::string local_rc;
-
-      if (! home_rc.empty ())
-        {
-          safe_source_file (home_rc, context, verbose, require_file);
-
-          // Names alone are not enough.
-
-          octave::sys::file_stat fs_home_rc (home_rc);
-
-          if (fs_home_rc)
-            {
-              // We want to check for curr_dir after executing home_rc
-              // because doing that may change the working directory.
-
-              local_rc = octave::sys::env::make_absolute (initfile);
-
-              home_rc_already_executed = same_file (home_rc, local_rc);
-            }
-        }
-
-      if (! home_rc_already_executed)
-        {
-          if (local_rc.empty ())
-            local_rc = octave::sys::env::make_absolute (initfile);
-
-          safe_source_file (local_rc, context, verbose, require_file);
-        }
-    }
-}
-
-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_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_throw_execution_exception ();
-}
-
-static void
-initialize_error_handlers ()
-{
-  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);
-}
-
-// What internal options get configured by --traditional.
-
-static void
-maximum_braindamage (void)
-{
-  FPS1 (octave_value (">> "));
-  FPS2 (octave_value (""));
-  FPS4 (octave_value (""));
-  Fbeep_on_error (octave_value (true));
-  Fconfirm_recursive_rmdir (octave_value (false));
-  Fcrash_dumps_octave_core (octave_value (false));
-  Fdisable_diagonal_matrix (octave_value (true));
-  Fdisable_permutation_matrix (octave_value (true));
-  Fdisable_range (octave_value (true));
-  Ffixed_point_format (octave_value (true));
-  Fhistory_timestamp_format_string (octave_value ("%%-- %D %I:%M %p --%%"));
-  Fpage_screen_output (octave_value (false));
-  Fprint_empty_dimensions (octave_value (false));
-  Fsave_default_options (octave_value ("-mat-binary"));
-  Fstruct_levels_to_print (octave_value (0));
-
-  disable_warning ("Octave:abbreviated-property-match");
-  disable_warning ("Octave:data-file-in-path");
-  disable_warning ("Octave:function-name-clash");
-  disable_warning ("Octave:possible-matlab-short-circuit-operator");
-}
 
 namespace octave
 {
@@ -743,332 +425,6 @@
 
     return execute_interpreter ();
   }
-
-  interpreter::interpreter (application *app_context, bool embedded)
-    : m_app_context (app_context), m_embedded (embedded),
-      m_interactive (false)
-  {
-    cmdline_options options = m_app_context->options ();
-
-    sysdep_init ();
-
-    install_defaults ();
-
-    // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
-    setlocale (LC_NUMERIC, "C");
-    setlocale (LC_TIME, "C");
-    octave::sys::env::putenv ("LC_NUMERIC", "C");
-    octave::sys::env::putenv ("LC_TIME", "C");
-
-    // 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 ();
-
-    // Initialize default warning state before --traditional option
-    // that may reset them.
-
-    initialize_default_warning_state ();
-
-    if (options.traditional ())
-      maximum_braindamage ();
-
-    octave_ieee_init ();
-
-    // 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
-    // octave::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 (octave::numeric_limits<double>::NaN () == -1)
-      F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6));
-
-    initialize_error_handlers ();
-
-    if (! m_embedded)
-      octave::install_signal_handlers ();
-    else
-      quit_allowed = false;
-
-    initialize_file_io ();
-
-    install_types ();
-
-    install_ops ();
-
-    install_builtins ();
-
-    install_classdef ();
-
-    std::list<std::string> command_line_path = options.command_line_path ();
-
-    for (std::list<std::string>::const_iterator it = command_line_path.begin ();
-         it != command_line_path.end (); it++)
-      load_path::set_command_line_path (*it);
-
-    std::string exec_path = options.exec_path ();
-    if (! exec_path.empty ())
-      set_exec_path (exec_path);
-
-    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 ();
-
-    // 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));
-
-    m_interactive = (! m_embedded
-                     && ! m_app_context->is_octave_program ()
-                     && stdin_is_tty
-                     && octave_isatty_wrapper (fileno (stdout)));
-
-    // Check if the user forced an interactive session.  If he
-    // unnecessarily did so, reset forced_interactive to false.
-    if (options.forced_interactive ())
-      {
-        if (m_interactive)
-          options.forced_interactive (false);
-        else
-          m_interactive = true;
-      }
-
-    if ((! m_interactive || options.forced_interactive ())
-        && ! options.forced_line_editing ())
-      options.line_editing (false);
-
-    // Also skip start-up message unless session is interactive.
-    if (! m_interactive)
-      options.inhibit_startup_message (true);
-
-    // Force default line editor if we don't want readline editing.
-    if (! options.line_editing ())
-      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 (options.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.
-
-    app_context->intern_argv (options.all_args ());
-
-    initialize_load_path (options.set_initial_path ());
-
-    initialize_history (options.read_history_file ());
-  }
-
-  int interpreter::execute (void)
-  {
-    cmdline_options options = m_app_context->options ();
-
-    if (! options.inhibit_startup_message ())
-      std::cout << octave_startup_message () << "\n" << std::endl;
-
-    octave_prepare_hdf5 ();
-
-    execute_startup_files (options.read_site_files (),
-                           options.read_init_files (),
-                           options.verbose_flag (),
-                           options.inhibit_startup_message ());
-
-    if (! options.inhibit_startup_message ()
-        && reading_startup_message_printed)
-      std::cout << std::endl;
-
-    // Execute any code specified with --eval 'CODE'
-    std::string code_to_eval = options.code_to_eval ();
-
-    if (! code_to_eval.empty ())
-      {
-        int parse_status = 0;
-
-        try
-          {
-            parse_status = execute_eval_option_code (code_to_eval);
-          }
-        catch (const octave_execution_exception&)
-          {
-            recover_from_exception ();
-
-            parse_status = 1;
-          }
-
-        if (! options.persist ())
-          {
-            quitting_gracefully = true;
-
-            clean_up_and_exit (parse_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 ())
-      {
-        // If we are running an executable script (#! /bin/octave) then
-        // we should only see the args passed to the script.
-
-        exit_status = 0;
-
-        try
-          {
-            string_vector script_args = options.remaining_args ();
-
-            m_app_context->intern_argv (script_args);
-
-            execute_command_line_file (script_args[0]);
-          }
-        catch (const octave_execution_exception&)
-          {
-            recover_from_exception ();
-
-            exit_status = 1;
-          }
-
-        // Restore full set of args.
-        m_app_context->intern_argv (options.all_args ());
-
-        if (! options.persist ())
-          {
-            quitting_gracefully = true;
-
-            clean_up_and_exit (exit_status);
-          }
-      }
-
-    // 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));
-      }
-
-    if (m_embedded)
-      {
-        // FIXME: Do we need to do any cleanup here before returning?
-        // If we don't, what will happen to Octave functions that have been
-        // registered to execute with atexit, for example?
-
-        return 1;
-      }
-
-    int retval = main_loop ();
-
-    quitting_gracefully = true;
-
-    clean_up_and_exit (retval, true);
-
-    return retval;
-  }
-
-  int interpreter::execute_eval_option_code (const std::string& code)
-  {
-    octave::unwind_protect frame;
-
-    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;
-
-    frame.add_method (this, &interpreter::interactive, m_interactive);
-
-    m_interactive = false;
-
-    int parse_status = 0;
-
-    try
-      {
-        eval_string (code, false, parse_status, 0);
-      }
-    catch (const octave_interrupt_exception&)
-      {
-        recover_from_exception ();
-
-        if (quitting_gracefully)
-          clean_up_and_exit (exit_status);
-      }
-    catch (const octave_execution_exception&)
-      {
-        recover_from_exception ();
-
-        std::cerr << "error: unhandled execution exception -- eval failed"
-                  << std::endl;
-      }
-
-    return parse_status;
-  }
-
-  void interpreter::execute_command_line_file (const std::string& fname)
-  {
-    octave::unwind_protect frame;
-
-    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;
-
-    frame.add_method (this, &interpreter::interactive, m_interactive);
-
-    frame.add_method (m_app_context,
-                      &application::program_invocation_name,
-                      application::program_invocation_name ());
-
-    frame.add_method (m_app_context,
-                      &application::program_name,
-                      application::program_name ());
-
-    m_interactive = false;
-
-    m_app_context->set_program_names (fname);
-
-    std::string context;
-    bool verbose = false;
-    bool require_file = true;
-
-    safe_source_file (fname, context, verbose, require_file, "octave");
-  }
 }
 
 // embedded is int here because octave_main is extern "C".
--- a/libinterp/octave.h	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/octave.h	Mon Jul 11 18:05:53 2016 -0400
@@ -173,8 +173,8 @@
 
   // The application object contains a pointer to the current
   // interpreter and the interpreter contains a pointer back to the
-  // application context so we need a forward declaration for one of
-  // them...
+  // application context so we need a forward declaration for one (or
+  // both) of them...
 
   class interpreter;
 
@@ -330,39 +330,6 @@
 
     embedded_application& operator = (const embedded_application&);
   };
-
-  class OCTINTERP_API interpreter
-  {
-  public:
-
-    interpreter (application *app_context = 0, bool embedded = false);
-
-    ~interpreter (void) { }
-
-    int execute (void);
-
-    int execute_eval_option_code (const std::string& code);
-
-    void execute_command_line_file (const std::string& fname);
-
-    bool interactive (void) const { return m_interactive; }
-    void interactive (bool arg) { m_interactive = arg; }
-
-  private:
-
-    // No copying, at least not yet...
-
-    interpreter (const interpreter&);
-
-    interpreter& operator = (const interpreter&);
-
-    application *m_app_context;
-
-    bool m_embedded;
-
-    // TRUE means this is an interactive interpreter (forced or not).
-    bool m_interactive = false;
-  };
 }
 
 #endif
--- a/libinterp/parse-tree/lex.ll	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/parse-tree/lex.ll	Mon Jul 11 18:05:53 2016 -0400
@@ -106,6 +106,7 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "interpreter.h"
 #include "lex.h"
 #include "octave.h"
 #include "ov.h"
@@ -113,7 +114,6 @@
 #include "pt-all.h"
 #include "symtab.h"
 #include "token.h"
-#include "toplev.h"
 #include "utils.h"
 #include "variables.h"
 #include <oct-parse.h>
@@ -2321,8 +2321,7 @@
   // Only ask for input from stdin if we are expecting interactive
   // input.
 
-  if (! quitting_gracefully
-      && octave::application::interactive ()
+  if (octave::application::interactive ()
       && ! (reading_fcn_file
             || reading_classdef_file
             || reading_script_file
--- a/libinterp/parse-tree/oct-parse.in.yy	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/parse-tree/oct-parse.in.yy	Mon Jul 11 18:05:53 2016 -0400
@@ -61,6 +61,7 @@
 #include "dynamic-ld.h"
 #include "error.h"
 #include "input.h"
+#include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
 #include "oct-hist.h"
@@ -69,7 +70,6 @@
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
 #include "ov-null-mat.h"
-#include "toplev.h"
 #include "pager.h"
 #include "parse.h"
 #include "pt-all.h"
--- a/libinterp/parse-tree/pt-arg-list.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/parse-tree/pt-arg-list.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -41,7 +41,7 @@
 #include "pt-id.h"
 #include "pt-pr-code.h"
 #include "pt-walk.h"
-#include "toplev.h"
+#include "interpreter.h"
 #include "unwind-prot.h"
 
 // Argument lists.
--- a/libinterp/parse-tree/pt-bp.h	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/parse-tree/pt-bp.h	Mon Jul 11 18:05:53 2016 -0400
@@ -29,7 +29,7 @@
 #include "ov-usr-fcn.h"
 #include "pt-walk.h"
 #include "pt-pr-code.h"
-#include "toplev.h"
+#include "interpreter.h"
 
 class tree;
 class tree_decl_command;
--- a/libinterp/parse-tree/pt-eval.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -37,13 +37,13 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "interpreter.h"
 #include "ov-fcn-handle.h"
 #include "ov-usr-fcn.h"
 #include "variables.h"
 #include "pt-all.h"
 #include "pt-eval.h"
 #include "symtab.h"
-#include "toplev.h"
 #include "unwind-prot.h"
 
 //FIXME: This should be part of tree_evaluator
--- a/liboctave/cruft/misc/cquit.c	Tue Jul 12 10:17:45 2016 +0200
+++ b/liboctave/cruft/misc/cquit.c	Mon Jul 11 18:05:53 2016 -0400
@@ -59,4 +59,8 @@
 
 sig_atomic_t octave_exception_state = 0;
 
+sig_atomic_t octave_exit_exception_status = 0;
+
+sig_atomic_t octave_exit_exception_safe_to_return = 0;
+
 volatile sig_atomic_t octave_signal_caught = 0;
--- a/liboctave/cruft/misc/quit.cc	Tue Jul 12 10:17:45 2016 +0200
+++ b/liboctave/cruft/misc/quit.cc	Mon Jul 11 18:05:53 2016 -0400
@@ -48,6 +48,14 @@
     }
 }
 
+extern OCTAVE_API void
+clean_up_and_exit (int exit_status, bool safe_to_return)
+{
+  octave_exception_state = octave_quit_exception;
+
+  throw octave_exit_exception (exit_status, safe_to_return);
+}
+
 void
 octave_throw_interrupt_exception (void)
 {
@@ -98,6 +106,11 @@
           octave_throw_bad_alloc ();
           break;
 
+        case octave_quit_exception:
+          clean_up_and_exit (octave_exit_exception_status,
+                             octave_exit_exception_safe_to_return);
+          break;
+
         default:
           break;
         }
--- a/liboctave/cruft/misc/quit.h	Tue Jul 12 10:17:45 2016 +0200
+++ b/liboctave/cruft/misc/quit.h	Mon Jul 11 18:05:53 2016 -0400
@@ -59,6 +59,7 @@
 OCTAVE_NORETURN OCTAVE_API extern void octave_jump_to_enclosing_context (void);
 
 #if defined (__cplusplus)
+
 class
 octave_execution_exception
 {
@@ -100,16 +101,55 @@
 };
 
 class
+octave_exit_exception
+{
+public:
+
+  octave_exit_exception (int exit_status = 0, bool safe_to_return = false)
+    : m_exit_status (exit_status), m_safe_to_return (safe_to_return)
+  { }
+
+  octave_exit_exception (const octave_exit_exception& ex)
+    : m_exit_status (ex.m_exit_status), m_safe_to_return (ex.m_safe_to_return)
+  { }
+
+  octave_exit_exception& operator = (octave_exit_exception& ex)
+  {
+    if (this != &ex)
+      {
+        m_exit_status = ex.m_exit_status;
+        m_safe_to_return = ex.m_safe_to_return;
+      }
+
+    return *this;
+  }
+
+  ~octave_exit_exception (void) { }
+
+  int exit_status (void) const { return m_exit_status; }
+
+  bool safe_to_return (void) const { return m_safe_to_return; }
+
+private:
+
+  int m_exit_status;
+
+  bool m_safe_to_return;
+};
+
+class
 octave_interrupt_exception
 {
 };
+
 #endif
 
 enum octave_exception
 {
   octave_no_exception = 0,
   octave_exec_exception = 1,
-  octave_alloc_exception = 2
+  octave_alloc_exception = 3,
+  octave_quit_exception = 4
 };
 
 OCTAVE_API extern sig_atomic_t octave_interrupt_immediately;
@@ -123,6 +163,10 @@
 
 OCTAVE_API extern sig_atomic_t octave_exception_state;
 
+OCTAVE_API extern sig_atomic_t octave_exit_exception_status;
+
+OCTAVE_API extern sig_atomic_t octave_exit_exception_safe_to_return;
+
 OCTAVE_API extern volatile sig_atomic_t octave_signal_caught;
 
 OCTAVE_API extern void octave_handle_signal (void);
@@ -136,6 +180,10 @@
 OCTAVE_API extern void octave_rethrow_exception (void);
 
 #if defined (__cplusplus)
+
+extern OCTAVE_API void
+clean_up_and_exit (int exit_status, bool safe_to_return = false);
+
 inline void octave_quit (void)
 {
   if (octave_signal_caught)
@@ -234,6 +282,14 @@
       octave_exception_state = octave_alloc_exception; \
       octave_jump_to_enclosing_context (); \
     } \
+  catch (const octave_exit_exception& ex) \
+    { \
+      octave_interrupt_immediately = saved_octave_interrupt_immediately; \
+      octave_exception_state = octave_quit_exception; \
+      octave_exit_exception_status = ex.exit_status (); \
+      octave_exit_exception_safe_to_return = ex.safe_to_return (); \
+      octave_jump_to_enclosing_context (); \
+    } \
  \
   octave_interrupt_immediately = saved_octave_interrupt_immediately
 #endif