1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 #  include "config.h"
28 #endif
29 
30 #include <cstdio>
31 
32 #include <set>
33 #include <string>
34 #include <iostream>
35 
36 #include "cmd-edit.h"
37 #include "cmd-hist.h"
38 #include "file-ops.h"
39 #include "file-stat.h"
40 #include "file-ops.h"
41 #include "fpucw-wrappers.h"
42 #include "lo-blas-proto.h"
43 #include "lo-error.h"
44 #include "oct-env.h"
45 #include "str-vec.h"
46 #include "signal-wrappers.h"
47 #include "unistd-wrappers.h"
48 
49 #include "builtin-defun-decls.h"
50 #include "defaults.h"
51 #include "Cell.h"
52 #include "defun.h"
53 #include "display.h"
54 #include "error.h"
55 #include "event-manager.h"
56 #include "file-io.h"
57 #include "graphics.h"
58 #include "help.h"
59 #include "input.h"
60 #include "interpreter-private.h"
61 #include "interpreter.h"
62 #include "load-path.h"
63 #include "load-save.h"
64 #include "octave.h"
65 #include "oct-hist.h"
66 #include "oct-map.h"
67 #include "oct-mutex.h"
68 #include "ovl.h"
69 #include "ov.h"
70 #include "ov-classdef.h"
71 #include "parse.h"
72 #include "pt-classdef.h"
73 #include "pt-eval.h"
74 #include "pt-jump.h"
75 #include "pt-stmt.h"
76 #include "settings.h"
77 #include "sighandlers.h"
78 #include "sysdep.h"
79 #include "unwind-prot.h"
80 #include "utils.h"
81 #include "variables.h"
82 #include "version.h"
83 
84 // TRUE means the quit() call is allowed.
85 bool quit_allowed = true;
86 
87 // TRUE means we are ready to interpret commands, but not everything
88 // is ready for interactive use.
89 bool octave_interpreter_ready = false;
90 
91 // TRUE means we've processed all the init code and we are good to go.
92 bool octave_initialized = false;
93 
94 DEFUN (__version_info__, args, ,
95        doc: /* -*- texinfo -*-
96 @deftypefn {} {retval =} __version_info__ (@var{name}, @var{version}, @var{release}, @var{date})
97 Undocumented internal function.
98 @end deftypefn */)
99 {
100   static octave_map vinfo;
101 
102   int nargin = args.length ();
103 
104   if (nargin != 0 && nargin != 4)
105     print_usage ();
106 
107   octave_value retval;
108 
109   if (nargin == 0)
110     retval = vinfo;
111   else if (nargin == 4)
112     {
113       if (vinfo.nfields () == 0)
114         {
115           vinfo.assign ("Name", args(0));
116           vinfo.assign ("Version", args(1));
117           vinfo.assign ("Release", args(2));
118           vinfo.assign ("Date", args(3));
119         }
120       else
121         {
122           octave_idx_type n = vinfo.numel () + 1;
123 
124           vinfo.resize (dim_vector (n, 1));
125 
126           octave_value idx (n);
127 
128           vinfo.assign (idx, "Name", Cell (octave_value (args(0))));
129           vinfo.assign (idx, "Version", Cell (octave_value (args(1))));
130           vinfo.assign (idx, "Release", Cell (octave_value (args(2))));
131           vinfo.assign (idx, "Date", Cell (octave_value (args(3))));
132         }
133     }
134 
135   return retval;
136 }
137 
138 DEFMETHOD (quit, interp, args, ,
139            doc: /* -*- texinfo -*-
140 @deftypefn  {} {} quit
141 @deftypefnx {} {} quit cancel
142 @deftypefnx {} {} quit force
143 @deftypefnx {} {} quit ("cancel")
144 @deftypefnx {} {} quit ("force")
145 @deftypefnx {} {} quit (@var{status})
146 @deftypefnx {} {} quit (@var{status}, "force")
147 Quit the current Octave session.
148 
149 The @code{exit} function is an alias for @code{quit}.
150 
151 If the optional integer value @var{status} is supplied, pass that value to
152 the operating system as Octave's exit status.  The default value is zero.
153 
154 When exiting, Octave will attempt to run the m-file @file{finish.m} if it
155 exists.  User commands to save the workspace or clean up temporary files
156 may be placed in that file.  Alternatively, another m-file may be scheduled
157 to run using @code{atexit}.  If an error occurs while executing the
158 @file{finish.m} file, Octave does not exit and control is returned to
159 the command prompt.
160 
161 If the optional argument @qcode{"cancel"} is provided, Octave does not
162 exit and control is returned to the command prompt.  This feature allows
163 the @code{finish.m} file to cancel the quit process.
164 
165 If the user preference to request confirmation before exiting, Octave
166 will display a dialog and give the user an option to cancel the exit
167 process.
168 
169 If the optional argument @qcode{"force"} is provided, no confirmation is
170 requested, and the execution of the @file{finish.m} file is skipped.
171 @seealso{atexit}
172 @end deftypefn */)
173 {
174   int numel = args.length ();
175 
176   if (numel > 2)
177     print_usage ();
178 
179   int exit_status = 0;
180 
181   bool force = false;
182   bool cancel = false;
183 
184   if (numel == 2)
185     {
186       exit_status = args(0).xnint_value ("quit: STATUS must be an integer");
187       std::string frc
188         = args(1).xstring_value ("quit: second argument must be a string");
189 
190       if (frc == "force")
191         force = true;
192       else
193         error (R"(quit: second argument must be string "force")");
194     }
195   else if (numel == 1)
196     {
197       if (args(0).is_string ())
198         {
199           const char *msg
200             = R"(quit: option must be string "cancel" or "force")";
201 
202           std::string opt = args(0).xstring_value (msg);
203 
204           if (opt == "cancel")
205             cancel = true;
206           else if (opt == "force")
207             force = true;
208           else
209             error ("%s", msg);
210         }
211       else
212         exit_status = args(0).xnint_value ("quit: STATUS must be an integer");
213     }
214 
215   if (cancel)
216     {
217       // No effect if "quit cancel" appears outside of finish script.
218 
219       if (interp.executing_finish_script ())
220         interp.cancel_quit (true);
221 
222       return ovl ();
223     }
224 
225   interp.quit (exit_status, force);
226 
227   return ovl ();
228 }
229 
230 DEFALIAS (exit, quit);
231 
232 DEFMETHOD (atexit, interp, args, nargout,
233            doc: /* -*- texinfo -*-
234 @deftypefn  {} {} atexit (@var{fcn})
235 @deftypefnx {} {} atexit (@var{fcn}, @var{flag})
236 Register a function to be called when Octave exits.
237 
238 For example,
239 
240 @example
241 @group
242 function last_words ()
243   disp ("Bye bye");
244 endfunction
245 atexit ("last_words");
246 @end group
247 @end example
248 
249 @noindent
250 will print the message @qcode{"Bye bye"} when Octave exits.
251 
252 The additional argument @var{flag} will register or unregister @var{fcn}
253 from the list of functions to be called when Octave exits.  If @var{flag} is
254 true, the function is registered, and if @var{flag} is false, it is
255 unregistered.  For example, after registering the function @code{last_words}
256 above,
257 
258 @example
259 atexit ("last_words", false);
260 @end example
261 
262 @noindent
263 will remove the function from the list and Octave will not call
264 @code{last_words} when it exits.
265 
266 Note that @code{atexit} only removes the first occurrence of a function
267 from the list, so if a function was placed in the list multiple times with
268 @code{atexit}, it must also be removed from the list multiple times.
269 @seealso{quit}
270 @end deftypefn */)
271 {
272   int nargin = args.length ();
273 
274   if (nargin < 1 || nargin > 2)
275     print_usage ();
276 
277   std::string arg = args(0).xstring_value ("atexit: FCN argument must be a string");
278 
279   bool add_mode = (nargin == 2)
280     ? args(1).xbool_value ("atexit: FLAG argument must be a logical value")
281     : true;
282 
283   octave_value_list retval;
284 
285   if (add_mode)
286     interp.add_atexit_fcn (arg);
287   else
288     {
289       bool found = interp.remove_atexit_fcn (arg);
290 
291       if (nargout > 0)
292         retval = ovl (found);
293     }
294 
295   return retval;
296 }
297 
298 namespace octave
299 {
~temporary_file_list(void)300   temporary_file_list::~temporary_file_list (void)
301   {
302     cleanup ();
303   }
304 
insert(const std::string & file)305   void temporary_file_list::insert (const std::string& file)
306   {
307     m_files.insert (file);
308   }
309 
cleanup(void)310   void temporary_file_list::cleanup (void)
311   {
312     while (! m_files.empty ())
313       {
314         auto it = m_files.begin ();
315 
316         octave_unlink_wrapper (it->c_str ());
317 
318         m_files.erase (it);
319       }
320   }
321 
322   // The time we last time we changed directories.
323   sys::time Vlast_chdir_time = 0.0;
324 
325   // Execute commands from a file and catch potential exceptions in a consistent
326   // way.  This function should be called anywhere we might parse and execute
327   // commands from a file before we have entered the main loop in
328   // toplev.cc.
329 
safe_source_file(const std::string & file_name,const std::string & context="",bool verbose=false,bool require_file=true)330   static int safe_source_file (const std::string& file_name,
331                                const std::string& context = "",
332                                bool verbose = false,
333                                bool require_file = true)
334   {
335     interpreter& interp = __get_interpreter__ ("safe_source_file");
336 
337     try
338       {
339         source_file (file_name, context, verbose, require_file);
340       }
341     catch (const interrupt_exception&)
342       {
343         interp.recover_from_exception ();
344 
345         return 1;
346       }
347     catch (const execution_exception& e)
348       {
349         interp.handle_exception (e);
350 
351         return 1;
352       }
353 
354     return 0;
355   }
356 
initialize_version_info(void)357   static void initialize_version_info (void)
358   {
359     octave_value_list args;
360 
361     args(3) = OCTAVE_RELEASE_DATE;
362     args(2) = config::release ();
363     args(1) = OCTAVE_VERSION;
364     args(0) = "GNU Octave";
365 
366     F__version_info__ (args, 0);
367   }
368 
xerbla_abort(void)369   static void xerbla_abort (void)
370   {
371     error ("Fortran procedure terminated by call to XERBLA");
372   }
373 
initialize_xerbla_error_handler(void)374   static void initialize_xerbla_error_handler (void)
375   {
376     // The idea here is to force xerbla to be referenced so that we will
377     // link to our own version instead of the one provided by the BLAS
378     // library.  But numeric_limits<double>::NaN () should never be -1, so
379     // we should never actually call xerbla.  FIXME (again!): If this
380     // becomes a constant expression the test might be optimized away and
381     // then the reference to the function might also disappear.
382 
383     if (numeric_limits<double>::NaN () == -1)
384       F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6));
385 
386     typedef void (*xerbla_handler_ptr) (void);
387 
388     typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr);
389 
390     dynamic_library libs ("");
391 
392     if (libs)
393       {
394         octave_set_xerbla_handler_ptr octave_set_xerbla_handler
395           = reinterpret_cast<octave_set_xerbla_handler_ptr>
396               (libs.search ("octave_set_xerbla_handler"));
397 
398         if (octave_set_xerbla_handler)
399           octave_set_xerbla_handler (xerbla_abort);
400       }
401   }
402 
403   OCTAVE_NORETURN static void
lo_error_handler(const char * fmt,...)404   lo_error_handler (const char *fmt, ...)
405   {
406     va_list args;
407     va_start (args, fmt);
408     verror_with_cfn (fmt, args);
409     va_end (args);
410 
411     throw execution_exception ();
412   }
413 
414   OCTAVE_NORETURN static void
lo_error_with_id_handler(const char * id,const char * fmt,...)415   lo_error_with_id_handler (const char *id, const char *fmt, ...)
416   {
417     va_list args;
418     va_start (args, fmt);
419     verror_with_id_cfn (id, fmt, args);
420     va_end (args);
421 
422     throw execution_exception ();
423   }
424 
initialize_error_handlers(void)425   static void initialize_error_handlers (void)
426   {
427     set_liboctave_error_handler (lo_error_handler);
428     set_liboctave_error_with_id_handler (lo_error_with_id_handler);
429     set_liboctave_warning_handler (warning);
430     set_liboctave_warning_with_id_handler (warning_with_id);
431   }
432 
433   // Create an interpreter object and perform initialization up to the
434   // point of setting reading command history and setting the load
435   // path.
436 
interpreter(application * app_context)437   interpreter::interpreter (application *app_context)
438     : m_app_context (app_context),
439       m_tmp_files (),
440       m_atexit_fcns (),
441       m_display_info (),
442       m_environment (),
443       m_settings (),
444       m_error_system (*this),
445       m_help_system (*this),
446       m_input_system (*this),
447       m_output_system (*this),
448       m_history_system (*this),
449       m_dynamic_loader (*this),
450       m_load_path (*this),
451       m_load_save_system (*this),
452       m_type_info (),
453       m_symbol_table (*this),
454       m_evaluator (*this),
455       m_stream_list (*this),
456       m_child_list (),
457       m_url_handle_manager (),
458       m_cdef_manager (*this),
459       m_gtk_manager (),
460       m_event_manager (*this),
461       m_gh_manager (nullptr),
462       m_interactive (false),
463       m_read_site_files (true),
464       m_read_init_files (m_app_context != nullptr),
465       m_verbose (false),
466       m_inhibit_startup_message (false),
467       m_load_path_initialized (false),
468       m_history_initialized (false),
469       m_cancel_quit (false),
470       m_executing_finish_script (false),
471       m_executing_atexit (false),
472       m_initialized (false)
473   {
474     // FIXME: When thread_local storage is used by default, this message
475     // should change to say something like
476     //
477     //   only one Octave interpreter may be active in any given thread
478 
479     if (instance)
480       throw std::runtime_error
481         ("only one Octave interpreter may be active");
482 
483     instance = this;
484 
485     // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting
486     setlocale (LC_ALL, "");
487     setlocale (LC_NUMERIC, "C");
488     setlocale (LC_TIME, "C");
489     sys::env::putenv ("LC_NUMERIC", "C");
490     sys::env::putenv ("LC_TIME", "C");
491 
492     // Initialize the default floating point unit control state.
493     octave_set_default_fpucw ();
494 
495     thread::init ();
496 
497     octave_ieee_init ();
498 
499     initialize_xerbla_error_handler ();
500 
501     initialize_error_handlers ();
502 
503     if (m_app_context)
504       {
505         install_signal_handlers ();
506         octave_unblock_signal_by_name ("SIGTSTP");
507       }
508     else
509       quit_allowed = false;
510 
511     if (! m_app_context)
512       m_display_info.initialize ();
513 
514     bool line_editing = false;
515     bool traditional = false;
516 
517     if (m_app_context)
518       {
519         // Embedded interpreters don't execute command line options.
520         const cmdline_options& options = m_app_context->options ();
521 
522         // Make all command-line arguments available to startup files,
523         // including PKG_ADD files.
524 
525         string_vector args = options.all_args ();
526 
527         m_app_context->intern_argv (args);
528         intern_nargin (args.numel () - 1);
529 
530         bool is_octave_program = m_app_context->is_octave_program ();
531 
532         std::list<std::string> command_line_path = options.command_line_path ();
533 
534         for (const auto& pth : command_line_path)
535           m_load_path.set_command_line_path (pth);
536 
537         std::string exec_path = options.exec_path ();
538         if (! exec_path.empty ())
539           m_environment.exec_path (exec_path);
540 
541         std::string image_path = options.image_path ();
542         if (! image_path.empty ())
543           m_environment.image_path (image_path);
544 
545         if (! options.no_window_system ())
546           m_display_info.initialize ();
547 
548         // Is input coming from a terminal?  If so, we are probably
549         // interactive.
550 
551         // If stdin is not a tty, then we are reading commands from a
552         // pipe or a redirected file.
553         bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin));
554 
555         m_interactive = (! is_octave_program && stdin_is_tty
556                          && octave_isatty_wrapper (fileno (stdout)));
557 
558         // Check if the user forced an interactive session.
559         if (options.forced_interactive ())
560           m_interactive = true;
561 
562         line_editing = options.line_editing ();
563         if ((! m_interactive || options.forced_interactive ())
564             && ! options.forced_line_editing ())
565           line_editing = false;
566 
567         traditional = options.traditional ();
568 
569         // FIXME: if possible, perform the following actions directly
570         // instead of using the interpreter-level functions.
571 
572         if (options.echo_commands ())
573           m_evaluator.echo
574             (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS
575              | tree_evaluator::ECHO_ALL);
576 
577         std::string docstrings_file = options.docstrings_file ();
578         if (! docstrings_file.empty ())
579           Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file));
580 
581         std::string doc_cache_file = options.doc_cache_file ();
582         if (! doc_cache_file.empty ())
583           Fdoc_cache_file (*this, octave_value (doc_cache_file));
584 
585         std::string info_file = options.info_file ();
586         if (! info_file.empty ())
587           Finfo_file (*this, octave_value (info_file));
588 
589         std::string info_program = options.info_program ();
590         if (! info_program.empty ())
591           Finfo_program (*this, octave_value (info_program));
592 
593         if (options.debug_jit ())
594           Fdebug_jit (octave_value (true));
595 
596         if (options.jit_compiler ())
597           Fjit_enable (octave_value (true));
598 
599         std::string texi_macros_file = options.texi_macros_file ();
600         if (! texi_macros_file.empty ())
601           Ftexi_macros_file (*this, octave_value (texi_macros_file));
602       }
603 
604     // FIXME: we defer creation of the gh_manager object because it
605     // creates a root_figure object that requires the display_info
606     // object, but that is currently only accessible through the global
607     // interpreter object and that is not available until after the
608     // interpreter::instance pointer is set (above).  It would be better
609     // if m_gh_manager could be an object value instead of a pointer and
610     // created as part of the interpreter initialization.  To do that,
611     // we should either make the display_info object independent of the
612     // interpreter object (does it really need to cache any
613     // information?) or defer creation of the root_figure object until
614     // it is actually needed.
615     m_gh_manager = new gh_manager (*this);
616 
617     m_input_system.initialize (line_editing);
618 
619     // These can come after command line args since none of them set any
620     // defaults that might be changed by command line options.
621 
622     initialize_version_info ();
623 
624     // This should be done before initializing the load path because
625     // some PKG_ADD files might need --traditional behavior.
626 
627     if (traditional)
628       maximum_braindamage ();
629 
630     octave_interpreter_ready = true;
631   }
632 
633   OCTAVE_THREAD_LOCAL interpreter *interpreter::instance = nullptr;
634 
~interpreter(void)635   interpreter::~interpreter (void)
636   {
637     shutdown ();
638 
639     delete m_gh_manager;
640   }
641 
intern_nargin(octave_idx_type nargs)642   void interpreter::intern_nargin (octave_idx_type nargs)
643   {
644     m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs);
645   }
646 
647   // Read the history file unless a command-line option inhibits that.
648 
initialize_history(bool read_history_file)649   void interpreter::initialize_history (bool read_history_file)
650   {
651     if (! m_history_initialized)
652       {
653         // Allow command-line option to override.
654 
655         if (m_app_context)
656           {
657             const cmdline_options& options = m_app_context->options ();
658 
659             read_history_file = options.read_history_file ();
660 
661             if (! read_history_file)
662               command_history::ignore_entries ();
663           }
664 
665         m_history_system.initialize (read_history_file);
666 
667         if (! m_app_context)
668           command_history::ignore_entries ();
669 
670         m_history_initialized = true;
671       }
672   }
673 
674   // Set the initial path to the system default unless command-line
675   // option says to leave it empty.
676 
initialize_load_path(bool set_initial_path)677   void interpreter::initialize_load_path (bool set_initial_path)
678   {
679     if (! m_load_path_initialized)
680       {
681         // Allow command-line option to override.
682 
683         if (m_app_context)
684           {
685             const cmdline_options& options = m_app_context->options ();
686 
687             set_initial_path = options.set_initial_path ();
688           }
689 
690         // Temporarily set the execute_pkg_add function to one that
691         // catches exceptions.  This is better than wrapping
692         // load_path::initialize in a try-catch block because it will
693         // not stop executing PKG_ADD files at the first exception.
694         // It's also better than changing the default execute_pkg_add
695         // function to use safe_source file because that will normally
696         // be evaluated from the normal interpreter loop where exceptions
697         // are already handled.
698 
699         unwind_protect frame;
700 
701         frame.add_method (m_load_path, &load_path::set_add_hook,
702                           m_load_path.get_add_hook ());
703 
704         m_load_path.set_add_hook ([this] (const std::string& dir)
705                                   { this->execute_pkg_add (dir); });
706 
707         m_load_path.initialize (set_initial_path);
708 
709         m_load_path_initialized = true;
710       }
711   }
712 
713   // This may be called separately from execute
714 
initialize(void)715   void interpreter::initialize (void)
716   {
717     if (m_initialized)
718       return;
719 
720     display_startup_message ();
721 
722     // Wait to read the history file until the interpreter reads input
723     // files and begins evaluating commands.
724 
725     initialize_history ();
726 
727     // Initializing the load path may execute PKG_ADD files, so can't be
728     // done until the interpreter is ready to execute commands.
729 
730     // Deferring it to the execute step also allows the path to be
731     // initialized between creating and execute the interpreter, for
732     // example, to set a custom path for an embedded interpreter.
733 
734     initialize_load_path ();
735 
736     octave_save_signal_mask ();
737 
738     can_interrupt = true;
739 
740     octave_signal_hook = respond_to_pending_signals;
741     octave_interrupt_hook = nullptr;
742 
743     catch_interrupts ();
744 
745     // FIXME: could we eliminate this variable or make it not be global?
746     // Global used to communicate with signal handler.
747     octave_initialized = true;
748 
749     m_initialized = true;
750   }
751 
752   // FIXME: this function is intended to be executed only once.  Should
753   // we enforce that restriction?
754 
execute(void)755   int interpreter::execute (void)
756   {
757     int exit_status = 0;
758 
759     try
760       {
761         initialize ();
762 
763         execute_startup_files ();
764 
765         if (m_app_context)
766           {
767             const cmdline_options& options = m_app_context->options ();
768 
769             if (m_app_context->have_eval_option_code ())
770               {
771                 int status = execute_eval_option_code ();
772 
773                 if (status )
774                   exit_status = status;
775 
776                 if (! options.persist ())
777                   return exit_status;
778               }
779 
780             // If there is an extra argument, see if it names a file to
781             // read.  Additional arguments are taken as command line options
782             // for the script.
783 
784             if (m_app_context->have_script_file ())
785               {
786                 int status = execute_command_line_file ();
787 
788                 if (status)
789                   exit_status = status;
790 
791                 if (! options.persist ())
792                   return exit_status;
793               }
794 
795             if (options.forced_interactive ())
796               command_editor::blink_matching_paren (false);
797 
798             exit_status = main_loop ();
799           }
800       }
801     catch (const exit_exception& ex)
802       {
803         return ex.exit_status ();
804       }
805 
806     return exit_status;
807   }
808 
809   // Call a function with exceptions handled to avoid problems with
810   // errors while shutting down.
811 
812 #define OCTAVE_IGNORE_EXCEPTION(E)                                      \
813   catch (E)                                                             \
814     {                                                                   \
815       recover_from_exception ();                                        \
816                                                                         \
817       std::cerr << "error: ignoring " #E " while preparing to exit"     \
818                 << std::endl;                                           \
819     }
820 
821 #define OCTAVE_SAFE_CALL(F, ARGS)                                       \
822   do                                                                    \
823     {                                                                   \
824       try                                                               \
825         {                                                               \
826           unwind_protect frame;                                         \
827                                                                         \
828           frame.add_method (m_error_system,                             \
829                             &error_system::set_debug_on_error,          \
830                             m_error_system.debug_on_error ());          \
831           frame.add_method (m_error_system,                             \
832                             &error_system::set_debug_on_warning,        \
833                             m_error_system.debug_on_warning ());        \
834                                                                         \
835           m_error_system.debug_on_error (false);                        \
836           m_error_system.debug_on_warning (false);                      \
837                                                                         \
838           F ARGS;                                                       \
839         }                                                               \
840       OCTAVE_IGNORE_EXCEPTION (const exit_exception&)                   \
841       OCTAVE_IGNORE_EXCEPTION (const interrupt_exception&)              \
842       OCTAVE_IGNORE_EXCEPTION (const execution_exception&)              \
843       OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&)                   \
844     }                                                                   \
845   while (0)
846 
shutdown(void)847   void interpreter::shutdown (void)
848   {
849     // Attempt to prevent more than one call to shutdown.
850 
851     if (! m_initialized)
852       return;
853 
854     m_initialized = false;
855 
856     OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0));
857 
858     // If we are attached to a GUI, process pending events and
859     // disable the link.
860 
861     OCTAVE_SAFE_CALL (m_event_manager.process_events, (true));
862     OCTAVE_SAFE_CALL (m_event_manager.disable, ());
863 
864     OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ());
865 
866     // Any atexit functions added after this function call won't be
867     // executed.  Each atexit function is executed with
868     // OCTAVE_SAFE_CALL, so we don't need that here.
869 
870     execute_atexit_fcns ();
871 
872     // Clear all functions and variables.
873 
874     // Note that we don't force symbols to be cleared, so we will
875     // respect mlock at this point.  Later, we'll force all variables
876     // and functions to be cleared.
877 
878     OCTAVE_SAFE_CALL (clear_all, ());
879 
880     // We may still have some figures.  Close them.
881 
882     OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0));
883 
884     // What is supposed to happen if a figure has a closerequestfcn or
885     // deletefcn callback registered that creates other figures or
886     // variables?  What if those variables are classdef objects with
887     // destructors that can create figures?  The possibilities are
888     // endless.  At some point, we have to give up and force execution
889     // to end.
890 
891     // Note that we again don't force symbols to be cleared, so we
892     // continue to respect mlock here.  Later, we'll force all variables
893     // and functions to be cleared.
894 
895     OCTAVE_SAFE_CALL (clear_all, ());
896 
897     // Do this explicitly so that destructors for mex file objects
898     // are called, so that functions registered with mexAtExit are
899     // called.
900 
901     OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ());
902 
903     OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ());
904 
905     OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ());
906 
907     if (! command_history::ignoring_entries ())
908       OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ());
909 
910     OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ());
911 
912     // Now that the graphics toolkits have been unloaded, force all
913     // symbols to be cleared.
914 
915     OCTAVE_SAFE_CALL (clear_all, (true));
916 
917     // FIXME:  May still need something like this to ensure that
918     // destructors for class objects will run properly.  Should that be
919     // done earlier?  Before or after atexit functions are executed?
920     // What will happen if the destructor for an obect attempts to
921     // display a figure?
922 
923     OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ());
924 
925     OCTAVE_SAFE_CALL (sysdep_cleanup, ());
926 
927     OCTAVE_SAFE_CALL (flush_stdout, ());
928 
929     // Don't call singleton_cleanup_list::cleanup until we have the
930     // problems with registering/unregistering types worked out.  For
931     // example, uncomment the following line, then use the make_int
932     // function from the examples directory to create an integer
933     // object and then exit Octave.  Octave should crash with a
934     // segfault when cleaning up the typinfo singleton.  We need some
935     // way to force new octave_value_X types that are created in
936     // .oct files to be unregistered when the .oct file shared library
937     // is unloaded.
938     //
939     // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ());
940   }
941 
execute_atexit_fcns(void)942   void interpreter::execute_atexit_fcns (void)
943   {
944     // Prevent atexit functions from adding new functions to the list.
945     m_executing_atexit = true;
946 
947     while (! m_atexit_fcns.empty ())
948       {
949         std::string fcn = m_atexit_fcns.front ();
950 
951         m_atexit_fcns.pop_front ();
952 
953         OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0));
954 
955         OCTAVE_SAFE_CALL (flush_stdout, ());
956       }
957   }
958 
display_startup_message(void) const959   void interpreter::display_startup_message (void) const
960   {
961     bool inhibit_startup_message = false;
962 
963     if (m_app_context)
964       {
965         const cmdline_options& options = m_app_context->options ();
966 
967         inhibit_startup_message = options.inhibit_startup_message ();
968       }
969 
970     if (m_interactive && ! inhibit_startup_message)
971       std::cout << octave_startup_message () << "\n" << std::endl;
972   }
973 
974   // Initialize by reading startup files.  Return non-zero if an exception
975   // occurs when reading any of them, but don't exit early because of an
976   // exception.
977 
execute_startup_files(void)978   int interpreter::execute_startup_files (void)
979   {
980     bool read_site_files = m_read_site_files;
981     bool read_init_files = m_read_init_files;
982     bool verbose = m_verbose;
983     bool inhibit_startup_message = m_inhibit_startup_message;
984 
985     if (m_app_context)
986       {
987         const cmdline_options& options = m_app_context->options ();
988 
989         read_site_files = options.read_site_files ();
990         read_init_files = options.read_init_files ();
991         verbose = options.verbose_flag ();
992         inhibit_startup_message = options.inhibit_startup_message ();
993       }
994 
995     verbose = (verbose && ! inhibit_startup_message);
996 
997     bool require_file = false;
998 
999     std::string context;
1000 
1001     int exit_status = 0;
1002 
1003     if (read_site_files)
1004       {
1005         // Execute commands from the site-wide configuration file.
1006         // First from the file $(prefix)/lib/octave/site/m/octaverc
1007         // (if it exists), then from the file
1008         // $(prefix)/share/octave/$(version)/m/octaverc (if it exists).
1009 
1010         int status = safe_source_file (config::local_site_defaults_file (),
1011                                        context, verbose, require_file);
1012 
1013         if (status)
1014           exit_status = status;
1015 
1016         status = safe_source_file (config::site_defaults_file (),
1017                                    context, verbose, require_file);
1018 
1019         if (status)
1020           exit_status = status;
1021       }
1022 
1023     if (read_init_files)
1024       {
1025         // Try to execute commands from the Matlab compatible startup.m file
1026         // if it exists anywhere in the load path when starting Octave.
1027         std::string ff_startup_m = file_in_path ("startup.m", "");
1028 
1029         if (! ff_startup_m.empty ())
1030           {
1031             int parse_status = 0;
1032 
1033             try
1034               {
1035                 eval_string (std::string ("startup"), false, parse_status, 0);
1036               }
1037             catch (const interrupt_exception&)
1038               {
1039                 recover_from_exception ();
1040               }
1041             catch (const execution_exception& e)
1042               {
1043                 handle_exception (e);
1044               }
1045           }
1046 
1047         // Try to execute commands from $CONFIG/octave/octaverc, where
1048         // $CONFIG is the platform-dependent location for user local
1049         // configuration files.
1050 
1051         std::string user_config_dir = sys::env::get_user_config_directory ();
1052 
1053         std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str ()
1054                               + "octave";
1055 
1056         std::string cfg_rc = sys::env::make_absolute ("octaverc", cfg_dir);
1057 
1058         if (! cfg_rc.empty ())
1059           {
1060             int status = safe_source_file (cfg_rc, context, verbose,
1061                                            require_file);
1062 
1063             if (status)
1064               exit_status = status;
1065           }
1066 
1067         // Try to execute commands from $HOME/$OCTAVE_INITFILE and
1068         // $OCTAVE_INITFILE.  If $OCTAVE_INITFILE is not set,
1069         // .octaverc is assumed.
1070 
1071         bool home_rc_already_executed = false;
1072 
1073         std::string initfile = sys::env::getenv ("OCTAVE_INITFILE");
1074 
1075         if (initfile.empty ())
1076           initfile = ".octaverc";
1077 
1078         std::string home_dir = sys::env::get_home_directory ();
1079 
1080         std::string home_rc = sys::env::make_absolute (initfile, home_dir);
1081 
1082         std::string local_rc;
1083 
1084         if (! home_rc.empty ())
1085           {
1086             int status = safe_source_file (home_rc, context, verbose,
1087                                            require_file);
1088 
1089             if (status)
1090               exit_status = status;
1091 
1092             // Names alone are not enough.
1093 
1094             sys::file_stat fs_home_rc (home_rc);
1095 
1096             if (fs_home_rc)
1097               {
1098                 // We want to check for curr_dir after executing home_rc
1099                 // because doing that may change the working directory.
1100 
1101                 local_rc = sys::env::make_absolute (initfile);
1102 
1103                 home_rc_already_executed = same_file (home_rc, local_rc);
1104               }
1105           }
1106 
1107         if (! home_rc_already_executed)
1108           {
1109             if (local_rc.empty ())
1110               local_rc = sys::env::make_absolute (initfile);
1111 
1112             int status = safe_source_file (local_rc, context, verbose,
1113                                            require_file);
1114 
1115             if (status)
1116               exit_status = status;
1117           }
1118       }
1119 
1120     if (m_interactive && verbose)
1121       std::cout << std::endl;
1122 
1123     return exit_status;
1124   }
1125 
1126   // Execute any code specified with --eval 'CODE'
1127 
execute_eval_option_code(void)1128   int interpreter::execute_eval_option_code (void)
1129   {
1130     if (! m_app_context)
1131       return 0;
1132 
1133     const cmdline_options& options = m_app_context->options ();
1134 
1135     std::string code_to_eval = options.code_to_eval ();
1136 
1137     unwind_protect_var<bool> upv (m_interactive, false);
1138 
1139     int parse_status = 0;
1140 
1141     try
1142       {
1143         eval_string (code_to_eval, false, parse_status, 0);
1144       }
1145     catch (const interrupt_exception&)
1146       {
1147         recover_from_exception ();
1148 
1149         return 1;
1150       }
1151     catch (const execution_exception& e)
1152       {
1153         handle_exception (e);
1154 
1155         return 1;
1156       }
1157 
1158     return parse_status;
1159   }
1160 
execute_command_line_file(void)1161   int interpreter::execute_command_line_file (void)
1162   {
1163     if (! m_app_context)
1164       return 0;
1165 
1166     const cmdline_options& options = m_app_context->options ();
1167 
1168     unwind_protect frame;
1169 
1170     frame.add_method (this, &interpreter::interactive, m_interactive);
1171 
1172     string_vector args = options.all_args ();
1173 
1174     frame.add_method (m_app_context, &application::intern_argv, args);
1175 
1176     frame.add_method (this, &interpreter::intern_nargin, args.numel () - 1);
1177 
1178     frame.add_method (m_app_context,
1179                       &application::program_invocation_name,
1180                       application::program_invocation_name ());
1181 
1182     frame.add_method (m_app_context,
1183                       &application::program_name,
1184                       application::program_name ());
1185 
1186     m_interactive = false;
1187 
1188     // If we are running an executable script (#! /bin/octave) then
1189     // we should only see the args passed to the script.
1190 
1191     string_vector script_args = options.remaining_args ();
1192 
1193     m_app_context->intern_argv (script_args);
1194     intern_nargin (script_args.numel () - 1);
1195 
1196     std::string fname = script_args[0];
1197 
1198     m_app_context->set_program_names (fname);
1199 
1200     std::string context;
1201     bool verbose = false;
1202     bool require_file = true;
1203 
1204     return safe_source_file (fname, context, verbose, require_file);
1205   }
1206 
main_loop(void)1207   int interpreter::main_loop (void)
1208   {
1209     return m_evaluator.repl ();
1210   }
1211 
get_evaluator(void)1212   tree_evaluator& interpreter::get_evaluator (void)
1213   {
1214     return m_evaluator;
1215   }
1216 
get_stream_list(void)1217   stream_list& interpreter::get_stream_list (void)
1218   {
1219     return m_stream_list;
1220   }
1221 
get_url_handle_manager(void)1222   url_handle_manager& interpreter::get_url_handle_manager (void)
1223   {
1224     return m_url_handle_manager;
1225   }
1226 
1227   symbol_scope
get_top_scope(void) const1228   interpreter::get_top_scope (void) const
1229   {
1230     return m_evaluator.get_top_scope ();
1231   }
1232 
1233   symbol_scope
get_current_scope(void) const1234   interpreter::get_current_scope (void) const
1235   {
1236     return m_evaluator.get_current_scope ();
1237   }
1238 
1239   symbol_scope
require_current_scope(const std::string & who) const1240   interpreter::require_current_scope (const std::string& who) const
1241   {
1242     symbol_scope scope = get_current_scope ();
1243 
1244     if (! scope)
1245       error ("%s: symbol table scope missing", who.c_str ());
1246 
1247     return scope;
1248   }
1249 
get_profiler(void)1250   profiler& interpreter::get_profiler (void)
1251   {
1252     return m_evaluator.get_profiler ();
1253   }
1254 
chdir(const std::string & dir)1255   int interpreter::chdir (const std::string& dir)
1256   {
1257     std::string xdir = sys::file_ops::tilde_expand (dir);
1258 
1259     int cd_ok = sys::env::chdir (xdir);
1260 
1261     if (! cd_ok)
1262       error ("%s: %s", dir.c_str (), std::strerror (errno));
1263 
1264     Vlast_chdir_time.stamp ();
1265 
1266     // FIXME: should these actions be handled as a list of functions
1267     // to call so users can add their own chdir handlers?
1268 
1269     m_load_path.update ();
1270 
1271     m_event_manager.directory_changed (sys::env::get_current_directory ());
1272 
1273     return cd_ok;
1274   }
1275 
mlock(bool skip_first) const1276   void interpreter::mlock (bool skip_first) const
1277   {
1278     m_evaluator.mlock (skip_first);
1279   }
1280 
munlock(bool skip_first) const1281   void interpreter::munlock (bool skip_first) const
1282   {
1283     m_evaluator.munlock (skip_first);
1284   }
1285 
mislocked(bool skip_first) const1286   bool interpreter::mislocked (bool skip_first) const
1287   {
1288     return m_evaluator.mislocked (skip_first);
1289   }
1290 
munlock(const char * nm)1291   void interpreter::munlock (const char *nm)
1292   {
1293     if (! nm)
1294       error ("munlock: invalid value for NAME");
1295 
1296     munlock (std::string (nm));
1297   }
1298 
munlock(const std::string & nm)1299   void interpreter::munlock (const std::string& nm)
1300   {
1301     octave_value val = m_symbol_table.find_function (nm);
1302 
1303     if (val.is_defined ())
1304       {
1305         octave_function *fcn = val.function_value ();
1306 
1307         if (fcn)
1308           fcn->unlock ();
1309       }
1310   }
1311 
mislocked(const char * nm)1312   bool interpreter::mislocked (const char *nm)
1313   {
1314     if (! nm)
1315       error ("mislocked: invalid value for NAME");
1316 
1317     return mislocked (std::string (nm));
1318   }
1319 
mislocked(const std::string & nm)1320   bool interpreter::mislocked (const std::string& nm)
1321   {
1322     bool retval = false;
1323 
1324     octave_value val = m_symbol_table.find_function (nm);
1325 
1326     if (val.is_defined ())
1327       {
1328         octave_function *fcn = val.function_value ();
1329 
1330         if (fcn)
1331           retval = fcn->islocked ();
1332       }
1333 
1334     return retval;
1335   }
1336 
mfilename(const std::string & opt) const1337   std::string interpreter::mfilename (const std::string& opt) const
1338   {
1339     return m_evaluator.mfilename (opt);
1340   }
1341 
eval_string(const std::string & eval_str,bool silent,int & parse_status,int nargout)1342   octave_value_list interpreter::eval_string (const std::string& eval_str,
1343                                               bool silent, int& parse_status,
1344                                               int nargout)
1345   {
1346     return m_evaluator.eval_string (eval_str, silent, parse_status, nargout);
1347   }
1348 
eval_string(const std::string & eval_str,bool silent,int & parse_status)1349   octave_value interpreter::eval_string (const std::string& eval_str,
1350                                          bool silent, int& parse_status)
1351   {
1352     return m_evaluator.eval_string (eval_str, silent, parse_status);
1353   }
1354 
eval_string(const octave_value & arg,bool silent,int & parse_status,int nargout)1355   octave_value_list interpreter::eval_string (const octave_value& arg,
1356                                               bool silent, int& parse_status,
1357                                               int nargout)
1358   {
1359     return m_evaluator.eval_string (arg, silent, parse_status, nargout);
1360   }
1361 
eval(const std::string & try_code,int nargout)1362   octave_value_list interpreter::eval (const std::string& try_code,
1363                                        int nargout)
1364   {
1365     return m_evaluator.eval (try_code, nargout);
1366   }
1367 
eval(const std::string & try_code,const std::string & catch_code,int nargout)1368   octave_value_list interpreter::eval (const std::string& try_code,
1369                                        const std::string& catch_code,
1370                                        int nargout)
1371   {
1372     return m_evaluator.eval (try_code, catch_code, nargout);
1373   }
1374 
evalin(const std::string & context,const std::string & try_code,int nargout)1375   octave_value_list interpreter::evalin (const std::string& context,
1376                                          const std::string& try_code,
1377                                          int nargout)
1378   {
1379     return m_evaluator.evalin (context, try_code, nargout);
1380   }
1381 
evalin(const std::string & context,const std::string & try_code,const std::string & catch_code,int nargout)1382   octave_value_list interpreter::evalin (const std::string& context,
1383                                          const std::string& try_code,
1384                                          const std::string& catch_code,
1385                                          int nargout)
1386   {
1387     return m_evaluator.evalin (context, try_code, catch_code, nargout);
1388   }
1389 
1390   //! Evaluate an Octave function (built-in or interpreted) and return
1391   //! the list of result values.
1392   //!
1393   //! @param name The name of the function to call.
1394   //! @param args The arguments to the function.
1395   //! @param nargout The number of output arguments expected.
1396   //! @return A list of output values.  The length of the list is not
1397   //!         necessarily the same as @c nargout.
1398 
feval(const char * name,const octave_value_list & args,int nargout)1399   octave_value_list interpreter::feval (const char *name,
1400                                         const octave_value_list& args,
1401                                         int nargout)
1402   {
1403     return feval (std::string (name), args, nargout);
1404   }
1405 
feval(const std::string & name,const octave_value_list & args,int nargout)1406   octave_value_list interpreter::feval (const std::string& name,
1407                                         const octave_value_list& args,
1408                                         int nargout)
1409   {
1410     octave_value fcn = m_symbol_table.find_function (name, args);
1411 
1412     if (fcn.is_undefined ())
1413       error ("feval: function '%s' not found", name.c_str ());
1414 
1415     octave_function *of = fcn.function_value ();
1416 
1417     return of->call (m_evaluator, nargout, args);
1418   }
1419 
feval(octave_function * fcn,const octave_value_list & args,int nargout)1420   octave_value_list interpreter::feval (octave_function *fcn,
1421                                         const octave_value_list& args,
1422                                         int nargout)
1423   {
1424     if (fcn)
1425       return fcn->call (m_evaluator, nargout, args);
1426 
1427     return octave_value_list ();
1428   }
1429 
feval(const octave_value & val,const octave_value_list & args,int nargout)1430   octave_value_list interpreter::feval (const octave_value& val,
1431                                         const octave_value_list& args,
1432                                         int nargout)
1433   {
1434     // FIXME: do we really want to silently return an empty ovl if
1435     // the function object is undefined?  It's essentially what the
1436     // version above that accepts a pointer to an octave_function
1437     // object does and some code was apparently written to rely on it
1438     // (for example, __ode15__).
1439 
1440     if (val.is_undefined ())
1441       return ovl ();
1442 
1443     if (val.is_function ())
1444       {
1445         return feval (val.function_value (), args, nargout);
1446       }
1447     else if (val.is_function_handle () || val.is_inline_function ())
1448       {
1449         // This covers function handles, inline functions, and anonymous
1450         //  functions.
1451 
1452         std::list<octave_value_list> arg_list;
1453         arg_list.push_back (args);
1454 
1455         // FIXME: could we make octave_value::subsref a const method?
1456         // It would be difficult because there are instances of
1457         // incrementing the reference count inside subsref methods,
1458         // which means they can't be const with the current way of
1459         // handling reference counting.
1460 
1461         octave_value xval = val;
1462         return xval.subsref ("(", arg_list, nargout);
1463       }
1464     else if (val.is_string ())
1465       {
1466         return feval (val.string_value (), args, nargout);
1467       }
1468     else
1469       error ("feval: first argument must be a string, inline function, or a function handle");
1470 
1471     return ovl ();
1472   }
1473 
1474   //! Evaluate an Octave function (built-in or interpreted) and return
1475   //! the list of result values.
1476   //!
1477   //! @param args The first element of @c args is the function to call.
1478   //!             It may be the name of the function as a string, a function
1479   //!             handle, or an inline function.  The remaining arguments are
1480   //!             passed to the function.
1481   //! @param nargout The number of output arguments expected.
1482   //! @return A list of output values.  The length of the list is not
1483   //!         necessarily the same as @c nargout.
1484 
feval(const octave_value_list & args,int nargout)1485   octave_value_list interpreter::feval (const octave_value_list& args,
1486                                         int nargout)
1487   {
1488     if (args.length () == 0)
1489       error ("feval: first argument must be a string, inline function, or a function handle");
1490 
1491     octave_value f_arg = args(0);
1492 
1493     octave_value_list tmp_args = args.slice (1, args.length () - 1, true);
1494 
1495     return feval (f_arg, tmp_args, nargout);
1496   }
1497 
make_function_handle(const std::string & name)1498   octave_value interpreter::make_function_handle (const std::string& name)
1499   {
1500     return m_evaluator.make_fcn_handle (name);
1501   }
1502 
install_variable(const std::string & name,const octave_value & value,bool global)1503   void interpreter::install_variable (const std::string& name,
1504                                       const octave_value& value, bool global)
1505   {
1506     m_evaluator.install_variable (name, value, global);
1507   }
1508 
global_varval(const std::string & name) const1509   octave_value interpreter::global_varval (const std::string& name) const
1510   {
1511     return m_evaluator.global_varval (name);
1512   }
1513 
global_assign(const std::string & name,const octave_value & val)1514   void interpreter::global_assign (const std::string& name,
1515                                    const octave_value& val)
1516   {
1517     m_evaluator.global_assign (name, val);
1518   }
1519 
top_level_varval(const std::string & name) const1520   octave_value interpreter::top_level_varval (const std::string& name) const
1521   {
1522     return m_evaluator.top_level_varval (name);
1523   }
1524 
top_level_assign(const std::string & name,const octave_value & val)1525   void interpreter::top_level_assign (const std::string& name,
1526                                       const octave_value& val)
1527   {
1528     m_evaluator.top_level_assign (name, val);
1529   }
1530 
is_variable(const std::string & name) const1531   bool interpreter::is_variable (const std::string& name) const
1532   {
1533     return m_evaluator.is_variable (name);
1534   }
1535 
is_local_variable(const std::string & name) const1536   bool interpreter::is_local_variable (const std::string& name) const
1537   {
1538     return m_evaluator.is_local_variable (name);
1539   }
1540 
varval(const std::string & name) const1541   octave_value interpreter::varval (const std::string& name) const
1542   {
1543     return m_evaluator.varval (name);
1544   }
1545 
assign(const std::string & name,const octave_value & val)1546   void interpreter::assign (const std::string& name,
1547                             const octave_value& val)
1548   {
1549     m_evaluator.assign (name, val);
1550   }
1551 
assignin(const std::string & context,const std::string & name,const octave_value & val)1552   void interpreter::assignin (const std::string& context,
1553                               const std::string& name,
1554                               const octave_value& val)
1555   {
1556     m_evaluator.assignin (context, name, val);
1557   }
1558 
source_file(const std::string & file_name,const std::string & context,bool verbose,bool require_file)1559   void interpreter::source_file (const std::string& file_name,
1560                                  const std::string& context, bool verbose,
1561                                  bool require_file)
1562   {
1563     m_evaluator.source_file (file_name, context, verbose, require_file);
1564   }
1565 
at_top_level(void) const1566   bool interpreter::at_top_level (void) const
1567   {
1568     return m_evaluator.at_top_level ();
1569   }
1570 
isglobal(const std::string & name) const1571   bool interpreter::isglobal (const std::string& name) const
1572   {
1573     return m_evaluator.is_global (name);
1574   }
1575 
find(const std::string & name)1576   octave_value interpreter::find (const std::string& name)
1577   {
1578     return m_evaluator.find (name);
1579   }
1580 
clear_all(bool force)1581   void interpreter::clear_all (bool force)
1582   {
1583     m_evaluator.clear_all (force);
1584   }
1585 
clear_objects(void)1586   void interpreter::clear_objects (void)
1587   {
1588     m_evaluator.clear_objects ();
1589   }
1590 
clear_variable(const std::string & name)1591   void interpreter::clear_variable (const std::string& name)
1592   {
1593     m_evaluator.clear_variable (name);
1594   }
1595 
clear_variable_pattern(const std::string & pattern)1596   void interpreter::clear_variable_pattern (const std::string& pattern)
1597   {
1598     m_evaluator.clear_variable_pattern (pattern);
1599   }
1600 
clear_variable_regexp(const std::string & pattern)1601   void interpreter::clear_variable_regexp (const std::string& pattern)
1602   {
1603     m_evaluator.clear_variable_regexp (pattern);
1604   }
1605 
clear_variables(void)1606   void interpreter::clear_variables (void)
1607   {
1608     m_evaluator.clear_variables ();
1609   }
1610 
clear_global_variable(const std::string & name)1611   void interpreter::clear_global_variable (const std::string& name)
1612   {
1613     m_evaluator.clear_global_variable (name);
1614   }
1615 
clear_global_variable_pattern(const std::string & pattern)1616   void interpreter::clear_global_variable_pattern (const std::string& pattern)
1617   {
1618     m_evaluator.clear_global_variable_pattern (pattern);
1619   }
1620 
clear_global_variable_regexp(const std::string & pattern)1621   void interpreter::clear_global_variable_regexp (const std::string& pattern)
1622   {
1623     m_evaluator.clear_global_variable_regexp (pattern);
1624   }
1625 
clear_global_variables(void)1626   void interpreter::clear_global_variables (void)
1627   {
1628     m_evaluator.clear_global_variables ();
1629   }
1630 
clear_functions(bool force)1631   void interpreter::clear_functions (bool force)
1632   {
1633     m_symbol_table.clear_functions (force);
1634   }
1635 
clear_function(const std::string & name)1636   void interpreter::clear_function (const std::string& name)
1637   {
1638     m_symbol_table.clear_function (name);
1639   }
1640 
clear_symbol(const std::string & name)1641   void interpreter::clear_symbol (const std::string& name)
1642   {
1643     m_evaluator.clear_symbol (name);
1644   }
1645 
clear_function_pattern(const std::string & pat)1646   void interpreter::clear_function_pattern (const std::string& pat)
1647   {
1648     m_symbol_table.clear_function_pattern (pat);
1649   }
1650 
clear_function_regexp(const std::string & pat)1651   void interpreter::clear_function_regexp (const std::string& pat)
1652   {
1653     m_symbol_table.clear_function_regexp (pat);
1654   }
1655 
clear_symbol_pattern(const std::string & pat)1656   void interpreter::clear_symbol_pattern (const std::string& pat)
1657   {
1658     return m_evaluator.clear_symbol_pattern (pat);
1659   }
1660 
clear_symbol_regexp(const std::string & pat)1661   void interpreter::clear_symbol_regexp (const std::string& pat)
1662   {
1663     return m_evaluator.clear_symbol_regexp (pat);
1664   }
1665 
global_variable_names(void)1666   std::list<std::string> interpreter::global_variable_names (void)
1667   {
1668     return m_evaluator.global_variable_names ();
1669   }
1670 
top_level_variable_names(void)1671   std::list<std::string> interpreter::top_level_variable_names (void)
1672   {
1673     return m_evaluator.top_level_variable_names ();
1674   }
1675 
variable_names(void)1676   std::list<std::string> interpreter::variable_names (void)
1677   {
1678     return m_evaluator.variable_names ();
1679   }
1680 
user_function_names(void)1681   std::list<std::string> interpreter::user_function_names (void)
1682   {
1683     return m_symbol_table.user_function_names ();
1684   }
1685 
autoloaded_functions(void) const1686   std::list<std::string> interpreter::autoloaded_functions (void) const
1687   {
1688     return m_evaluator.autoloaded_functions ();
1689   }
1690 
handle_exception(const execution_exception & e)1691   void interpreter::handle_exception (const execution_exception& e)
1692   {
1693     m_error_system.save_exception (e);
1694 
1695     // FIXME: use a separate stream instead of std::cerr directly so that
1696     // error messages can be redirected more easily?  Pass the message
1697     // to an event manager function?
1698     m_error_system.display_exception (e, std::cerr);
1699 
1700     recover_from_exception ();
1701   }
1702 
recover_from_exception(void)1703   void interpreter::recover_from_exception (void)
1704   {
1705     can_interrupt = true;
1706     octave_interrupt_state = 0;
1707     octave_signal_caught = 0;
1708     octave_restore_signal_mask ();
1709     catch_interrupts ();
1710   }
1711 
mark_for_deletion(const std::string & file)1712   void interpreter::mark_for_deletion (const std::string& file)
1713   {
1714     m_tmp_files.insert (file);
1715   }
1716 
cleanup_tmp_files(void)1717   void interpreter::cleanup_tmp_files (void)
1718   {
1719     m_tmp_files.cleanup ();
1720   }
1721 
quit(int exit_status,bool force,bool confirm)1722   void interpreter::quit (int exit_status, bool force, bool confirm)
1723   {
1724     if (! force)
1725       {
1726         try
1727           {
1728             bool cancel = false;
1729 
1730             if (symbol_exist ("finish.m", "file"))
1731               {
1732                 unwind_protect_var<bool> upv1 (m_executing_finish_script, true);
1733                 unwind_protect_var<bool> upv2 (m_cancel_quit);
1734 
1735                 evalin ("base", "finish", 0);
1736 
1737                 cancel = m_cancel_quit;
1738               }
1739 
1740             if (cancel)
1741               return;
1742 
1743             // Check for confirmation.
1744 
1745             if (confirm && ! m_event_manager.confirm_shutdown ())
1746               return;
1747           }
1748         catch (const execution_exception&)
1749           {
1750             // Catch execution_exceptions so we don't throw an
1751             // exit_exception if there is an in finish.m.  But throw it
1752             // again so that will be handled as any other
1753             // execution_exception by the evaluator.  This way, errors
1754             // will be ignored properly and we won't exit if quit is
1755             // called recursively from finish.m.
1756 
1757             throw;
1758           }
1759       }
1760 
1761     throw exit_exception (exit_status);
1762   }
1763 
add_atexit_fcn(const std::string & fname)1764   void interpreter::add_atexit_fcn (const std::string& fname)
1765   {
1766     if (m_executing_atexit)
1767       return;
1768 
1769     m_atexit_fcns.push_front (fname);
1770   }
1771 
remove_atexit_fcn(const std::string & fname)1772   bool interpreter::remove_atexit_fcn (const std::string& fname)
1773   {
1774     bool found = false;
1775 
1776     for (auto it = m_atexit_fcns.begin ();
1777          it != m_atexit_fcns.end (); it++)
1778       {
1779         if (*it == fname)
1780           {
1781             m_atexit_fcns.erase (it);
1782             found = true;
1783             break;
1784           }
1785       }
1786 
1787     return found;
1788   }
1789 
add_atexit_function(const std::string & fname)1790   void interpreter::add_atexit_function (const std::string& fname)
1791   {
1792     interpreter& interp
1793       = __get_interpreter__ ("interpreter::add_atexit_function");
1794 
1795     interp.add_atexit_fcn (fname);
1796   }
1797 
remove_atexit_function(const std::string & fname)1798   bool interpreter::remove_atexit_function (const std::string& fname)
1799   {
1800     interpreter& interp
1801       = __get_interpreter__ ("interpreter::remove_atexit_function");
1802 
1803     return interp.remove_atexit_fcn (fname);
1804   }
1805 
1806   // What internal options get configured by --traditional.
1807 
maximum_braindamage(void)1808   void interpreter::maximum_braindamage (void)
1809   {
1810     m_input_system.PS1 (">> ");
1811     m_input_system.PS2 ("");
1812 
1813     m_evaluator.PS4 ("");
1814 
1815     m_load_save_system.crash_dumps_octave_core (false);
1816     m_load_save_system.save_default_options ("-mat-binary");
1817 
1818     m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%");
1819 
1820     m_error_system.beep_on_error (true);
1821     Fconfirm_recursive_rmdir (octave_value (false));
1822 
1823     Fdisable_diagonal_matrix (octave_value (true));
1824     Fdisable_permutation_matrix (octave_value (true));
1825     Fdisable_range (octave_value (true));
1826     Ffixed_point_format (octave_value (true));
1827     Fprint_empty_dimensions (octave_value (false));
1828     Fstruct_levels_to_print (octave_value (0));
1829 
1830     disable_warning ("Octave:abbreviated-property-match");
1831     disable_warning ("Octave:colon-nonscalar-argument");
1832     disable_warning ("Octave:data-file-in-path");
1833     disable_warning ("Octave:function-name-clash");
1834     disable_warning ("Octave:possible-matlab-short-circuit-operator");
1835   }
1836 
execute_pkg_add(const std::string & dir)1837   void interpreter::execute_pkg_add (const std::string& dir)
1838   {
1839     try
1840       {
1841         m_load_path.execute_pkg_add (dir);
1842       }
1843     catch (const interrupt_exception&)
1844       {
1845         recover_from_exception ();
1846       }
1847     catch (const execution_exception& e)
1848       {
1849         handle_exception (e);
1850       }
1851   }
1852 }
1853