changeset 22089:c2c668b3051b

use classes for octave application and interpreter * main-cli.cc (main): Simplify using class objects. * main-gui.cc (main): Likeiwse. * octave.h, octave.cc (octave::cmdline_options, octave::application, octave::cli_application, octave::embedded_application, octave::interpreter): New classes. Replace ordinary functions and static/global data with objects. Access global application data through application object. * octave-gui.h, octave-gui.cc (octave::gui_application): New class. Replace ordinary functions and static/global data with objects. * main-window.cc (main_window::m_app_context): New data member. (main_window::main_window): Pass application object instead of start_gui flag. (main_window::construct_octave_qt_link): Pass m_app_context to octave_qt_link constructor. * octave-interpreter.h, octave-interpreter.cc (octave_interpreter::m_app_context, octave_interpreter::m_exit_status): New data members. (octave_interpreter::execute): Use class object to start interpreter. Save exit status. * octave-qt-link.h, octave-qt-link.cc (octave_qt_link::m_app_context): New data member. (octave_qt_link::do_set_default_prompts): Make prompt settings conditional on whether the GUI is running. * input.h, input.cc (interactive, forced_interactive): Delete global data. * dirfns.cc, error.cc, input.cc, oct-stream.cc, pager.cc, sighandlers.cc, sysdep.cc, toplev.cc, lex.ll: Access interactive and forced_interactive through global application object.
author John W. Eaton <jwe@octave.org>
date Sun, 10 Jul 2016 07:15:21 -0400
parents c3823cb0ea02
children 66db9a493c84
files libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-gui.cc libgui/src/octave-gui.h libgui/src/octave-interpreter.cc libgui/src/octave-interpreter.h libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libinterp/corefcn/dirfns.cc libinterp/corefcn/error.cc libinterp/corefcn/input.cc libinterp/corefcn/input.h libinterp/corefcn/oct-stream.cc libinterp/corefcn/pager.cc libinterp/corefcn/sighandlers.cc libinterp/corefcn/sysdep.cc libinterp/corefcn/toplev.cc libinterp/octave.cc libinterp/octave.h libinterp/parse-tree/lex.ll src/main-cli.cc src/main-gui.cc
diffstat 22 files changed, 1375 insertions(+), 878 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/main-window.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/main-window.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -60,6 +60,7 @@
 
 #include "builtin-defun-decls.h"
 #include "defaults.h"
+#include "octave.h"
 #include "symtab.h"
 #include "version.h"
 #include "utils.h"
@@ -74,26 +75,29 @@
 #endif
 }
 
-main_window::main_window (QWidget *p, bool start_gui)
-  : QMainWindow (p),
-    _workspace_model (start_gui ? new workspace_model () : 0),
-    status_bar (start_gui ? new QStatusBar () : 0),
-    command_window (start_gui ? new terminal_dock_widget (this) : 0),
-    history_window (start_gui ? new history_dock_widget (this) : 0),
-    file_browser_window (start_gui ? new files_dock_widget (this) : 0),
-    doc_browser_window (start_gui ? new documentation_dock_widget (this) : 0),
-    editor_window (start_gui ? create_default_editor (this) : 0),
-    workspace_window (start_gui ? new workspace_view (this) : 0),
-    _settings_dlg (0),
-    find_files_dlg (0),
-    release_notes_window (0),
-    community_news_window (0),
-    _octave_qt_link (0),
+main_window::main_window (QWidget *p, octave::gui_application *app_context)
+  : QMainWindow (p), m_app_context (app_context), _workspace_model (0),
+    status_bar (0), command_window (0), history_window (0),
+    file_browser_window (0), doc_browser_window (0), editor_window (0),
+    workspace_window (0), _settings_dlg (0), find_files_dlg (0),
+    release_notes_window (0), community_news_window (0), _octave_qt_link (0),
     _clipboard (QApplication::clipboard ()),
     _prevent_readline_conflicts (true),
     _suppress_dbg_location (true),
