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