-    _start_gui (start_gui)
+    _start_gui (app_context && app_context->start_gui_p ())
 {
+  if (_start_gui)
+    {
+      _workspace_model = new workspace_model ();
+      status_bar = new QStatusBar ();
+      command_window = new terminal_dock_widget (this);
+      history_window = new history_dock_widget (this);
+      file_browser_window = new files_dock_widget (this);
+      doc_browser_window = new documentation_dock_widget (this);
+      editor_window = create_default_editor (this);
+      workspace_window = new workspace_view (this);
+    }
+
   QSettings *settings = resource_manager::get_settings ();
 
   bool connect_to_web = true;
@@ -115,7 +119,7 @@
   QDateTime current = QDateTime::currentDateTime ();
   QDateTime one_day_ago = current.addDays (-1);
 
-  if (start_gui && connect_to_web
+  if (_start_gui && connect_to_web
       && (! last_checked.isValid () || one_day_ago > last_checked))
     load_and_display_community_news (serial);
 
@@ -1479,7 +1483,7 @@
 void
 main_window::construct_octave_qt_link (void)
 {
-  _octave_qt_link = new octave_qt_link (this);
+  _octave_qt_link = new octave_qt_link (this, m_app_context);
 
   connect (_octave_qt_link, SIGNAL (exit_app_signal (int)),
            this, SLOT (exit_app (int)));
--- a/libgui/src/main-window.h	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/main-window.h	Sun Jul 10 07:15:21 2016 -0400
@@ -46,17 +46,18 @@
 
 // Own includes
 #include "dialog.h"
+#include "documentation-dock-widget.h"
+#include "files-dock-widget.h"
+#include "find-files-dialog.h"
+#include "history-dock-widget.h"
+#include "octave-cmd.h"
+#include "octave-dock-widget.h"
+#include "octave-gui.h"
+#include "octave-qt-link.h"
 #include "resource-manager.h"
+#include "terminal-dock-widget.h"
 #include "workspace-model.h"
 #include "workspace-view.h"
-#include "history-dock-widget.h"
-#include "files-dock-widget.h"
-#include "terminal-dock-widget.h"
-#include "documentation-dock-widget.h"
-#include "octave-qt-link.h"
-#include "octave-dock-widget.h"
-#include "find-files-dialog.h"
-#include "octave-cmd.h"
 
 class settings_dialog;
 
@@ -74,7 +75,7 @@
   typedef std::pair <std::string, std::string> name_pair;
   typedef std::pair <int, int> int_pair;
 
-  main_window (QWidget *parent = 0, bool start_gui = true);
+  main_window (QWidget *parent, octave::gui_application *app_context);
 
   ~main_window (void);
 
@@ -291,6 +292,8 @@
 
   void configure_shortcuts ();
 
+  octave::gui_application *m_app_context;
+
   workspace_model *_workspace_model;
 
   QHash<QMenu*, QStringList> _hash_menu_text;
--- a/libgui/src/octave-gui.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/octave-gui.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -29,6 +29,8 @@
 #include <QThread>
 #include <QTranslator>
 
+#include <cstdio>
+
 #include <iostream>
 
 #if defined (HAVE_SYS_IOCTL_H)
@@ -40,10 +42,12 @@
 #include "oct-syscalls.h"
 
 #include "builtin-defun-decls.h"
+#include "display.h"
 #if defined (HAVE_QT_GRAPHICS)
 #  include "__init_qt__.h"
 #endif
 #include "octave.h"
+#include "unistd-wrappers.h"
 
 #include "main-window.h"
 #include "octave-gui.h"
@@ -59,101 +63,164 @@
 {
 }
 
-// If START_GUI is false, we still set up the QApplication so that we
-// can use Qt widgets for plot windows.
-
-int
-octave_start_gui (int argc, char *argv[], bool start_gui)
+namespace octave
 {
-  octave_thread_manager::block_interrupt_signal ();
+  bool gui_application::start_gui_p (void) const
+  {
+    if (m_options.no_window_system ())
+      return false;
+
+    std::string err_msg;
+    if (! display_info::display_available (err_msg))
+      {
+        if (! (m_options.inhibit_startup_message () || err_msg.empty ()))
+          warning (err_msg.c_str ());
+
+        return false;
+      }
 
-  std::string show_gui_msgs = octave::sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
+    if (! m_options.line_editing ())
+      {
+        if (! (m_options.inhibit_startup_message ()
+               || m_options.no_gui ()))
+          warning ("--no-line-editing option given, disabling GUI");
+
+        return false;
+      }
+
+    if (m_options.force_gui ())
+      return true;
+
+    if (m_options.no_gui ())
+      return false;
 
-  // Installing our handler suppresses the messages.
-  if (show_gui_msgs.empty ())
-    qInstallMsgHandler (message_handler);
+    if (m_options.persist ())
+      return true;
+
+    // If stdin is not a tty, then assume we are reading commands from a
+    // pipe or a redirected file and the GUI should not start.  If this
+    // is not the case (for example, starting from a desktop "launcher"
+    // with no terminal) and you want to start the GUI, you may use the
+    // --force-gui option to start the GUI.
+
+    if (! octave_isatty_wrapper (fileno (stdin)))
+      return false;
+
+    // If we have code to eval or execute from a file, and we are going
+    // to exit immediately after executing it, don't start the gui.
+
+    std::string code_to_eval = m_options.code_to_eval ();
+    if (! code_to_eval.empty () || m_have_script_file)
+      return false;
+
+    return true;
+  }
+
+  int gui_application::execute (void)
+  {
+    octave_thread_manager::block_interrupt_signal ();
+
+    std::string show_gui_msgs = octave::sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
+
+    // Installing our handler suppresses the messages.
+
+    if (show_gui_msgs.empty ())
+      qInstallMsgHandler (message_handler);
 
 #if defined (HAVE_QT_GRAPHICS)
-  install___init_qt___functions ();
+    install___init_qt___functions ();
 
-  Fregister_graphics_toolkit (ovl ("qt"));
+    Fregister_graphics_toolkit (ovl ("qt"));
 #endif
 
-  QApplication application (argc, argv);
-  QTranslator gui_tr, qt_tr, qsci_tr;
+    // If START_GUI is false, we still set up the QApplication so that
+    // we can use Qt widgets for plot windows.
 
-  // Set the codec for all strings (before wizard)
+    QApplication qt_app (m_argc, m_argv);
+    QTranslator gui_tr, qt_tr, qsci_tr;
+
+    // Set the codec for all strings (before wizard or any GUI object)
 #if ! defined (Q_OS_WIN32)
-  QTextCodec::setCodecForCStrings (QTextCodec::codecForName ("UTF-8"));
+    QTextCodec::setCodecForCStrings (QTextCodec::codecForName ("UTF-8"));
 #endif
 
-  // show wizard if this is the first run
-  if (resource_manager::is_first_run () && start_gui)
-    {
-      // before wizard
-      resource_manager::config_translators (&qt_tr, &qsci_tr, &gui_tr);
-      application.installTranslator (&qt_tr);
-      application.installTranslator (&gui_tr);
-      application.installTranslator (&qsci_tr);
+    bool start_gui = start_gui_p ();
+
+    // Show welcome wizard if this is the first run.
+
+    if (resource_manager::is_first_run () && start_gui)
+      {
+        // Before wizard.
+        resource_manager::config_translators (&qt_tr, &qsci_tr, &gui_tr);
 
-      welcome_wizard welcomeWizard;
-
-      if (welcomeWizard.exec () == QDialog::Rejected)
-        exit (1);
+        qt_app.installTranslator (&qt_tr);
+        qt_app.installTranslator (&gui_tr);
+        qt_app.installTranslator (&qsci_tr);
 
-      resource_manager::reload_settings ();  // install settings file
-    }
-  else
-    {
-      resource_manager::reload_settings ();  // get settings file
+        welcome_wizard welcomeWizard;
+
+        if (welcomeWizard.exec () == QDialog::Rejected)
+          exit (1);
 
-      // after settings
-      resource_manager::config_translators (&qt_tr, &qsci_tr, &gui_tr);
-      application.installTranslator (&qt_tr);
-      application.installTranslator (&gui_tr);
-      if (start_gui)
-        application.installTranslator (&qsci_tr);
-    }
+        // Install settings file.
+        resource_manager::reload_settings ();
+      }
+    else
+      {
+        // Get settings file.
+        resource_manager::reload_settings ();
+
+        // After settings.
+        resource_manager::config_translators (&qt_tr, &qsci_tr, &gui_tr);
+
+        qt_app.installTranslator (&qt_tr);
+        qt_app.installTranslator (&gui_tr);
 
-  if (start_gui)
-    {
-      // update network-settings
-      resource_manager::update_network_settings ();
+        if (start_gui)
+          qt_app.installTranslator (&qsci_tr);
+      }
+
+    if (start_gui)
+      {
+        resource_manager::update_network_settings ();
 
-      // We provide specific terminal capabilities, so ensure that TERM is
-      // always set appropriately
+        // We provide specific terminal capabilities, so ensure that
+        // TERM is always set appropriately.
+
 #if defined (OCTAVE_USE_WINDOWS_API)
-      octave::sys::env::putenv ("TERM", "cygwin");
+        octave::sys::env::putenv ("TERM", "cygwin");
 #else
-      octave::sys::env::putenv ("TERM", "xterm");
+        octave::sys::env::putenv ("TERM", "xterm");
 #endif
 
-      // shortcut manager
-      shortcut_manager::init_data ();
-    }
+        shortcut_manager::init_data ();
+      }
 
-  // Force left-to-right alignment (see bug #46204)
-  application.setLayoutDirection (Qt::LeftToRight);
+    // Force left-to-right alignment (see bug #46204)
+    qt_app.setLayoutDirection (Qt::LeftToRight);
+
+    // Create and show main window.
 
-  // Create and show main window.
-
-  main_window w (0, start_gui);
+    main_window w (0, this);
 
-  if (start_gui)
-    {
-      w.read_settings ();
+    if (start_gui)
+      {
+        w.read_settings ();
+
+        w.init_terminal_size ();
 
-      w.init_terminal_size ();
+        // Connect signals for changes in visibility not before w
+        // is shown.
 
-      // Connect signals for changes in visibility not before w
-      // is shown.
+        w.connect_visibility_changed ();
 
-      w.connect_visibility_changed ();
+        w.focus_command_window ();
 
-      w.focus_command_window ();
-    }
-  else
-    application.setQuitOnLastWindowClosed (false);
+        gui_running (true);
+      }
+    else
+      qt_app.setQuitOnLastWindowClosed (false);
 
-  return application.exec ();
+    return qt_app.exec ();
+  }
 }
--- a/libgui/src/octave-gui.h	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/octave-gui.h	Sun Jul 10 07:15:21 2016 -0400
@@ -23,7 +23,39 @@
 #if ! defined (octave_octave_gui_h)
 #define octave_octave_gui_h 1
 
-extern OCTGUI_API int octave_start_gui (int argc, char **argv,
-                                        bool start_gui = true);
+#include "octave.h"
+
+namespace octave
+{
+  class OCTGUI_API gui_application : public application
+  {
+  public:
+
+    gui_application (int argc, char **argv)
+      : application (argc, argv), m_argc (argc), m_argv (argv),
+        m_gui_running (false)
+    { }
+
+    // Should we start the GUI or fall back to the CLI?
+    bool start_gui_p (void) const;
+
+    int execute (void);
+
+    bool gui_running (void) const { return m_gui_running; }
+    void gui_running (bool arg) { m_gui_running = arg; }
+
+  private:
+
+    // No copying, at least not yet.
+
+    gui_application (const gui_application&);
+
+    gui_application& operator = (const gui_application&);
+
+    int m_argc;
+    char **m_argv;
+    bool m_gui_running;
+  };
+}
 
 #endif
--- a/libgui/src/octave-interpreter.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/octave-interpreter.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -29,6 +29,11 @@
 
 #include "octave-interpreter.h"
 
+octave_interpreter::octave_interpreter (octave::application *app_context)
+  : QObject (), thread_manager (), m_app_context (app_context),
+    m_exit_status (0)
+{ }
+
 void
 octave_interpreter::execute (void)
 {
@@ -36,12 +41,13 @@
 
   octave_thread_manager::unblock_interrupt_signal ();
 
-  octave_initialize_interpreter (octave_cmdline_argc, octave_cmdline_argv,
-                                 octave_embedded);
+  // The application context owns the interpreter.
+
+  m_app_context->create_interpreter ();
 
   emit octave_ready_signal ();
 
-  octave_execute_interpreter ();
+  m_exit_status = m_app_context->execute_interpreter ();
 }
 
 void
--- a/libgui/src/octave-interpreter.h	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/octave-interpreter.h	Sun Jul 10 07:15:21 2016 -0400
@@ -26,6 +26,8 @@
 
 #include <QObject>
 
+#include "octave.h"
+
 #include "thread-manager.h"
 
 class octave_interpreter : public QObject
@@ -36,7 +38,9 @@
 
   // An object to manage the Octave interpreter.
 
-  octave_interpreter (void) : QObject (), thread_manager () { }
+  octave_interpreter (octave::application *app_context);
+
+  ~octave_interpreter (void) { }
 
 signals:
 
@@ -53,6 +57,10 @@
 private:
 
   octave_thread_manager thread_manager;
+
+  octave::application *m_app_context;
+
+  int m_exit_status;
 };
 
 #endif
--- a/libgui/src/octave-qt-link.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/octave-qt-link.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -31,22 +31,25 @@
 #include <QDir>
 #include <QPushButton>
 
+#include "oct-env.h"
 #include "str-vec.h"
+
+#include "builtin-defun-decls.h"
 #include "dialog.h"
 #include "error.h"
-#include "workspace-element.h"
-#include "builtin-defun-decls.h"
 #include "load-path.h"
-#include "oct-env.h"
 #include "utils.h"
 
+#include "octave-gui.h"
 #include "octave-qt-link.h"
-
 #include "resource-manager.h"
+#include "workspace-element.h"
 
-octave_qt_link::octave_qt_link (QWidget *p)
+octave_qt_link::octave_qt_link (QWidget *p,
+                                octave::gui_application *app_context)
   : octave_link (), main_thread (new QThread ()),
-    command_interpreter (new octave_interpreter ())
+    m_app_context (app_context),
+    command_interpreter (new octave_interpreter (app_context))
 {
   _current_directory = "";
   _new_dir = true;
@@ -562,9 +565,12 @@
 octave_qt_link::do_set_default_prompts (std::string& ps1, std::string& ps2,
                                         std::string& ps4)
 {
-  ps1 = ">> ";
-  ps2 = "";
-  ps4 = "";
+  if (m_app_context->start_gui_p ())
+    {
+      ps1 = ">> ";
+      ps2 = "";
+      ps4 = "";
+    }
 }
 
 void
--- a/libgui/src/octave-qt-link.h	Mon Jul 11 13:45:12 2016 -0400
+++ b/libgui/src/octave-qt-link.h	Sun Jul 10 07:15:21 2016 -0400
@@ -35,6 +35,7 @@
 #include <QMutex>
 #include <QWaitCondition>
 
+#include "octave-gui.h"
 #include "octave-link.h"
 #include "octave-interpreter.h"
 
@@ -55,7 +56,7 @@
 
 public:
 
-  octave_qt_link (QWidget *p);
+  octave_qt_link (QWidget *p, octave::gui_application *app_context);
 
   ~octave_qt_link (void);
 
@@ -156,6 +157,8 @@
   // Thread running octave_main.
   QThread *main_thread;
 
+  octave::gui_application *m_app_context;
+
   octave_interpreter *command_interpreter;
 
   QString _current_directory;
--- a/libinterp/corefcn/dirfns.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/dirfns.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -48,6 +48,7 @@
 #include "errwarn.h"
 #include "input.h"
 #include "load-path.h"
+#include "octave.h"
 #include "octave-link.h"
 #include "ovl.h"
 #include "pager.h"
@@ -280,7 +281,9 @@
 
       bool doit = true;
 
-      if (interactive && ! forced_interactive && Vconfirm_recursive_rmdir)
+      if (octave::application::interactive ()
+          && ! octave::application::forced_interactive ()
+          && Vconfirm_recursive_rmdir)
         {
           std::string prompt = "remove entire contents of " + fulldir + "? ";
 
--- a/libinterp/corefcn/error.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/error.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -36,6 +36,7 @@
 #include "defun.h"
 #include "error.h"
 #include "input.h"
+#include "octave.h"
 #include "pager.h"
 #include "ovl.h"
 #include "oct-map.h"
@@ -313,7 +314,8 @@
 maybe_enter_debugger (octave_execution_exception& e,
                       bool show_stack_trace = false)
 {
-  if ((interactive || forced_interactive)
+  if ((octave::application::interactive ()
+       || octave::application::forced_interactive ())
       && ((Vdebug_on_error && bp_table::debug_on_err (last_error_id ()))
           || (Vdebug_on_caught && bp_table::debug_on_caught (last_error_id ())))
       && octave_call_stack::caller_user_code ())
@@ -720,7 +722,8 @@
           && ! discard_warning_messages)
         pr_where (std::cerr, "warning");
 
-      if ((interactive || forced_interactive)
+      if ((octave::application::interactive ()
+           || octave::application::forced_interactive ())
           && Vdebug_on_warning && in_user_code && bp_table::debug_on_warn (id))
         {
           octave::unwind_protect frame;
--- a/libinterp/corefcn/input.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/input.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -50,6 +50,7 @@
 #include "input.h"
 #include "lex.h"
 #include "load-path.h"
+#include "octave.h"
 #include "octave-link.h"
 #include "oct-map.h"
 #include "oct-hist.h"
@@ -95,13 +96,6 @@
 // Character to append after successful command-line completion attempts.
 static char Vcompletion_append_char = ' ';
 
-// TRUE means this is an interactive shell (either forced or not)
-bool interactive = false;
-
-// TRUE means the user forced this shell to be interactive (-i).
-// FALSE means the shell would be interactive, independent of user settings.
-bool forced_interactive = false;
-
 // TRUE after a call to completion_matches.
 bool octave_completion_matches_called = false;
 
@@ -147,9 +141,11 @@
 void
 octave_base_reader::do_input_echo (const std::string& input_string) const
 {
+  bool forced_interactive = octave::application::forced_interactive ();
+
   int do_echo = reading_script_file ()
     ? (Vecho_executing_commands & ECHO_SCRIPTS)
-    : (Vecho_executing_commands & ECHO_CMD_LINE) && ! forced_interactive;
+    : ((Vecho_executing_commands & ECHO_CMD_LINE) && ! forced_interactive);
 
   if (do_echo)
     {
@@ -193,7 +189,7 @@
 {
   Vlast_prompt_time.stamp ();
 
-  if (Vdrawnow_requested && interactive)
+  if (Vdrawnow_requested && octave::application::interactive ())
     {
       bool eval_error = false;
 
@@ -210,7 +206,7 @@
           if (! stack_trace.empty ())
             std::cerr << stack_trace;
 
-          if (interactive)
+          if (octave::application::interactive ())
             recover_from_exception ();
         }
 
@@ -240,7 +236,7 @@
   // Process pre input event hook function prior to flushing output and
   // printing the prompt.
 
-  if (interactive)
+  if (octave::application::interactive ())
     {
       if (! Vdebugging)
         octave_link::exit_debugger_event ();
@@ -306,7 +302,7 @@
   // Process post input event hook function after the internal history
   // list has been updated.
 
-  if (interactive)
+  if (octave::application::interactive ())
     octave_link::post_input_event ();
 
   return retval;
@@ -601,12 +597,20 @@
   frame.protect_var (VPS1);
   VPS1 = prompt;
 
-  if (! interactive)
+  octave::application *app = octave::application::app ();
+
+  if (! app->interactive ())
     {
-      frame.protect_var (interactive);
-      interactive = true;
-      frame.protect_var (forced_interactive);
-      forced_interactive = true;
+
+      frame.add_method (app, &octave::application::interactive,
+                        app->interactive ());
+
+      frame.add_method (app, &octave::application::forced_interactive,
+                        app->forced_interactive ());
+
+      app->interactive (true);
+
+      app->forced_interactive (true);
     }
 
   octave_parser curr_parser;
--- a/libinterp/corefcn/input.h	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/input.h	Sun Jul 10 07:15:21 2016 -0400
@@ -40,13 +40,6 @@
 
 extern OCTINTERP_API FILE *get_input_from_stdin (void);
 
-// TRUE means this is an interactive shell (forced or not)
-extern bool interactive;
-
-// TRUE means the user forced this shell to be interactive (-i).
-// FALSE means the shell would be interactive, independent of user settings.
-extern bool forced_interactive;
-
 // TRUE after a call to completion_matches.
 extern bool octave_completion_matches_called;
 
--- a/libinterp/corefcn/oct-stream.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/oct-stream.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -50,6 +50,7 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "octave.h"
 #include "oct-stdstrm.h"
 #include "oct-stream.h"
 #include "ov.h"
@@ -3989,7 +3990,7 @@
 octave_base_stream::do_gets (octave_idx_type max_len, bool& err,
                              bool strip_newline, const std::string& who)
 {
-  if (interactive && file_number () == 0)
+  if (octave::application::interactive () && file_number () == 0)
     ::error ("%s: unable to read from stdin while running interactively",
              who.c_str ());
 
@@ -4100,7 +4101,7 @@
 off_t
 octave_base_stream::skipl (off_t num, bool& err, const std::string& who)
 {
-  if (interactive && file_number () == 0)
+  if (octave::application::interactive () && file_number () == 0)
     ::error ("%s: unable to read from stdin while running interactively",
              who.c_str ());
 
@@ -4568,7 +4569,7 @@
                               octave_idx_type& conversion_count,
                               const std::string& who)
 {
-  if (interactive && file_number () == 0)
+  if (octave::application::interactive () && file_number () == 0)
     ::error ("%s: unable to read from stdin while running interactively",
              who.c_str ());
 
@@ -4896,7 +4897,9 @@
                     is.clear (is.rdstate () & (~std::ios::failbit));
 
                   // FIXME: is this the right thing to do?
-                  if (interactive && ! forced_interactive && name () == "stdin")
+                  if (octave::application::interactive ()
+                      && ! octave::application::forced_interactive ()
+                      && name () == "stdin")
                     {
                       is.clear ();
 
@@ -5126,7 +5129,9 @@
 
       // FIXME: is this the right thing to do?
 
-      if (interactive && ! forced_interactive && name () == "stdin")
+      if (octave::application::interactive ()
+          && ! octave::application::forced_interactive ()
+          && name () == "stdin")
         {
           // Skip to end of line.
           bool err;
@@ -5218,7 +5223,7 @@
                                  const std::string& who,
                                  octave_idx_type& read_count)
 {
-  if (interactive && file_number () == 0)
+  if (octave::application::interactive () && file_number () == 0)
     ::error ("%s: unable to read from stdin while running interactively",
              who.c_str ());
 
--- a/libinterp/corefcn/pager.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/pager.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -38,6 +38,7 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "octave.h"
 #include "ovl.h"
 #include "pager.h"
 #include "procstream.h"
@@ -232,7 +233,8 @@
 int
 octave_pager_buf::sync (void)
 {
-  if (! interactive || forced_interactive
+  if (! octave::application::interactive ()
+      || octave::application::forced_interactive ()
       || really_flush_to_pager
       || (Vpage_screen_output && Vpage_output_immediately)
       || ! Vpage_screen_output)
@@ -241,7 +243,8 @@
 
       int len = pptr () - buf;
 
-      bool bypass_pager = (! interactive || forced_interactive
+      bool bypass_pager = (! octave::application::interactive ()
+                           || octave::application::forced_interactive ()
                            || ! Vpage_screen_output
                            || (really_flush_to_pager
                                && Vpage_screen_output
--- a/libinterp/corefcn/sighandlers.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/sighandlers.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -46,6 +46,7 @@
 #include "error.h"
 #include "input.h"
 #include "load-save.h"
+#include "octave.h"
 #include "oct-map.h"
 #include "pager.h"
 #include "pt-bp.h"
@@ -523,7 +524,8 @@
             octave_signal_caught = 1;
             octave_interrupt_state++;
 
-            if (interactive && ! forced_interactive
+            if (octave::application::interactive ()
+                && ! octave::application::forced_interactive ()
                 && octave_interrupt_state == 2)
               std::cerr << "Press Control-C again to abort." << std::endl;
 
--- a/libinterp/corefcn/sysdep.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/sysdep.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -78,8 +78,9 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "octave.h"
+#include "ov.h"
 #include "ovl.h"
-#include "ov.h"
 #include "pager.h"
 #include "parse.h"
 #include "sighandlers.h"
@@ -341,7 +342,8 @@
   int tty_fd = STDIN_FILENO;
   if (! octave_isatty_wrapper (tty_fd))
     {
-      if (interactive && ! forced_interactive)
+      if (octave::application::interactive ()
+          && ! octave::application::forced_interactive ())
         error ("stdin is not a tty!");
     }
 
@@ -722,7 +724,7 @@
 
   // FIXME: add timeout and default value args?
 
-  if (interactive)
+  if (octave::application::interactive ())
     {
       Fdrawnow ();
 
--- a/libinterp/corefcn/toplev.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/corefcn/toplev.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -65,6 +65,7 @@
 #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"
@@ -685,7 +686,7 @@
 
   // The big loop.
 
-  octave_lexer *lxr = (interactive
+  octave_lexer *lxr = (octave::application::interactive ()
                        ? new octave_lexer ()
                        : new octave_lexer (stdin));
 
@@ -713,7 +714,7 @@
 
                   octave_quit ();
 
-                  if (! interactive)
+                  if (! octave::application::interactive ())
                     {
                       bool quit = (tree_return_command::returning
                                    || tree_break_command::breaking);
@@ -745,7 +746,7 @@
             return exit_status;
 
           // Required newline when the user does Ctrl+C at the prompt.
-          if (interactive)
+          if (octave::application::interactive ())
             octave_stdout << "\n";
         }
       catch (const index_exception& e)
@@ -763,7 +764,7 @@
           if (! stack_trace.empty ())
             std::cerr << stack_trace;
 
-          if (interactive)
+          if (octave::application::interactive ())
             recover_from_exception ();
           else
             {
@@ -790,7 +791,7 @@
     }
   while (retval == 0);
 
-  if (interactive)
+  if (octave::application::interactive ())
     octave_stdout << "\n";
 
   if (retval == EOF)
@@ -863,7 +864,7 @@
 
       OCTAVE_SAFE_CALL (flush_octave_stdout, ());
 
-      if (! quitting_gracefully && interactive)
+      if (! quitting_gracefully && octave::application::interactive ())
         {
           octave_stdout << "\n";
 
--- a/libinterp/octave.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/octave.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -87,118 +87,9 @@
 
 extern void install_builtins (void);
 
-int octave_cmdline_argc;
-char **octave_cmdline_argv;
-int octave_embedded;
-
-// The command-line options.
-static string_vector octave_argv;
-
-// The name used to invoke Octave.
-static std::string octave_program_invocation_name;
-
-// The last component of octave_program_invocation_name.
-static std::string octave_program_name;
-
-// TRUE means we are using readline.
-// (--no-line-editing)
-static bool line_editing = true;
-
-// TRUE means we read ~/.octaverc and ./.octaverc.
-// (--norc; --no-init-file; -f)
-static bool read_init_files = true;
-
-// TRUE means we read the site-wide octaverc files.
-// (--norc; --no-site-file; -f)
-static bool read_site_files = true;
-
-// TRUE means we set the initial path to configured defaults.
-// (--no-init-path)
-static bool set_initial_path = true;
-
-// TRUE means we don't print the usual startup message.
-// (--quiet; --silent; -q)
-static bool inhibit_startup_message = false;
-
-// If TRUE, print verbose info in some cases.
-// (--verbose; -V)
-static bool verbose_flag = false;
-
-// If TRUE, force the GUI to start.
-// (--force-gui)
-static bool force_gui_option = false;
-
-// If TRUE don't start the GUI.
-// (--no-gui)
-static bool no_gui_option = false;
-
-// If TRUE, force readline command line editing.
-// (--line-editing)
-static bool forced_line_editing = false;
-
-// If TRUE, initialize history list from saved history file.
-// (--no-history; -H)
-static bool read_history_file = true;
-
-// The value of "path" specified on the command line.
-// (--path; -p)
-static std::list<std::string> command_line_path;
-
-// The value for "EXEC_PATH" specified on the command line.
-// (--exec-path)
-static std::string exec_path;
-
-// The value for "IMAGE_PATH" specified on the command line.
-// (--image-path)
-static std::string image_path;
-
-// If TRUE, ignore the window system even if it is available.
-// (--no-window-system, -W)
-static bool no_window_system = false;
-
-// The code to evaluate at startup
-// (--eval CODE)
-static std::string code_to_eval;
-
-// If TRUE, don't exit after evaluating code given by --eval option.
-// (--persist)
-static bool persist = false;
-
-// If TRUE, the GUI should be started.
-static bool start_gui = false;
-
-// If TRUE use traditional (maximally MATLAB compatible) settings
-// (--traditional)
-static bool traditional = false;
-
-// TRUE if this is a program and no interpreter and interaction is
-// needed.  For example, an octave program with shebang line, or code
-// from eval without persist.
-static bool an_octave_program = false;
-
 // Store the command-line options for later use.
 
 static void
-intern_argv (int argc, char **argv)
-{
-  assert (symbol_table::at_top_level ());
-
-  symbol_table::assign (".nargin.", argc - 1);
-
-  symbol_table::mark_hidden (".nargin.");
-
-  if (argc > 0)
-    {
-      octave_argv.resize (argc - 1);
-
-      // Skip program name in argv.
-      int i = argc;
-      while (--i > 0)
-        octave_argv[i-1] = *(argv+i);
-    }
-}
-
-static void
 execute_pkg_add (const std::string& dir)
 {
   std::string file_name = octave::sys::file_ops::concat (dir, "PKG_ADD");
@@ -230,7 +121,7 @@
 }
 
 static void
-initialize_load_path (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
@@ -346,7 +237,8 @@
 // Initialize by reading startup files.
 
 static void
-execute_startup_files (void)
+execute_startup_files (bool read_site_files, bool read_init_files,
+                       bool verbose_flag, bool inhibit_startup_message)
 {
   octave::unwind_protect frame;
 
@@ -417,89 +309,6 @@
     }
 }
 
-static int
-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.protect_var (interactive);
-
-  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;
-}
-
-static void
-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.protect_var (interactive);
-
-  frame.protect_var (octave_program_invocation_name);
-  frame.protect_var (octave_program_name);
-
-  interactive = false;
-
-  octave_program_invocation_name = fname;
-
-  size_t pos = fname.find_last_of (octave::sys::file_ops::dir_sep_chars ());
-
-  octave_program_name
-    = (pos != std::string::npos) ? fname.substr (pos+1) : fname;
-
-  std::string context;
-  bool verbose = false;
-  bool require_file = true;
-
-  safe_source_file (fname, context, verbose, require_file, "octave");
-}
-
 OCTAVE_NORETURN static void
 lo_error_handler (const char *fmt, ...)
 {
@@ -536,8 +345,6 @@
 static void
 maximum_braindamage (void)
 {
-  persist = true;
-
   FPS1 (octave_value (">> "));
   FPS2 (octave_value (""));
   FPS4 (octave_value (""));
@@ -560,509 +367,726 @@
   disable_warning ("Octave:possible-matlab-short-circuit-operator");
 }
 
-// EMBEDDED is declared int instead of bool because this function is
-// declared extern "C".
+namespace octave
+{
+  cmdline_options::cmdline_options (void)
+  {
+    m_all_args.resize (1);
+    m_all_args[0] = "";
+  }
+
+  cmdline_options::cmdline_options (int argc, char **argv)
+  {
+    // Save raw program arguments.
+    m_all_args = string_vector (argv, argc);
+
+    while (true)
+      {
+        int long_idx;
+
+        int optc = octave_getopt_long_wrapper (argc, argv, short_opts,
+                                               long_opts, &long_idx);
+
+        if (optc < 0)
+          break;
+
+        switch (optc)
+          {
+          case '?':
+            // Unrecognized option.  getopt_long already printed a message about
+            // it, so we will just print the usage string and exit.
+            octave_print_terse_usage_and_exit ();
+            break;
+
+          case 'H':
+            Fhistory_save (octave_value (false));
+            m_read_history_file = false;
+            break;
+
+          case 'W':
+            m_no_window_system = true;
+            break;
+
+          case 'V':
+            m_verbose_flag = true;
+            break;
+
+          case 'd':
+            // This is the same as yydebug in parse.y.
+            octave_debug++;
+            break;
+
+          case 'f':
+            m_read_init_files = false;
+            m_read_site_files = false;
+            break;
+
+          case 'h':
+            octave_print_verbose_usage_and_exit ();
+            break;
+
+          case 'i':
+            m_forced_interactive = true;
+            break;
+
+          case 'p':
+            if (optarg)
+              m_command_line_path.push_back (optarg);
+            break;
+
+          case 'q':
+            m_inhibit_startup_message = true;
+            break;
+
+          case 'x':
+            {
+              int val = ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_CMD_LINE;
+              Fecho_executing_commands (octave_value (val));
+            }
+            break;
+
+          case 'v':
+            octave_print_version_and_exit ();
+            break;
+
+          case BUILT_IN_DOCSTRINGS_FILE_OPTION:
+            if (optarg)
+              Fbuilt_in_docstrings_file (octave_value (optarg));
+            break;
+
+          case DOC_CACHE_FILE_OPTION:
+            if (optarg)
+              Fdoc_cache_file (octave_value (optarg));
+            break;
+
+          case EVAL_OPTION:
+            if (optarg)
+              {
+                if (m_code_to_eval.empty ())
+                  m_code_to_eval = optarg;
+                else
+                  m_code_to_eval += std::string (" ") + optarg;
+              }
+            break;
+
+          case EXEC_PATH_OPTION:
+            if (optarg)
+              m_exec_path = optarg;
+            break;
+
+          case FORCE_GUI_OPTION:
+            m_force_gui = true;
+            break;
+
+          case IMAGE_PATH_OPTION:
+            if (optarg)
+              m_image_path = optarg;
+            break;
+
+          case INFO_FILE_OPTION:
+            if (optarg)
+              Finfo_file (octave_value (optarg));
+            break;
+
+          case INFO_PROG_OPTION:
+            if (optarg)
+              Finfo_program (octave_value (optarg));
+            break;
+
+          case DEBUG_JIT_OPTION:
+            Fdebug_jit (octave_value (true));
+            break;
+
+          case JIT_COMPILER_OPTION:
+            Fjit_enable (octave_value (true));
+            break;
+
+          case LINE_EDITING_OPTION:
+            m_forced_line_editing = m_line_editing = true;
+            break;
+
+          case NO_GUI_OPTION:
+            m_no_gui = true;
+            break;
+
+          case NO_INIT_FILE_OPTION:
+            m_read_init_files = false;
+            break;
+
+          case NO_INIT_PATH_OPTION:
+            m_set_initial_path = false;
+            break;
+
+          case NO_LINE_EDITING_OPTION:
+            m_line_editing = false;
+            break;
+
+          case NO_SITE_FILE_OPTION:
+            m_read_site_files = 0;
+            break;
+
+          case PERSIST_OPTION:
+            m_persist = true;
+            break;
+
+          case TEXI_MACROS_FILE_OPTION:
+            if (optarg)
+              Ftexi_macros_file (octave_value (optarg));
+            break;
+
+          case TRADITIONAL_OPTION:
+            m_traditional = true;
+            m_persist = true;
+            break;
+
+          default:
+            // getopt_long should print a message about unrecognized options and
+            // return '?', which is handled above.  If we end up here, it is
+            // because there was an option but we forgot to handle it.
+            // That should be fatal.
+            panic_impossible ();
+            break;
+          }
+      }
+
+    // Check for various incompatible argument pairs
+    if (m_force_gui && m_no_gui)
+      {
+        warning ("only one of --force-gui and --no-gui may be used");
+
+        octave_print_terse_usage_and_exit ();
+      }
+
+    m_remaining_args = string_vector (argv+optind, argc-optind);
+  }
+
+  cmdline_options::cmdline_options (const cmdline_options& opts)
+    : m_force_gui (opts.m_force_gui),
+      m_forced_interactive (opts.m_forced_interactive),
+      m_forced_line_editing (opts.m_forced_line_editing),
+      m_inhibit_startup_message (opts.m_inhibit_startup_message),
+      m_line_editing (opts.m_line_editing),
+      m_no_gui (opts.m_no_gui),
+      m_no_window_system (opts.m_no_window_system),
+      m_persist (opts.m_persist),
+      m_read_history_file (opts.m_read_history_file),
+      m_read_init_files (opts.m_read_init_files),
+      m_read_site_files (opts.m_read_site_files),
+      m_set_initial_path (opts.m_set_initial_path),
+      m_traditional (opts.m_traditional),
+      m_verbose_flag (opts.m_verbose_flag),
+      m_code_to_eval (opts.m_code_to_eval),
+      m_command_line_path (opts.m_command_line_path),
+      m_exec_path (opts.m_exec_path),
+      m_image_path (opts.m_image_path),
+      m_all_args (opts.m_all_args),
+      m_remaining_args (opts.m_remaining_args)
+  { }
+
+  cmdline_options&
+  cmdline_options::operator = (const cmdline_options& opts)
+  {
+    if (this != &opts)
+      {
+        m_force_gui = opts.m_force_gui;
+        m_forced_interactive = opts.m_forced_interactive;
+        m_forced_line_editing = opts.m_forced_line_editing;
+        m_inhibit_startup_message = opts.m_inhibit_startup_message;
+        m_line_editing = opts.m_line_editing;
+        m_no_gui = opts.m_no_gui;
+        m_no_window_system = opts.m_no_window_system;
+        m_persist = opts.m_persist;
+        m_read_history_file = opts.m_read_history_file;
+        m_read_init_files = opts.m_read_init_files;
+        m_read_site_files = opts.m_read_site_files;
+        m_set_initial_path = opts.m_set_initial_path;
+        m_traditional = opts.m_traditional;
+        m_verbose_flag = opts.m_verbose_flag;
+        m_code_to_eval = opts.m_code_to_eval;
+        m_command_line_path = opts.m_command_line_path;
+        m_exec_path = opts.m_exec_path;
+        m_image_path = opts.m_image_path;
+        m_all_args = opts.m_all_args;
+        m_remaining_args = opts.m_remaining_args;
+      }
+
+    return *this;
+  }
+
+  application *application::instance = 0;
+
+  application::application (int argc, char **argv)
+    : m_options (argc, argv)
+  {
+    init ();
+  }
+
+  application::application (const cmdline_options& opts)
+    : m_options (opts)
+  {
+    init ();
+  }
+
+  void
+  application::set_program_names (const std::string& pname)
+  {
+    m_program_invocation_name = pname;
+
+    size_t pos = pname.find_last_of (octave::sys::file_ops::dir_sep_chars ());
+
+    m_program_name = (pos != std::string::npos) ? pname.substr (pos+1) : pname;
+  }
+
+  void
+  application::intern_argv (const string_vector& args)
+  {
+    assert (symbol_table::at_top_level ());
+
+    octave_idx_type nargs = args.numel ();
+
+    if (nargs > 0)
+      {
+        // Skip first argument (program name).
+        nargs--;
+
+        m_argv.resize (nargs);
+
+        for (octave_idx_type i = 0; i < nargs; i++)
+          m_argv[i] = args[i+1];
+      }
+
+    symbol_table::assign (".nargin.", nargs);
+    symbol_table::mark_hidden (".nargin.");
+  }
+
+  void application::interactive (bool arg)
+  {
+    m_interpreter->interactive (arg);
+  }
+
+  bool application::forced_interactive (void)
+  {
+    return instance->m_options.forced_interactive ();
+  }
+
+  bool application::interactive (void)
+  {
+    return instance->m_interpreter->interactive ();
+  }
+
+  application::~application (void)
+  {
+    instance = 0;
+
+    delete m_interpreter;
+  }
+
+  void application::create_interpreter (void)
+  {
+    if (! m_interpreter)
+      m_interpreter = new interpreter (this);
+  }
+
+  int application::execute_interpreter (void)
+  {
+    return m_interpreter ? m_interpreter->execute () : -1;
+  }
+
+  void application::init (void)
+  {
+    if (instance)
+      {
+        // FIXME: Should this be an error?
+      }
+    else
+      instance = this;
+
+    string_vector all_args = m_options.all_args ();
+
+    set_program_names (all_args[0]);
+
+    string_vector remaining_args = m_options.remaining_args ();
+
+    std::string code_to_eval = m_options.code_to_eval ();
+
+    m_have_script_file = ! remaining_args.empty ();
+
+    if (! code_to_eval.empty () && m_have_script_file)
+      {
+        warning ("--eval \"CODE\" and script file are mutually exclusive options");
+
+        octave_print_terse_usage_and_exit ();
+      }
+
+    m_is_octave_program = ((m_have_script_file || ! code_to_eval.empty ())
+                           && ! m_options.persist ()
+                           && ! m_options.traditional ());
+  }
+
+  int cli_application::execute (void)
+  {
+    create_interpreter ();
+
+    return execute_interpreter ();
+  }
+
+  void embedded_application::create_interpreter (void)
+  {
+    if (! m_interpreter)
+      m_interpreter = new interpreter (this, true);
+  }
+
+  int embedded_application::execute (void)
+  {
+    create_interpreter ();
+
+    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".
 
 int
 octave_main (int argc, char **argv, int embedded)
 {
-  octave_process_command_line (argc, argv);
-
-  sysdep_init ();
-
-  install_defaults ();
-
-  octave_initialize_interpreter (argc, argv, embedded);
-
-  return octave_execute_interpreter ();
-}
-
-void
-octave_process_command_line (int argc, char **argv)
-{
-  octave_cmdline_argc = argc;
-  octave_cmdline_argv = argv;
-
-  while (true)
-    {
-      int long_idx;
-
-      int optc = octave_getopt_long_wrapper (argc, argv, short_opts,
-                                             long_opts, &long_idx);
-
-      if (optc < 0)
-        break;
-
-      switch (optc)
-        {
-        case '?':
-          // Unrecognized option.  getopt_long already printed a message about
-          // it, so we will just print the usage string and exit.
-          octave_print_terse_usage_and_exit ();
-          break;
-
-        case 'H':
-          Fhistory_save (octave_value (false));
-          read_history_file = false;
-          break;
-
-        case 'W':
-          no_window_system = true;
-          break;
-
-        case 'V':
-          verbose_flag = true;
-          break;
-
-        case 'd':
-          // This is the same as yydebug in parse.y.
-          octave_debug++;
-          break;
-
-        case 'f':
-          read_init_files = false;
-          read_site_files = false;
-          break;
-
-        case 'h':
-          octave_print_verbose_usage_and_exit ();
-          break;
-
-        case 'i':
-          forced_interactive = true;
-          break;
-
-        case 'p':
-          if (optarg)
-            command_line_path.push_back (optarg);
-          break;
-
-        case 'q':
-          inhibit_startup_message = true;
-          break;
-
-        case 'x':
-          {
-            int val = ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_CMD_LINE;
-            Fecho_executing_commands (octave_value (val));
-          }
-          break;
-
-        case 'v':
-          octave_print_version_and_exit ();
-          break;
-
-        case BUILT_IN_DOCSTRINGS_FILE_OPTION:
-          if (optarg)
-            Fbuilt_in_docstrings_file (octave_value (optarg));
-          break;
-
-        case DOC_CACHE_FILE_OPTION:
-          if (optarg)
-            Fdoc_cache_file (octave_value (optarg));
-          break;
-
-        case EVAL_OPTION:
-          if (optarg)
-            {
-              if (code_to_eval.empty ())
-                code_to_eval = optarg;
-              else
-                code_to_eval += std::string (" ") + optarg;
-            }
-          break;
-
-        case EXEC_PATH_OPTION:
-          if (optarg)
-            exec_path = optarg;
-          break;
-
-        case FORCE_GUI_OPTION:
-          force_gui_option = true;
-          break;
-
-        case IMAGE_PATH_OPTION:
-          if (optarg)
-            image_path = optarg;
-          break;
-
-        case INFO_FILE_OPTION:
-          if (optarg)
-            Finfo_file (octave_value (optarg));
-          break;
-
-        case INFO_PROG_OPTION:
-          if (optarg)
-            Finfo_program (octave_value (optarg));
-          break;
-
-        case DEBUG_JIT_OPTION:
-          Fdebug_jit (octave_value (true));
-          break;
-
-        case JIT_COMPILER_OPTION:
-          Fjit_enable (octave_value (true));
-          break;
-
-        case LINE_EDITING_OPTION:
-          forced_line_editing = line_editing = true;
-          break;
-
-        case NO_GUI_OPTION:
-          no_gui_option = true;
-          break;
-
-        case NO_INIT_FILE_OPTION:
-          read_init_files = false;
-          break;
-
-        case NO_INIT_PATH_OPTION:
-          set_initial_path = false;
-          break;
-
-        case NO_LINE_EDITING_OPTION:
-          line_editing = false;
-          break;
-
-        case NO_SITE_FILE_OPTION:
-          read_site_files = 0;
-          break;
-
-        case PERSIST_OPTION:
-          persist = true;
-          break;
-
-        case TEXI_MACROS_FILE_OPTION:
-          if (optarg)
-            Ftexi_macros_file (octave_value (optarg));
-          break;
-
-        case TRADITIONAL_OPTION:
-          traditional = true;
-          break;
-
-        default:
-          // getopt_long should print a message about unrecognized options and
-          // return '?', which is handled above.  If we end up here, it is
-          // because there was an option but we forgot to handle it.
-          // That should be fatal.
-          panic_impossible ();
-          break;
-        }
-    }
-
-  // Check for various incompatible argument pairs
-  if (force_gui_option && no_gui_option)
-    {
-      warning ("only one of --force-gui and --no-gui may be used");
-
-      octave_print_terse_usage_and_exit ();
-    }
-
-  bool script_file = (argc - optind) > 0;
-  if (! code_to_eval.empty () && script_file)
-    {
-      warning ("--eval \"CODE\" and script file are mutually exclusive options");
-
-      octave_print_terse_usage_and_exit ();
-    }
-  an_octave_program = ((script_file || ! code_to_eval.empty ())
-                       && ! persist && ! traditional);
-
-}
-
-// EMBEDDED is declared int instead of bool because this function is
-// declared extern "C".
-
-void
-octave_initialize_interpreter (int argc, char **argv, int embedded)
-{
-  // 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 ();
-
-  octave_embedded = embedded;
-
   octave::sys::env::set_program_name (argv[0]);
 
-  octave_program_invocation_name = octave::sys::env::get_program_invocation_name ();
-  octave_program_name = octave::sys::env::get_program_name ();
-
-  octave_thread::init ();
-
-  set_default_prompts ();
-
-  // Initialize default warning state before --traditional option
-  // that may reset them.
-
-  initialize_default_warning_state ();
-
-  if (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 (! embedded)
-    octave::install_signal_handlers ();
-  else
-    quit_allowed = false;
-
-  initialize_file_io ();
-
-  install_types ();
-
-  install_ops ();
-
-  install_builtins ();
-
-  install_classdef ();
-
-  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);
-
-  if (! exec_path.empty ())
-    set_exec_path (exec_path);
-
-  if (! image_path.empty ())
-    set_image_path (image_path);
-
-  if (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));
-
-  interactive = (! embedded && ! an_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 (forced_interactive)
-    {
-      if (interactive)
-        forced_interactive = false;
-      else
-        interactive = true;
-    }
-
-  if ((! interactive || forced_interactive) && ! forced_line_editing)
-    line_editing = false;
-
-  // Also skip start-up message unless session is interactive.
-  if (! interactive)
-    inhibit_startup_message = true;
-
-  // Force default line editor if we don't want readline editing.
-  if (! 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 (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.
-
-  intern_argv (argc, argv);
-
-  initialize_load_path ();
-
-  initialize_history (read_history_file);
-}
-
-int
-octave_execute_interpreter (void)
-{
-  if (! inhibit_startup_message)
-    std::cout << octave_startup_message () << "\n" << std::endl;
-
-  octave_prepare_hdf5 ();
-
-  execute_startup_files ();
-
-  if (! inhibit_startup_message && reading_startup_message_printed)
-    std::cout << std::endl;
-
-  // Execute any code specified with --eval 'CODE'
-  if (! code_to_eval.empty ())
+  if (embedded)
     {
-      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 (! persist)
-        {
-          quitting_gracefully = true;
-
-          clean_up_and_exit (parse_status);
-        }
+      octave::embedded_application app (argc, argv);
+      return app.execute ();
     }
-
-  // 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.
-
-  int last_arg_idx = optind;
-  int remaining_args = octave_cmdline_argc - last_arg_idx;
-
-  if (remaining_args > 0)
-    {
-      // If we are running an executable script (#! /bin/octave) then
-      // we should only see the args passed to the script.
-
-      exit_status = 0;
-
-      try
-        {
-          intern_argv (remaining_args, octave_cmdline_argv+last_arg_idx);
-
-          execute_command_line_file (octave_cmdline_argv[last_arg_idx]);
-        }
-      catch (const octave_execution_exception&)
-        {
-          recover_from_exception ();
-
-          exit_status = 1;
-        }
-
-      if (! persist)
-        {
-          quitting_gracefully = true;
-
-          clean_up_and_exit (exit_status);
-        }
-    }
-
-  // Avoid counting commands executed from startup files.
-
-  octave::command_editor::reset_current_command_number (1);
-
-  // Now argv should have the full set of args.
-  intern_argv (octave_cmdline_argc, octave_cmdline_argv);
-
-  // Force input to be echoed if not really interactive,
-  // but the user has forced interactive behavior.
-
-  if (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 (octave_embedded)
+  else
     {
-      // 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;
-}
-
-static bool
-check_starting_gui (void)
-{
-  if (no_window_system)
-    return false;
-
-  std::string err_msg;
-  if (! display_info::display_available (err_msg))
-    {
-      if (! (inhibit_startup_message || err_msg.empty ()))
-        warning (err_msg.c_str ());
-
-      return false;
-    }
-
-  if (! line_editing)
-    {
-      if (! (inhibit_startup_message || no_gui_option))
-        warning ("--no-line-editing option given, disabling GUI");
-
-      return false;
+      octave::cli_application app (argc, argv);
+      return app.execute ();
     }
-
-  if (force_gui_option)
-    return true;
-
-  if (no_gui_option)
-    return false;
-
-  if (persist)
-    return true;
-
-  // If stdin is not a tty, then assume we are reading commands from a pipe or
-  // a redirected file and the GUI should not start.  If this is not the case
-  // (for example, starting from a desktop "launcher" with no terminal) and you
-  // want to start the GUI, you may use the --force-gui option to start the GUI.
-
-  if (! octave_isatty_wrapper (fileno (stdin)))
-    return false;
-
-  // If we have code to eval or execute from a file, and we are going to exit
-  // immediately after executing it, don't start the gui.
-
-  int last_arg_idx = optind;
-  int remaining_args = octave_cmdline_argc - last_arg_idx;
-
-  if (! code_to_eval.empty () || remaining_args > 0)
-    return false;
-
-  return true;
-}
-
-// Return int instead of bool because this function is declared extern "C".
-
-int
-octave_starting_gui (void)
-{
-  start_gui = check_starting_gui ();
-  return start_gui;
 }
 
 DEFUN (isguirunning, args, ,
@@ -1075,7 +1099,10 @@
   if (args.length () != 0)
     print_usage ();
 
-  return ovl (start_gui);
+  // FIXME: This isn't quite right, it just says that we intended to
+  // start the GUI, not that it is actually running.
+
+  return ovl (octave::application::is_gui_running ());
 }
 
 /*
@@ -1106,7 +1133,7 @@
   if (args.length () != 0)
     print_usage ();
 
-  return ovl (Cell (octave_argv));
+  return ovl (Cell (octave::application::argv ()));
 }
 
 /*
@@ -1129,7 +1156,7 @@
   if (args.length () != 0)
     print_usage ();
 
-  return ovl (octave_program_invocation_name);
+  return ovl (octave::application::program_invocation_name ());
 }
 
 /*
@@ -1148,7 +1175,7 @@
   if (args.length () != 0)
     print_usage ();
 
-  return ovl (octave_program_name);
+  return ovl (octave::application::program_name ());
 }
 
 /*
--- a/libinterp/octave.h	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/octave.h	Sun Jul 10 07:15:21 2016 -0400
@@ -26,25 +26,353 @@
 #include "octave-config.h"
 
 #if defined  (__cplusplus)
+
+#include <list>
+#include <string>
+
+#include <str-vec.h>
+
+namespace octave
+{
+  // Command line arguments.  See also options-usage.h.
+
+  class OCTINTERP_API cmdline_options
+  {
+  public:
+
+    cmdline_options (void);
+
+    cmdline_options (int argc, char **argv);
+
+    cmdline_options (const cmdline_options& opts);
+
+    cmdline_options& operator = (const cmdline_options& opts);
+
+    bool force_gui (void) const { return m_force_gui; }
+    bool forced_interactive (void) const { return m_forced_interactive; }
+    bool forced_line_editing (void) const { return m_forced_line_editing; }
+    bool inhibit_startup_message (void) const { return m_inhibit_startup_message; }
+    bool line_editing (void) const { return m_line_editing; }
+    bool no_gui (void) const { return m_no_gui; }
+    bool no_window_system (void) const { return m_no_window_system; }
+    bool persist (void) const { return m_persist; }
+    bool read_history_file (void) const { return m_read_history_file; }
+    bool read_init_files (void) const { return m_read_init_files; }
+    bool read_site_files (void) const { return m_read_site_files; }
+    bool set_initial_path (void) const { return m_set_initial_path; }
+    bool traditional (void) const { return m_traditional; }
+    bool verbose_flag (void) const { return m_verbose_flag; }
+    std::string code_to_eval (void) const { return m_code_to_eval; }
+    std::list<std::string> command_line_path (void) const { return m_command_line_path; }
+    std::string exec_path (void) const { return m_exec_path; }
+    std::string image_path (void) const { return m_image_path; }
+    string_vector all_args (void) const { return m_all_args; }
+    string_vector remaining_args (void) const { return m_remaining_args; }
+
+    void force_gui (bool arg) { m_force_gui = arg; }
+    void forced_line_editing (bool arg) { m_forced_line_editing = arg; }
+    void forced_interactive (bool arg) { m_forced_interactive = arg; }
+    void inhibit_startup_message (bool arg) { m_inhibit_startup_message = arg; }
+    void line_editing (bool arg) { m_line_editing = arg; }
+    void no_gui (bool arg) { m_no_gui = arg; }
+    void no_window_system (bool arg) { m_no_window_system = arg; }
+    void persist (bool arg) { m_persist = arg; }
+    void read_history_file (bool arg) { m_read_history_file = arg; }
+    void read_init_files (bool arg) { m_read_init_files = arg; }
+    void read_site_files (bool arg) { m_read_site_files = arg; }
+    void set_initial_path (bool arg) { m_set_initial_path = arg; }
+    void traditional (bool arg) { m_traditional = arg; }
+    void verbose_flag (bool arg) { m_verbose_flag = arg; }
+    void code_to_eval (const std::string& arg) { m_code_to_eval = arg; }
+    void command_line_path (const std::list<std::string>& arg) { m_command_line_path = arg; }
+    void exec_path (const std::string& arg) { m_exec_path = arg; }
+    void image_path (const std::string& arg) { m_image_path = arg; }
+    void all_args (const string_vector& arg) { m_all_args = arg; }
+    void remaining_args (const string_vector& arg) { m_remaining_args = arg; }
+
+  private:
+
+    // If TRUE, force the GUI to start.
+    // (--force-gui)
+    bool m_force_gui = false;
+
+    // TRUE means the user forced this shell to be interactive.
+    // (--interactive, -i)
+    bool m_forced_interactive = false;
+
+    // If TRUE, force readline command line editing.
+    // (--line-editing)
+    bool m_forced_line_editing = false;
+
+    // TRUE means we don't print the usual startup message.
+    // (--quiet; --silent; -q)
+    bool m_inhibit_startup_message = false;
+
+    // TRUE means we are using readline.
+    // (--no-line-editing)
+    bool m_line_editing = true;
+
+    // If TRUE don't start the GUI.
+    // (--no-gui)
+    bool m_no_gui = false;
+
+    // If TRUE, ignore the window system even if it is available.
+    // (--no-window-system, -W)
+    bool m_no_window_system = false;
+
+    // If TRUE, don't exit after evaluating code given by --eval option.
+    // (--persist)
+    bool m_persist = false;
+
+    // If TRUE, initialize history list from saved history file.
+    // (--no-history; -H)
+    bool m_read_history_file = true;
+
+    // TRUE means we read ~/.octaverc and ./.octaverc.
+    // (--norc; --no-init-file; -f)
+    bool m_read_init_files = true;
+
+    // TRUE means we read the site-wide octaverc files.
+    // (--norc; --no-site-file; -f)
+    bool m_read_site_files = true;
+
+    // TRUE means we set the initial path to configured defaults.
+    // (--no-init-path)
+    bool m_set_initial_path = true;
+
+    // If TRUE use traditional (maximally MATLAB compatible) settings
+    // (--traditional)
+    bool m_traditional = false;
+
+    // If TRUE, print verbose info in some cases.
+    // (--verbose; -V)
+    bool m_verbose_flag = false;
+
+    // The code to evaluate at startup
+    // (--eval CODE)
+    std::string m_code_to_eval;
+
+    // The value of "path" specified on the command line.
+    // (--path; -p)
+    std::list<std::string> m_command_line_path;
+
+    // The value for "EXEC_PATH" specified on the command line.
+    // (--exec-path)
+    std::string m_exec_path;
+
+    // The value for "IMAGE_PATH" specified on the command line.
+    // (--image-path)
+    std::string m_image_path;
+
+    // All arguments passed to the argc, argv constructor.
+    string_vector m_all_args;
+
+    // Arguments remaining after parsing.
+    string_vector m_remaining_args;
+  };
+
+  // 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...
+
+  class interpreter;
+
+  // Base class for an Octave application.
+
+  class OCTINTERP_API application
+  {
+  public:
+
+    application (const cmdline_options& opts = cmdline_options ());
+
+    application (int argc, char **argv);
+
+    virtual ~application (void);
+
+    void set_program_names (const std::string& pname);
+
+    void intern_argv (const string_vector& args);
+
+    cmdline_options options (void) const { return m_options; }
+
+    bool have_script_file (void) const { return m_have_script_file; }
+
+    bool is_octave_program (void) const { return m_is_octave_program; }
+
+    virtual void create_interpreter (void);
+
+    virtual int execute_interpreter (void);
+
+    virtual int execute (void) = 0;
+
+    virtual bool gui_running (void) const { return false; }
+    virtual void gui_running (bool) { }
+
+    void program_invocation_name (const std::string& nm) { m_program_invocation_name = nm; }
+
+    void program_name (const std::string& nm) { m_program_name = nm; }
+
+    void forced_interactive (bool arg) { m_options.forced_interactive (arg); }
+
+    void interactive (bool arg);
+
+    // Should be an error if instance is 0.
+    static application *app (void) { return instance; }
+
+    static std::string program_invocation_name (void) { return instance->m_program_invocation_name; }
+
+    static std::string program_name (void) { return instance->m_program_name; }
+
+    static string_vector argv (void) { return instance->m_argv; }
+
+    static bool is_gui_running (void) { return instance->gui_running (); }
+
+    static interpreter *the_interpreter (void) { return instance->m_interpreter; }
+
+    // Convenience functions.
+
+    static bool forced_interactive (void);
+    static bool interactive (void);
+
+  private:
+
+    // No copying, at least not yet...
+
+    application (const application&);
+
+    application& operator = (const application&);
+
+    // The application instance;  There should be only one.
+    static application *instance;
+
+    void init (void);
+
+  protected:
+
+    // The name used to invoke Octave.
+    std::string m_program_invocation_name;
+
+    // The last component of octave_program_invocation_name.
+    std::string m_program_name;
+
+    // The current argument vector (may change if we are running a
+    // script with --persist because after the script is done, the
+    // arguments revert to the full list given to the octave
+    // interpreter at startup.
+    string_vector m_argv;
+
+    cmdline_options m_options;
+
+    // TRUE if there is a command line argument that looks like the
+    // name of a file to execute.
+    bool m_have_script_file = false;
+
+    // TRUE if this is a program and no interpreter and interaction is
+    // needed.  For example, an octave program with shebang line, or code
+    // from eval without persist.
+    bool m_is_octave_program = false;
+
+    // If TRUE, the GUI should be started.
+    bool m_gui_running = false;
+
+    interpreter *m_interpreter = 0;
+  };
+
+  class OCTINTERP_API cli_application : public application
+  {
+  public:
+
+    cli_application (const cmdline_options& opts = cmdline_options ())
+      : application (opts)
+    { }
+
+    cli_application (int argc, char **argv)
+      : application (argc, argv)
+    { }
+
+    ~cli_application (void) { }
+
+    int execute (void);
+
+  private:
+
+    // No copying, at least not yet...
+
+    cli_application (const cli_application&);
+
+    cli_application& operator = (const cli_application&);
+  };
+
+  class OCTINTERP_API embedded_application : public application
+  {
+  public:
+
+    embedded_application (const cmdline_options& opts = cmdline_options ())
+      : application (opts)
+    { }
+
+    embedded_application (int argc, char **argv)
+      : application (argc, argv)
+    { }
+
+    ~embedded_application (void) { }
+
+    void create_interpreter (void);
+
+    int execute (void);
+
+  private:
+
+    // No copying, at least not yet...
+
+    embedded_application (const embedded_application&);
+
+    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
+
+#if defined  (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTINTERP_API int octave_main (int argc, char **argv, int embedded);
 
-extern OCTINTERP_API void octave_process_command_line (int argc, char **argv);
-
-extern OCTINTERP_API void
-octave_initialize_interpreter (int argc, char **argv, int embedded);
-
-extern OCTINTERP_API int octave_execute_interpreter (void);
-
-extern OCTINTERP_API int octave_cmdline_argc;
-extern OCTINTERP_API char **octave_cmdline_argv;
-extern OCTINTERP_API int octave_embedded;
-
-extern OCTINTERP_API int octave_starting_gui (void);
-extern OCTINTERP_API int octave_fork_gui (void);
-
 #if defined  (__cplusplus)
 }
 #endif
--- a/libinterp/parse-tree/lex.ll	Mon Jul 11 13:45:12 2016 -0400
+++ b/libinterp/parse-tree/lex.ll	Sun Jul 10 07:15:21 2016 -0400
@@ -107,6 +107,7 @@
 #include "errwarn.h"
 #include "input.h"
 #include "lex.h"
+#include "octave.h"
 #include "ov.h"
 #include "parse.h"
 #include "pt-all.h"
@@ -2321,7 +2322,7 @@
   // input.
 
   if (! quitting_gracefully
-      && interactive
+      && octave::application::interactive ()
       && ! (reading_fcn_file
             || reading_classdef_file
             || reading_script_file
--- a/src/main-cli.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/src/main-cli.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -33,6 +33,8 @@
 
 #include "liboctinterp-build-info.h"
 
+#include "oct-env.h"
+
 #include "defaults.h"
 #include "octave.h"
 #include "octave-build-info.h"
@@ -81,13 +83,9 @@
 {
   check_hg_versions ();
 
-  octave_process_command_line (argc, argv);
-
-  sysdep_init ();
+  octave::sys::env::set_program_name (argv[0]);
 
-  install_defaults ();
+  octave::cli_application app (argc, argv);
 
-  octave_initialize_interpreter (argc, argv, 0);
-
-  return octave_execute_interpreter ();
+  return app.execute ();
 }
--- a/src/main-gui.cc	Mon Jul 11 13:45:12 2016 -0400
+++ b/src/main-gui.cc	Sun Jul 10 07:15:21 2016 -0400
@@ -35,6 +35,8 @@
 
 #include "liboctgui-build-info.h"
 
+#include "oct-env.h"
+
 #include "defaults.h"
 #include "octave.h"
 #include "octave-build-info.h"
@@ -95,13 +97,9 @@
 {
   check_hg_versions ();
 
-  octave_process_command_line (argc, argv);
-
-  sysdep_init ();
+  octave::sys::env::set_program_name (argv[0]);
 
-  install_defaults ();
+  octave::gui_application app (argc, argv);
 
-  bool start_gui = octave_starting_gui ();
-
-  return octave_start_gui (argc, argv, start_gui);
+  return app.execute ();
 }