Mercurial > octave
comparison libinterp/corefcn/interpreter.cc @ 31607:aac27ad79be6 stable
maint: Re-indent code after switch to using namespace macros.
* build-env.h, build-env.in.cc, Cell.h, __betainc__.cc, __eigs__.cc,
__ftp__.cc, __ichol__.cc, __ilu__.cc, __isprimelarge__.cc, __magick_read__.cc,
__pchip_deriv__.cc, amd.cc, base-text-renderer.cc, base-text-renderer.h,
besselj.cc, bitfcns.cc, bsxfun.cc, c-file-ptr-stream.h, call-stack.cc,
call-stack.h, ccolamd.cc, cellfun.cc, chol.cc, colamd.cc, dasrt.cc, data.cc,
debug.cc, defaults.cc, defaults.h, det.cc, display.cc, display.h, dlmread.cc,
dynamic-ld.cc, dynamic-ld.h, ellipj.cc, environment.cc, environment.h,
error.cc, error.h, errwarn.h, event-manager.cc, event-manager.h,
event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, fft.cc, fft2.cc,
file-io.cc, filter.cc, find.cc, ft-text-renderer.cc, ft-text-renderer.h,
gcd.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, gl2ps-print.h,
graphics-toolkit.cc, graphics-toolkit.h, graphics.cc, gsvd.cc, gtk-manager.cc,
gtk-manager.h, help.cc, help.h, hook-fcn.cc, hook-fcn.h, input.cc, input.h,
interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h,
inv.cc, jsondecode.cc, jsonencode.cc, latex-text-renderer.cc,
latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h,
lookup.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, lsode.cc, lu.cc, mappers.cc,
matrix_type.cc, max.cc, mex.cc, mexproto.h, mxarray.h, mxtypes.in.h,
oct-errno.in.cc, oct-hdf5-types.cc, oct-hist.cc, oct-hist.h, oct-map.cc,
oct-map.h, oct-opengl.h, oct-prcstrm.h, oct-process.cc, oct-process.h,
oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.h,
octave-default-image.h, ordqz.cc, ordschur.cc, pager.cc, pager.h, pinv.cc,
pow2.cc, pr-output.cc, psi.cc, qr.cc, quadcc.cc, rand.cc, regexp.cc,
settings.cc, settings.h, sighandlers.cc, sighandlers.h, sparse-xpow.cc,
sqrtm.cc, stack-frame.cc, stack-frame.h, stream-euler.cc, strfns.cc, svd.cc,
syminfo.cc, syminfo.h, symrcm.cc, symrec.cc, symrec.h, symscope.cc, symscope.h,
symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h,
text-renderer.cc, text-renderer.h, time.cc, toplev.cc, typecast.cc,
url-handle-manager.cc, url-handle-manager.h, urlwrite.cc, utils.cc, utils.h,
variables.cc, variables.h, xdiv.cc, __delaunayn__.cc, __init_fltk__.cc,
__init_gnuplot__.cc, __ode15__.cc, __voronoi__.cc, audioread.cc, convhulln.cc,
gzip.cc, cdef-class.cc, cdef-class.h, cdef-fwd.h, cdef-manager.cc,
cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h,
cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h,
cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc,
ov-base-mat.h, ov-base-scalar.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc,
ov-bool-mat.h, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.h, ov-cell.cc,
ov-ch-mat.cc, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h,
ov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc,
ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.h, ov-float.cc,
ov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-diag.cc,
ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-lazy-idx.cc,
ov-legacy-range.cc, ov-magic-int.cc, ov-mex-fcn.cc, ov-mex-fcn.h,
ov-null-mat.cc, ov-perm.cc, ov-range.cc, ov-re-diag.cc, ov-re-mat.cc,
ov-re-mat.h, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc,
ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.h,
octave.cc, octave.h, op-b-sbm.cc, op-bm-sbm.cc, op-cs-scm.cc, op-fm-fcm.cc,
op-fs-fcm.cc, op-s-scm.cc, op-scm-cs.cc, op-scm-s.cc, op-sm-cs.cc, ops.h,
anon-fcn-validator.cc, anon-fcn-validator.h, bp-table.cc, bp-table.h,
comment-list.cc, comment-list.h, filepos.h, lex.h, oct-lvalue.cc, oct-lvalue.h,
parse.h, profiler.cc, profiler.h, pt-anon-scopes.cc, pt-anon-scopes.h,
pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h,
pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc,
pt-binop.h, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc,
pt-cell.h, pt-check.cc, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h,
pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h,
pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h,
pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h,
pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h,
pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h,
pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h,
pt-walk.cc, pt-walk.h, pt.cc, pt.h, token.cc, token.h, Range.cc, Range.h,
idx-vector.cc, idx-vector.h, range-fwd.h, CollocWt.cc, CollocWt.h,
aepbalance.cc, aepbalance.h, chol.cc, chol.h, gepbalance.cc, gepbalance.h,
gsvd.cc, gsvd.h, hess.cc, hess.h, lo-mappers.cc, lo-mappers.h, lo-specfun.cc,
lo-specfun.h, lu.cc, lu.h, oct-convn.cc, oct-convn.h, oct-fftw.cc, oct-fftw.h,
oct-norm.cc, oct-norm.h, oct-rand.cc, oct-rand.h, oct-spparms.cc,
oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randgamma.cc, randgamma.h,
randmtzig.cc, randmtzig.h, randpoisson.cc, randpoisson.h, schur.cc, schur.h,
sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc,
sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h,
file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h,
lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h,
oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc,
oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h,
action-container.cc, action-container.h, base-list.h, cmd-edit.cc, cmd-edit.h,
cmd-hist.cc, cmd-hist.h, f77-fcn.h, file-info.cc, file-info.h,
lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.h,
lo-regexp.cc, lo-regexp.h, lo-utils.cc, lo-utils.h, oct-base64.cc,
oct-base64.h, oct-glob.cc, oct-glob.h, oct-inttypes.h, oct-mutex.cc,
oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sparse.cc,
oct-sparse.h, oct-string.h, octave-preserve-stream-state.h, pathsearch.cc,
pathsearch.h, quit.cc, quit.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc,
url-transfer.h:
Re-indent code after switch to using namespace macros.
author | Rik <rik@octave.org> |
---|---|
date | Thu, 01 Dec 2022 18:02:15 -0800 |
parents | e88a07dec498 |
children | d9970470108a |
comparison
equal
deleted
inserted
replaced
31605:e88a07dec498 | 31607:aac27ad79be6 |
---|---|
285 print_usage (); | 285 print_usage (); |
286 | 286 |
287 std::string arg = args(0).xstring_value ("atexit: FCN argument must be a string"); | 287 std::string arg = args(0).xstring_value ("atexit: FCN argument must be a string"); |
288 | 288 |
289 bool add_mode = (nargin == 2) | 289 bool add_mode = (nargin == 2) |
290 ? args(1).xbool_value ("atexit: FLAG argument must be a logical value") | 290 ? args(1).xbool_value ("atexit: FLAG argument must be a logical value") |
291 : true; | 291 : true; |
292 | 292 |
293 octave_value_list retval; | 293 octave_value_list retval; |
294 | 294 |
295 if (add_mode) | 295 if (add_mode) |
296 interp.add_atexit_fcn (arg); | 296 interp.add_atexit_fcn (arg); |
312 @end deftypefn */) | 312 @end deftypefn */) |
313 { | 313 { |
314 return ovl (interp.traditional ()); | 314 return ovl (interp.traditional ()); |
315 } | 315 } |
316 | 316 |
317 temporary_file_list::~temporary_file_list (void) | 317 temporary_file_list::~temporary_file_list (void) |
318 { | |
319 cleanup (); | |
320 } | |
321 | |
322 void temporary_file_list::insert (const std::string& file) | |
323 { | |
324 m_files.insert (file); | |
325 } | |
326 | |
327 void temporary_file_list::cleanup (void) | |
328 { | |
329 while (! m_files.empty ()) | |
330 { | |
331 auto it = m_files.begin (); | |
332 | |
333 octave_unlink_wrapper (it->c_str ()); | |
334 | |
335 m_files.erase (it); | |
336 } | |
337 } | |
338 | |
339 // The time we last time we changed directories. | |
340 sys::time Vlast_chdir_time = 0.0; | |
341 | |
342 // Execute commands from a file and catch potential exceptions in a consistent | |
343 // way. This function should be called anywhere we might parse and execute | |
344 // commands from a file before we have entered the main loop in | |
345 // toplev.cc. | |
346 | |
347 static int safe_source_file (const std::string& file_name, | |
348 const std::string& context = "", | |
349 bool verbose = false, | |
350 bool require_file = true) | |
351 { | |
352 interpreter& interp = __get_interpreter__ (); | |
353 | |
354 try | |
355 { | |
356 source_file (file_name, context, verbose, require_file); | |
357 } | |
358 catch (const interrupt_exception&) | |
359 { | |
360 interp.recover_from_exception (); | |
361 | |
362 return 1; | |
363 } | |
364 catch (const execution_exception& ee) | |
365 { | |
366 interp.handle_exception (ee); | |
367 | |
368 return 1; | |
369 } | |
370 | |
371 return 0; | |
372 } | |
373 | |
374 static void initialize_version_info (void) | |
375 { | |
376 octave_value_list args; | |
377 | |
378 args(3) = OCTAVE_RELEASE_DATE; | |
379 args(2) = config::release (); | |
380 args(1) = OCTAVE_VERSION; | |
381 args(0) = "GNU Octave"; | |
382 | |
383 F__version_info__ (args, 0); | |
384 } | |
385 | |
386 static void xerbla_abort (void) | |
387 { | |
388 error ("Fortran procedure terminated by call to XERBLA"); | |
389 } | |
390 | |
391 static void initialize_xerbla_error_handler (void) | |
392 { | |
393 // The idea here is to force xerbla to be referenced so that we will | |
394 // link to our own version instead of the one provided by the BLAS | |
395 // library. But numeric_limits<double>::NaN () should never be -1, so | |
396 // we should never actually call xerbla. FIXME (again!): If this | |
397 // becomes a constant expression the test might be optimized away and | |
398 // then the reference to the function might also disappear. | |
399 | |
400 if (numeric_limits<double>::NaN () == -1) | |
401 F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6)); | |
402 | |
403 typedef void (*xerbla_handler_ptr) (void); | |
404 | |
405 typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr); | |
406 | |
407 dynamic_library libs (""); | |
408 | |
409 if (libs) | |
410 { | |
411 octave_set_xerbla_handler_ptr octave_set_xerbla_handler | |
412 = reinterpret_cast<octave_set_xerbla_handler_ptr> | |
413 (libs.search ("octave_set_xerbla_handler")); | |
414 | |
415 if (octave_set_xerbla_handler) | |
416 octave_set_xerbla_handler (xerbla_abort); | |
417 } | |
418 } | |
419 | |
420 OCTAVE_NORETURN static void | |
421 lo_error_handler (const char *fmt, ...) | |
422 { | |
423 va_list args; | |
424 va_start (args, fmt); | |
425 verror_with_cfn (fmt, args); | |
426 va_end (args); | |
427 | |
428 throw execution_exception (); | |
429 } | |
430 | |
431 OCTAVE_NORETURN static void | |
432 lo_error_with_id_handler (const char *id, const char *fmt, ...) | |
433 { | |
434 va_list args; | |
435 va_start (args, fmt); | |
436 verror_with_id_cfn (id, fmt, args); | |
437 va_end (args); | |
438 | |
439 throw execution_exception (); | |
440 } | |
441 | |
442 static void initialize_error_handlers (void) | |
443 { | |
444 set_liboctave_error_handler (lo_error_handler); | |
445 set_liboctave_error_with_id_handler (lo_error_with_id_handler); | |
446 set_liboctave_warning_handler (warning); | |
447 set_liboctave_warning_with_id_handler (warning_with_id); | |
448 } | |
449 | |
450 // Create an interpreter object and perform initialization up to the | |
451 // point of setting reading command history and setting the load | |
452 // path. | |
453 | |
454 interpreter::interpreter (application *app_context) | |
455 : m_app_context (app_context), | |
456 m_tmp_files (), | |
457 m_atexit_fcns (), | |
458 m_display_info (), | |
459 m_environment (), | |
460 m_settings (), | |
461 m_error_system (*this), | |
462 m_evaluator (*this), | |
463 m_help_system (*this), | |
464 m_input_system (*this), | |
465 m_output_system (*this), | |
466 m_history_system (*this), | |
467 m_dynamic_loader (*this), | |
468 m_load_path (*this), | |
469 m_load_save_system (*this), | |
470 m_type_info (), | |
471 m_symbol_table (*this), | |
472 m_stream_list (*this), | |
473 m_child_list (), | |
474 m_url_handle_manager (), | |
475 m_cdef_manager (*this), | |
476 m_gtk_manager (), | |
477 m_event_manager (*this), | |
478 m_gh_manager (nullptr), | |
479 m_interactive (false), | |
480 m_read_site_files (true), | |
481 m_read_init_files (m_app_context != nullptr), | |
482 m_verbose (false), | |
483 m_traditional (false), | |
484 m_inhibit_startup_message (false), | |
485 m_load_path_initialized (false), | |
486 m_history_initialized (false), | |
487 m_interrupt_all_in_process_group (true), | |
488 m_cancel_quit (false), | |
489 m_executing_finish_script (false), | |
490 m_executing_atexit (false), | |
491 m_initialized (false) | |
492 { | |
493 // FIXME: When thread_local storage is used by default, this message | |
494 // should change to say something like | |
495 // | |
496 // only one Octave interpreter may be active in any given thread | |
497 | |
498 if (m_instance) | |
499 throw std::runtime_error | |
500 ("only one Octave interpreter may be active"); | |
501 | |
502 m_instance = this; | |
503 | |
504 #if defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE) | |
505 // Force a UTF-8 locale on Windows if possible | |
506 std::setlocale (LC_ALL, ".UTF8"); | |
507 #else | |
508 std::setlocale (LC_ALL, ""); | |
509 #endif | |
510 // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting | |
511 std::setlocale (LC_NUMERIC, "C"); | |
512 std::setlocale (LC_TIME, "C"); | |
513 sys::env::putenv ("LC_NUMERIC", "C"); | |
514 sys::env::putenv ("LC_TIME", "C"); | |
515 | |
516 // Initialize the default floating point unit control state. | |
517 octave_set_default_fpucw (); | |
518 | |
519 thread::init (); | |
520 | |
521 octave_ieee_init (); | |
522 | |
523 initialize_xerbla_error_handler (); | |
524 | |
525 initialize_error_handlers (); | |
526 | |
527 if (m_app_context) | |
528 { | |
529 install_signal_handlers (); | |
530 octave_unblock_signal_by_name ("SIGTSTP"); | |
531 } | |
532 else | |
533 quit_allowed = false; | |
534 | |
535 if (! m_app_context) | |
536 m_display_info.initialize (); | |
537 | |
538 bool line_editing = false; | |
539 | |
540 if (m_app_context) | |
541 { | |
542 // Embedded interpreters don't execute command line options. | |
543 const cmdline_options& options = m_app_context->options (); | |
544 | |
545 // Make all command-line arguments available to startup files, | |
546 // including PKG_ADD files. | |
547 | |
548 string_vector args = options.all_args (); | |
549 | |
550 m_app_context->intern_argv (args); | |
551 intern_nargin (args.numel () - 1); | |
552 | |
553 bool is_octave_program = m_app_context->is_octave_program (); | |
554 | |
555 std::list<std::string> command_line_path = options.command_line_path (); | |
556 | |
557 for (const auto& pth : command_line_path) | |
558 m_load_path.set_command_line_path (pth); | |
559 | |
560 std::string exec_path = options.exec_path (); | |
561 if (! exec_path.empty ()) | |
562 m_environment.exec_path (exec_path); | |
563 | |
564 std::string image_path = options.image_path (); | |
565 if (! image_path.empty ()) | |
566 m_environment.image_path (image_path); | |
567 | |
568 if (! options.no_window_system ()) | |
569 m_display_info.initialize (); | |
570 | |
571 // Is input coming from a terminal? If so, we are probably | |
572 // interactive. | |
573 | |
574 // If stdin is not a tty, then we are reading commands from a | |
575 // pipe or a redirected file. | |
576 bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin)); | |
577 | |
578 m_interactive = (! is_octave_program && stdin_is_tty | |
579 && octave_isatty_wrapper (fileno (stdout))); | |
580 | |
581 // Don't force interactive if we're already interactive (bug #60696). | |
582 bool forced_interactive = options.forced_interactive (); | |
583 if (m_interactive) | |
584 { | |
585 m_app_context->forced_interactive (false); | |
586 forced_interactive = false; | |
587 } | |
588 | |
589 // Check if the user forced an interactive session. | |
590 if (forced_interactive) | |
591 m_interactive = true; | |
592 | |
593 line_editing = options.line_editing (); | |
594 if ((! m_interactive || forced_interactive) | |
595 && ! options.forced_line_editing ()) | |
596 line_editing = false; | |
597 | |
598 m_traditional = options.traditional (); | |
599 | |
600 // FIXME: if possible, perform the following actions directly | |
601 // instead of using the interpreter-level functions. | |
602 | |
603 if (options.echo_commands ()) | |
604 m_evaluator.echo | |
605 (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS | |
606 | tree_evaluator::ECHO_ALL); | |
607 | |
608 std::string docstrings_file = options.docstrings_file (); | |
609 if (! docstrings_file.empty ()) | |
610 Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file)); | |
611 | |
612 std::string doc_cache_file = options.doc_cache_file (); | |
613 if (! doc_cache_file.empty ()) | |
614 Fdoc_cache_file (*this, octave_value (doc_cache_file)); | |
615 | |
616 std::string info_file = options.info_file (); | |
617 if (! info_file.empty ()) | |
618 Finfo_file (*this, octave_value (info_file)); | |
619 | |
620 std::string info_program = options.info_program (); | |
621 if (! info_program.empty ()) | |
622 Finfo_program (*this, octave_value (info_program)); | |
623 | |
624 std::string texi_macros_file = options.texi_macros_file (); | |
625 if (! texi_macros_file.empty ()) | |
626 Ftexi_macros_file (*this, octave_value (texi_macros_file)); | |
627 } | |
628 | |
629 // FIXME: we defer creation of the gh_manager object because it | |
630 // creates a root_figure object that requires the display_info | |
631 // object, but that is currently only accessible through the global | |
632 // interpreter object and that is not available until after the | |
633 // interpreter::instance pointer is set (above). It would be better | |
634 // if m_gh_manager could be an object value instead of a pointer and | |
635 // created as part of the interpreter initialization. To do that, | |
636 // we should either make the display_info object independent of the | |
637 // interpreter object (does it really need to cache any | |
638 // information?) or defer creation of the root_figure object until | |
639 // it is actually needed. | |
640 m_gh_manager = new gh_manager (*this); | |
641 | |
642 m_input_system.initialize (line_editing); | |
643 | |
644 // These can come after command line args since none of them set any | |
645 // defaults that might be changed by command line options. | |
646 | |
647 initialize_version_info (); | |
648 | |
649 // This should be done before initializing the load path because | |
650 // some PKG_ADD files might need --traditional behavior. | |
651 | |
652 if (m_traditional) | |
653 maximum_braindamage (); | |
654 | |
655 octave_interpreter_ready = true; | |
656 } | |
657 | |
658 OCTAVE_THREAD_LOCAL interpreter *interpreter::m_instance = nullptr; | |
659 | |
660 interpreter::~interpreter (void) | |
661 { | |
662 if (! m_app_context) | |
663 shutdown (); | |
664 | |
665 delete m_gh_manager; | |
666 } | |
667 | |
668 void interpreter::intern_nargin (octave_idx_type nargs) | |
669 { | |
670 m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs); | |
671 } | |
672 | |
673 // Read the history file unless a command-line option inhibits that. | |
674 | |
675 void interpreter::initialize_history (bool read_history_file) | |
676 { | |
677 if (! m_history_initialized) | |
678 { | |
679 // Allow command-line option to override. | |
680 | |
681 if (m_app_context) | |
682 { | |
683 const cmdline_options& options = m_app_context->options (); | |
684 | |
685 read_history_file = options.read_history_file (); | |
686 | |
687 if (! read_history_file) | |
688 command_history::ignore_entries (); | |
689 } | |
690 | |
691 m_history_system.initialize (read_history_file); | |
692 | |
693 if (! m_app_context) | |
694 command_history::ignore_entries (); | |
695 | |
696 m_history_initialized = true; | |
697 } | |
698 } | |
699 | |
700 // Set the initial path to the system default unless command-line | |
701 // option says to leave it empty. | |
702 | |
703 void interpreter::initialize_load_path (bool set_initial_path) | |
704 { | |
705 if (! m_load_path_initialized) | |
706 { | |
707 // Allow command-line option to override. | |
708 | |
709 if (m_app_context) | |
710 { | |
711 const cmdline_options& options = m_app_context->options (); | |
712 | |
713 set_initial_path = options.set_initial_path (); | |
714 } | |
715 | |
716 // Temporarily set the execute_pkg_add function to one that | |
717 // catches exceptions. This is better than wrapping | |
718 // load_path::initialize in a try-catch block because it will | |
719 // not stop executing PKG_ADD files at the first exception. | |
720 // It's also better than changing the default execute_pkg_add | |
721 // function to use safe_source file because that will normally | |
722 // be evaluated from the normal interpreter loop where exceptions | |
723 // are already handled. | |
724 | |
725 unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path, | |
726 m_load_path.get_add_hook ()); | |
727 | |
728 m_load_path.set_add_hook ([=] (const std::string& dir) | |
729 { this->execute_pkg_add (dir); }); | |
730 | |
731 m_load_path.initialize (set_initial_path); | |
732 | |
733 m_load_path_initialized = true; | |
734 } | |
735 } | |
736 | |
737 // This may be called separately from execute | |
738 | |
739 void interpreter::initialize (void) | |
740 { | |
741 if (m_initialized) | |
742 return; | |
743 | |
744 if (m_app_context) | |
745 { | |
746 const cmdline_options& options = m_app_context->options (); | |
747 | |
748 if (options.experimental_terminal_widget ()) | |
749 { | |
750 if (! options.gui ()) | |
751 display_startup_message (); | |
752 } | |
753 else | |
754 display_startup_message (); | |
755 } | |
756 else | |
757 display_startup_message (); | |
758 | |
759 // Wait to read the history file until the interpreter reads input | |
760 // files and begins evaluating commands. | |
761 | |
762 initialize_history (); | |
763 | |
764 // Initializing the load path may execute PKG_ADD files, so can't be | |
765 // done until the interpreter is ready to execute commands. | |
766 | |
767 // Deferring it to the execute step also allows the path to be | |
768 // initialized between creating and execute the interpreter, for | |
769 // example, to set a custom path for an embedded interpreter. | |
770 | |
771 initialize_load_path (); | |
772 | |
773 octave_save_signal_mask (); | |
774 | |
775 can_interrupt = true; | |
776 | |
777 octave_signal_hook = respond_to_pending_signals; | |
778 octave_interrupt_hook = nullptr; | |
779 | |
780 catch_interrupts (); | |
781 | |
782 // FIXME: could we eliminate this variable or make it not be global? | |
783 // Global used to communicate with signal handler. | |
784 octave_initialized = true; | |
785 | |
786 m_initialized = true; | |
787 } | |
788 | |
789 // Note: this function is currently only used with the new | |
790 // experimental terminal widget. | |
791 | |
792 void interpreter::get_line_and_eval (void) | |
793 { | |
794 m_evaluator.get_line_and_eval (); | |
795 } | |
796 | |
797 // Note: the following class is currently only used with the new | |
798 // experimental terminal widget. | |
799 | |
800 class cli_input_reader | |
801 { | |
802 public: | |
803 | |
804 cli_input_reader (interpreter& interp) | |
805 : m_interpreter (interp), m_thread () { } | |
806 | |
807 cli_input_reader (const cli_input_reader&) = delete; | |
808 | |
809 cli_input_reader& operator = (const cli_input_reader&) = delete; | |
810 | |
811 ~cli_input_reader (void) | |
318 { | 812 { |
319 cleanup (); | 813 // FIXME: Would it be better to ensure that |
814 // interpreter::get_line_and_eval exits and then call | |
815 // m_thread.join () here? | |
816 | |
817 m_thread.detach (); | |
320 } | 818 } |
321 | 819 |
322 void temporary_file_list::insert (const std::string& file) | 820 void start (void) |
323 { | 821 { |
324 m_files.insert (file); | 822 m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter); |
325 } | 823 } |
326 | 824 |
327 void temporary_file_list::cleanup (void) | 825 private: |
328 { | 826 |
329 while (! m_files.empty ()) | 827 interpreter& m_interpreter; |
330 { | 828 |
331 auto it = m_files.begin (); | 829 std::thread m_thread; |
332 | 830 }; |
333 octave_unlink_wrapper (it->c_str ()); | 831 |
334 | 832 void interpreter::parse_and_execute (const std::string& input, |
335 m_files.erase (it); | 833 bool& incomplete_parse) |
336 } | 834 { |
337 } | 835 m_evaluator.parse_and_execute (input, incomplete_parse); |
338 | 836 } |
339 // The time we last time we changed directories. | 837 |
340 sys::time Vlast_chdir_time = 0.0; | 838 // FIXME: this function is intended to be executed only once. Should |
341 | 839 // we enforce that restriction? |
342 // Execute commands from a file and catch potential exceptions in a consistent | 840 |
343 // way. This function should be called anywhere we might parse and execute | 841 int interpreter::execute (void) |
344 // commands from a file before we have entered the main loop in | 842 { |
345 // toplev.cc. | 843 int exit_status = 0; |
346 | 844 |
347 static int safe_source_file (const std::string& file_name, | 845 try |
348 const std::string& context = "", | 846 { |
349 bool verbose = false, | 847 initialize (); |
350 bool require_file = true) | 848 |
351 { | 849 execute_startup_files (); |
352 interpreter& interp = __get_interpreter__ (); | 850 |
353 | 851 if (m_app_context) |
354 try | 852 { |
355 { | 853 const cmdline_options& options = m_app_context->options (); |
356 source_file (file_name, context, verbose, require_file); | 854 |
357 } | 855 if (m_app_context->have_eval_option_code ()) |
358 catch (const interrupt_exception&) | 856 { |
359 { | 857 int status = execute_eval_option_code (); |
360 interp.recover_from_exception (); | 858 |
361 | 859 if (status ) |
362 return 1; | 860 exit_status = status; |
363 } | 861 |
364 catch (const execution_exception& ee) | 862 if (! options.persist ()) |
365 { | 863 { |
366 interp.handle_exception (ee); | 864 shutdown (); |
367 | 865 |
368 return 1; | 866 return exit_status; |
369 } | 867 } |
370 | 868 } |
371 return 0; | 869 |
372 } | 870 // If there is an extra argument, see if it names a file to |
373 | 871 // read. Additional arguments are taken as command line options |
374 static void initialize_version_info (void) | 872 // for the script. |
375 { | 873 |
376 octave_value_list args; | 874 if (m_app_context->have_script_file ()) |
377 | 875 { |
378 args(3) = OCTAVE_RELEASE_DATE; | 876 int status = execute_command_line_file (); |
379 args(2) = config::release (); | 877 |
380 args(1) = OCTAVE_VERSION; | 878 if (status) |
381 args(0) = "GNU Octave"; | 879 exit_status = status; |
382 | 880 |
383 F__version_info__ (args, 0); | 881 if (! options.persist ()) |
384 } | 882 { |
385 | 883 shutdown (); |
386 static void xerbla_abort (void) | 884 |
387 { | 885 return exit_status; |
388 error ("Fortran procedure terminated by call to XERBLA"); | 886 } |
389 } | 887 } |
390 | 888 |
391 static void initialize_xerbla_error_handler (void) | 889 if (options.forced_interactive ()) |
392 { | 890 command_editor::blink_matching_paren (false); |
393 // The idea here is to force xerbla to be referenced so that we will | 891 |
394 // link to our own version instead of the one provided by the BLAS | 892 if (options.server ()) |
395 // library. But numeric_limits<double>::NaN () should never be -1, so | 893 exit_status = server_loop (); |
396 // we should never actually call xerbla. FIXME (again!): If this | 894 else if (options.experimental_terminal_widget ()) |
397 // becomes a constant expression the test might be optimized away and | 895 { |
398 // then the reference to the function might also disappear. | 896 if (options.gui ()) |
399 | 897 { |
400 if (numeric_limits<double>::NaN () == -1) | 898 m_event_manager.start_gui (true); |
401 F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6)); | 899 |
402 | 900 exit_status = server_loop (); |
403 typedef void (*xerbla_handler_ptr) (void); | 901 } |
404 | 902 else |
405 typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr); | 903 { |
406 | 904 // Use an object so that the thread started for the |
407 dynamic_library libs (""); | 905 // reader will be cleaned up no matter how we exit |
408 | 906 // this function. |
409 if (libs) | 907 |
410 { | 908 cli_input_reader reader (*this); |
411 octave_set_xerbla_handler_ptr octave_set_xerbla_handler | 909 |
412 = reinterpret_cast<octave_set_xerbla_handler_ptr> | 910 reader.start (); |
413 (libs.search ("octave_set_xerbla_handler")); | 911 |
414 | 912 exit_status = server_loop (); |
415 if (octave_set_xerbla_handler) | 913 } |
416 octave_set_xerbla_handler (xerbla_abort); | 914 } |
417 } | 915 else |
418 } | 916 exit_status = main_loop (); |
419 | 917 |
420 OCTAVE_NORETURN static void | 918 shutdown (); |
421 lo_error_handler (const char *fmt, ...) | 919 } |
422 { | 920 } |
423 va_list args; | 921 catch (const exit_exception& xe) |
424 va_start (args, fmt); | 922 { |
425 verror_with_cfn (fmt, args); | 923 exit_status = xe.exit_status (); |
426 va_end (args); | 924 |
427 | |
428 throw execution_exception (); | |
429 } | |
430 | |
431 OCTAVE_NORETURN static void | |
432 lo_error_with_id_handler (const char *id, const char *fmt, ...) | |
433 { | |
434 va_list args; | |
435 va_start (args, fmt); | |
436 verror_with_id_cfn (id, fmt, args); | |
437 va_end (args); | |
438 | |
439 throw execution_exception (); | |
440 } | |
441 | |
442 static void initialize_error_handlers (void) | |
443 { | |
444 set_liboctave_error_handler (lo_error_handler); | |
445 set_liboctave_error_with_id_handler (lo_error_with_id_handler); | |
446 set_liboctave_warning_handler (warning); | |
447 set_liboctave_warning_with_id_handler (warning_with_id); | |
448 } | |
449 | |
450 // Create an interpreter object and perform initialization up to the | |
451 // point of setting reading command history and setting the load | |
452 // path. | |
453 | |
454 interpreter::interpreter (application *app_context) | |
455 : m_app_context (app_context), | |
456 m_tmp_files (), | |
457 m_atexit_fcns (), | |
458 m_display_info (), | |
459 m_environment (), | |
460 m_settings (), | |
461 m_error_system (*this), | |
462 m_evaluator (*this), | |
463 m_help_system (*this), | |
464 m_input_system (*this), | |
465 m_output_system (*this), | |
466 m_history_system (*this), | |
467 m_dynamic_loader (*this), | |
468 m_load_path (*this), | |
469 m_load_save_system (*this), | |
470 m_type_info (), | |
471 m_symbol_table (*this), | |
472 m_stream_list (*this), | |
473 m_child_list (), | |
474 m_url_handle_manager (), | |
475 m_cdef_manager (*this), | |
476 m_gtk_manager (), | |
477 m_event_manager (*this), | |
478 m_gh_manager (nullptr), | |
479 m_interactive (false), | |
480 m_read_site_files (true), | |
481 m_read_init_files (m_app_context != nullptr), | |
482 m_verbose (false), | |
483 m_traditional (false), | |
484 m_inhibit_startup_message (false), | |
485 m_load_path_initialized (false), | |
486 m_history_initialized (false), | |
487 m_interrupt_all_in_process_group (true), | |
488 m_cancel_quit (false), | |
489 m_executing_finish_script (false), | |
490 m_executing_atexit (false), | |
491 m_initialized (false) | |
492 { | |
493 // FIXME: When thread_local storage is used by default, this message | |
494 // should change to say something like | |
495 // | |
496 // only one Octave interpreter may be active in any given thread | |
497 | |
498 if (m_instance) | |
499 throw std::runtime_error | |
500 ("only one Octave interpreter may be active"); | |
501 | |
502 m_instance = this; | |
503 | |
504 #if defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE) | |
505 // Force a UTF-8 locale on Windows if possible | |
506 std::setlocale (LC_ALL, ".UTF8"); | |
507 #else | |
508 std::setlocale (LC_ALL, ""); | |
509 #endif | |
510 // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting | |
511 std::setlocale (LC_NUMERIC, "C"); | |
512 std::setlocale (LC_TIME, "C"); | |
513 sys::env::putenv ("LC_NUMERIC", "C"); | |
514 sys::env::putenv ("LC_TIME", "C"); | |
515 | |
516 // Initialize the default floating point unit control state. | |
517 octave_set_default_fpucw (); | |
518 | |
519 thread::init (); | |
520 | |
521 octave_ieee_init (); | |
522 | |
523 initialize_xerbla_error_handler (); | |
524 | |
525 initialize_error_handlers (); | |
526 | |
527 if (m_app_context) | |
528 { | |
529 install_signal_handlers (); | |
530 octave_unblock_signal_by_name ("SIGTSTP"); | |
531 } | |
532 else | |
533 quit_allowed = false; | |
534 | |
535 if (! m_app_context) | |
536 m_display_info.initialize (); | |
537 | |
538 bool line_editing = false; | |
539 | |
540 if (m_app_context) | |
541 { | |
542 // Embedded interpreters don't execute command line options. | |
543 const cmdline_options& options = m_app_context->options (); | |
544 | |
545 // Make all command-line arguments available to startup files, | |
546 // including PKG_ADD files. | |
547 | |
548 string_vector args = options.all_args (); | |
549 | |
550 m_app_context->intern_argv (args); | |
551 intern_nargin (args.numel () - 1); | |
552 | |
553 bool is_octave_program = m_app_context->is_octave_program (); | |
554 | |
555 std::list<std::string> command_line_path = options.command_line_path (); | |
556 | |
557 for (const auto& pth : command_line_path) | |
558 m_load_path.set_command_line_path (pth); | |
559 | |
560 std::string exec_path = options.exec_path (); | |
561 if (! exec_path.empty ()) | |
562 m_environment.exec_path (exec_path); | |
563 | |
564 std::string image_path = options.image_path (); | |
565 if (! image_path.empty ()) | |
566 m_environment.image_path (image_path); | |
567 | |
568 if (! options.no_window_system ()) | |
569 m_display_info.initialize (); | |
570 | |
571 // Is input coming from a terminal? If so, we are probably | |
572 // interactive. | |
573 | |
574 // If stdin is not a tty, then we are reading commands from a | |
575 // pipe or a redirected file. | |
576 bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin)); | |
577 | |
578 m_interactive = (! is_octave_program && stdin_is_tty | |
579 && octave_isatty_wrapper (fileno (stdout))); | |
580 | |
581 // Don't force interactive if we're already interactive (bug #60696). | |
582 bool forced_interactive = options.forced_interactive (); | |
583 if (m_interactive) | |
584 { | |
585 m_app_context->forced_interactive (false); | |
586 forced_interactive = false; | |
587 } | |
588 | |
589 // Check if the user forced an interactive session. | |
590 if (forced_interactive) | |
591 m_interactive = true; | |
592 | |
593 line_editing = options.line_editing (); | |
594 if ((! m_interactive || forced_interactive) | |
595 && ! options.forced_line_editing ()) | |
596 line_editing = false; | |
597 | |
598 m_traditional = options.traditional (); | |
599 | |
600 // FIXME: if possible, perform the following actions directly | |
601 // instead of using the interpreter-level functions. | |
602 | |
603 if (options.echo_commands ()) | |
604 m_evaluator.echo | |
605 (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS | |
606 | tree_evaluator::ECHO_ALL); | |
607 | |
608 std::string docstrings_file = options.docstrings_file (); | |
609 if (! docstrings_file.empty ()) | |
610 Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file)); | |
611 | |
612 std::string doc_cache_file = options.doc_cache_file (); | |
613 if (! doc_cache_file.empty ()) | |
614 Fdoc_cache_file (*this, octave_value (doc_cache_file)); | |
615 | |
616 std::string info_file = options.info_file (); | |
617 if (! info_file.empty ()) | |
618 Finfo_file (*this, octave_value (info_file)); | |
619 | |
620 std::string info_program = options.info_program (); | |
621 if (! info_program.empty ()) | |
622 Finfo_program (*this, octave_value (info_program)); | |
623 | |
624 std::string texi_macros_file = options.texi_macros_file (); | |
625 if (! texi_macros_file.empty ()) | |
626 Ftexi_macros_file (*this, octave_value (texi_macros_file)); | |
627 } | |
628 | |
629 // FIXME: we defer creation of the gh_manager object because it | |
630 // creates a root_figure object that requires the display_info | |
631 // object, but that is currently only accessible through the global | |
632 // interpreter object and that is not available until after the | |
633 // interpreter::instance pointer is set (above). It would be better | |
634 // if m_gh_manager could be an object value instead of a pointer and | |
635 // created as part of the interpreter initialization. To do that, | |
636 // we should either make the display_info object independent of the | |
637 // interpreter object (does it really need to cache any | |
638 // information?) or defer creation of the root_figure object until | |
639 // it is actually needed. | |
640 m_gh_manager = new gh_manager (*this); | |
641 | |
642 m_input_system.initialize (line_editing); | |
643 | |
644 // These can come after command line args since none of them set any | |
645 // defaults that might be changed by command line options. | |
646 | |
647 initialize_version_info (); | |
648 | |
649 // This should be done before initializing the load path because | |
650 // some PKG_ADD files might need --traditional behavior. | |
651 | |
652 if (m_traditional) | |
653 maximum_braindamage (); | |
654 | |
655 octave_interpreter_ready = true; | |
656 } | |
657 | |
658 OCTAVE_THREAD_LOCAL interpreter *interpreter::m_instance = nullptr; | |
659 | |
660 interpreter::~interpreter (void) | |
661 { | |
662 if (! m_app_context) | |
663 shutdown (); | 925 shutdown (); |
664 | 926 } |
665 delete m_gh_manager; | 927 |
666 } | 928 return exit_status; |
667 | 929 } |
668 void interpreter::intern_nargin (octave_idx_type nargs) | 930 |
669 { | 931 // Call a function with exceptions handled to avoid problems with |
670 m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs); | 932 // errors while shutting down. |
671 } | |
672 | |
673 // Read the history file unless a command-line option inhibits that. | |
674 | |
675 void interpreter::initialize_history (bool read_history_file) | |
676 { | |
677 if (! m_history_initialized) | |
678 { | |
679 // Allow command-line option to override. | |
680 | |
681 if (m_app_context) | |
682 { | |
683 const cmdline_options& options = m_app_context->options (); | |
684 | |
685 read_history_file = options.read_history_file (); | |
686 | |
687 if (! read_history_file) | |
688 command_history::ignore_entries (); | |
689 } | |
690 | |
691 m_history_system.initialize (read_history_file); | |
692 | |
693 if (! m_app_context) | |
694 command_history::ignore_entries (); | |
695 | |
696 m_history_initialized = true; | |
697 } | |
698 } | |
699 | |
700 // Set the initial path to the system default unless command-line | |
701 // option says to leave it empty. | |
702 | |
703 void interpreter::initialize_load_path (bool set_initial_path) | |
704 { | |
705 if (! m_load_path_initialized) | |
706 { | |
707 // Allow command-line option to override. | |
708 | |
709 if (m_app_context) | |
710 { | |
711 const cmdline_options& options = m_app_context->options (); | |
712 | |
713 set_initial_path = options.set_initial_path (); | |
714 } | |
715 | |
716 // Temporarily set the execute_pkg_add function to one that | |
717 // catches exceptions. This is better than wrapping | |
718 // load_path::initialize in a try-catch block because it will | |
719 // not stop executing PKG_ADD files at the first exception. | |
720 // It's also better than changing the default execute_pkg_add | |
721 // function to use safe_source file because that will normally | |
722 // be evaluated from the normal interpreter loop where exceptions | |
723 // are already handled. | |
724 | |
725 unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path, | |
726 m_load_path.get_add_hook ()); | |
727 | |
728 m_load_path.set_add_hook ([=] (const std::string& dir) | |
729 { this->execute_pkg_add (dir); }); | |
730 | |
731 m_load_path.initialize (set_initial_path); | |
732 | |
733 m_load_path_initialized = true; | |
734 } | |
735 } | |
736 | |
737 // This may be called separately from execute | |
738 | |
739 void interpreter::initialize (void) | |
740 { | |
741 if (m_initialized) | |
742 return; | |
743 | |
744 if (m_app_context) | |
745 { | |
746 const cmdline_options& options = m_app_context->options (); | |
747 | |
748 if (options.experimental_terminal_widget ()) | |
749 { | |
750 if (! options.gui ()) | |
751 display_startup_message (); | |
752 } | |
753 else | |
754 display_startup_message (); | |
755 } | |
756 else | |
757 display_startup_message (); | |
758 | |
759 // Wait to read the history file until the interpreter reads input | |
760 // files and begins evaluating commands. | |
761 | |
762 initialize_history (); | |
763 | |
764 // Initializing the load path may execute PKG_ADD files, so can't be | |
765 // done until the interpreter is ready to execute commands. | |
766 | |
767 // Deferring it to the execute step also allows the path to be | |
768 // initialized between creating and execute the interpreter, for | |
769 // example, to set a custom path for an embedded interpreter. | |
770 | |
771 initialize_load_path (); | |
772 | |
773 octave_save_signal_mask (); | |
774 | |
775 can_interrupt = true; | |
776 | |
777 octave_signal_hook = respond_to_pending_signals; | |
778 octave_interrupt_hook = nullptr; | |
779 | |
780 catch_interrupts (); | |
781 | |
782 // FIXME: could we eliminate this variable or make it not be global? | |
783 // Global used to communicate with signal handler. | |
784 octave_initialized = true; | |
785 | |
786 m_initialized = true; | |
787 } | |
788 | |
789 // Note: this function is currently only used with the new | |
790 // experimental terminal widget. | |
791 | |
792 void interpreter::get_line_and_eval (void) | |
793 { | |
794 m_evaluator.get_line_and_eval (); | |
795 } | |
796 | |
797 // Note: the following class is currently only used with the new | |
798 // experimental terminal widget. | |
799 | |
800 class cli_input_reader | |
801 { | |
802 public: | |
803 | |
804 cli_input_reader (interpreter& interp) | |
805 : m_interpreter (interp), m_thread () { } | |
806 | |
807 cli_input_reader (const cli_input_reader&) = delete; | |
808 | |
809 cli_input_reader& operator = (const cli_input_reader&) = delete; | |
810 | |
811 ~cli_input_reader (void) | |
812 { | |
813 // FIXME: Would it be better to ensure that | |
814 // interpreter::get_line_and_eval exits and then call | |
815 // m_thread.join () here? | |
816 | |
817 m_thread.detach (); | |
818 } | |
819 | |
820 void start (void) | |
821 { | |
822 m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter); | |
823 } | |
824 | |
825 private: | |
826 | |
827 interpreter& m_interpreter; | |
828 | |
829 std::thread m_thread; | |
830 }; | |
831 | |
832 void interpreter::parse_and_execute (const std::string& input, | |
833 bool& incomplete_parse) | |
834 { | |
835 m_evaluator.parse_and_execute (input, incomplete_parse); | |
836 } | |
837 | |
838 // FIXME: this function is intended to be executed only once. Should | |
839 // we enforce that restriction? | |
840 | |
841 int interpreter::execute (void) | |
842 { | |
843 int exit_status = 0; | |
844 | |
845 try | |
846 { | |
847 initialize (); | |
848 | |
849 execute_startup_files (); | |
850 | |
851 if (m_app_context) | |
852 { | |
853 const cmdline_options& options = m_app_context->options (); | |
854 | |
855 if (m_app_context->have_eval_option_code ()) | |
856 { | |
857 int status = execute_eval_option_code (); | |
858 | |
859 if (status ) | |
860 exit_status = status; | |
861 | |
862 if (! options.persist ()) | |
863 { | |
864 shutdown (); | |
865 | |
866 return exit_status; | |
867 } | |
868 } | |
869 | |
870 // If there is an extra argument, see if it names a file to | |
871 // read. Additional arguments are taken as command line options | |
872 // for the script. | |
873 | |
874 if (m_app_context->have_script_file ()) | |
875 { | |
876 int status = execute_command_line_file (); | |
877 | |
878 if (status) | |
879 exit_status = status; | |
880 | |
881 if (! options.persist ()) | |
882 { | |
883 shutdown (); | |
884 | |
885 return exit_status; | |
886 } | |
887 } | |
888 | |
889 if (options.forced_interactive ()) | |
890 command_editor::blink_matching_paren (false); | |
891 | |
892 if (options.server ()) | |
893 exit_status = server_loop (); | |
894 else if (options.experimental_terminal_widget ()) | |
895 { | |
896 if (options.gui ()) | |
897 { | |
898 m_event_manager.start_gui (true); | |
899 | |
900 exit_status = server_loop (); | |
901 } | |
902 else | |
903 { | |
904 // Use an object so that the thread started for the | |
905 // reader will be cleaned up no matter how we exit | |
906 // this function. | |
907 | |
908 cli_input_reader reader (*this); | |
909 | |
910 reader.start (); | |
911 | |
912 exit_status = server_loop (); | |
913 } | |
914 } | |
915 else | |
916 exit_status = main_loop (); | |
917 | |
918 shutdown (); | |
919 } | |
920 } | |
921 catch (const exit_exception& xe) | |
922 { | |
923 exit_status = xe.exit_status (); | |
924 | |
925 shutdown (); | |
926 } | |
927 | |
928 return exit_status; | |
929 } | |
930 | |
931 // Call a function with exceptions handled to avoid problems with | |
932 // errors while shutting down. | |
933 | 933 |
934 #define OCTAVE_IGNORE_EXCEPTION(E) \ | 934 #define OCTAVE_IGNORE_EXCEPTION(E) \ |
935 catch (E) \ | 935 catch (E) \ |
936 { \ | 936 { \ |
937 recover_from_exception (); \ | 937 recover_from_exception (); \ |
963 OCTAVE_IGNORE_EXCEPTION (const execution_exception&) \ | 963 OCTAVE_IGNORE_EXCEPTION (const execution_exception&) \ |
964 OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&) \ | 964 OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&) \ |
965 } \ | 965 } \ |
966 while (0) | 966 while (0) |
967 | 967 |
968 void interpreter::shutdown (void) | 968 void interpreter::shutdown (void) |
969 { | 969 { |
970 // Attempt to prevent more than one call to shutdown. | 970 // Attempt to prevent more than one call to shutdown. |
971 | 971 |
972 if (! m_initialized) | 972 if (! m_initialized) |
973 return; | 973 return; |
974 | 974 |
975 m_initialized = false; | 975 m_initialized = false; |
976 | 976 |
977 OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); | 977 OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); |
978 | 978 |
979 // Any atexit functions added after this function call won't be | 979 // Any atexit functions added after this function call won't be |
980 // executed. Each atexit function is executed with | 980 // executed. Each atexit function is executed with |
981 // OCTAVE_SAFE_CALL, so we don't need that here. | 981 // OCTAVE_SAFE_CALL, so we don't need that here. |
982 | 982 |
983 execute_atexit_fcns (); | 983 execute_atexit_fcns (); |
984 | 984 |
985 // Clear all functions and variables while the event manager is | 985 // Clear all functions and variables while the event manager is |
986 // still processing events and notify the event manager. This way, | 986 // still processing events and notify the event manager. This way, |
987 // the workspace model will be cleared before the GUI exits. | 987 // the workspace model will be cleared before the GUI exits. |
988 | 988 |
989 // FIXME: This approach seems a bit fragile since there could be | 989 // FIXME: This approach seems a bit fragile since there could be |
990 // other places in the GUI that have references to interpreter | 990 // other places in the GUI that have references to interpreter |
991 // objects. How can we reliably ensure that they are all removed | 991 // objects. How can we reliably ensure that they are all removed |
992 // before the interpreter exits? Maybe the best solution is to | 992 // before the interpreter exits? Maybe the best solution is to |
993 // always start the GUI from the interpreter and close it when the | 993 // always start the GUI from the interpreter and close it when the |
994 // interpreter exits? However, the workspace model is owned by the | 994 // interpreter exits? However, the workspace model is owned by the |
995 // base_qobject object not the workspace viewer or the main window, | 995 // base_qobject object not the workspace viewer or the main window, |
996 // so simply closing the GUI window(s) is not sufficient. See also | 996 // so simply closing the GUI window(s) is not sufficient. See also |
997 // bug #61994. | 997 // bug #61994. |
998 | 998 |
999 // Note that we don't force symbols to be cleared, so we will | 999 // Note that we don't force symbols to be cleared, so we will |
1000 // respect mlock at this point. Later, we'll force all variables | 1000 // respect mlock at this point. Later, we'll force all variables |
1001 // and functions to be cleared. | 1001 // and functions to be cleared. |
1002 | 1002 |
1003 OCTAVE_SAFE_CALL (clear_all, ()); | 1003 OCTAVE_SAFE_CALL (clear_all, ()); |
1004 OCTAVE_SAFE_CALL (m_event_manager.clear_workspace, ()); | 1004 OCTAVE_SAFE_CALL (m_event_manager.clear_workspace, ()); |
1005 | 1005 |
1006 // If we are attached to a GUI, queue and event to close it (only | 1006 // If we are attached to a GUI, queue and event to close it (only |
1007 // works with the new terminal widget), process pending events and | 1007 // works with the new terminal widget), process pending events and |
1008 // disable the link. | 1008 // disable the link. |
1009 | 1009 |
1010 OCTAVE_SAFE_CALL (m_event_manager.close_gui, ()); | 1010 OCTAVE_SAFE_CALL (m_event_manager.close_gui, ()); |
1011 OCTAVE_SAFE_CALL (m_event_manager.process_events, (true)); | 1011 OCTAVE_SAFE_CALL (m_event_manager.process_events, (true)); |
1012 OCTAVE_SAFE_CALL (m_event_manager.disable, ()); | 1012 OCTAVE_SAFE_CALL (m_event_manager.disable, ()); |
1013 | 1013 |
1014 OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ()); | 1014 OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ()); |
1015 | 1015 |
1016 // We may still have some figures. Close them. | 1016 // We may still have some figures. Close them. |
1017 | 1017 |
1018 OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); | 1018 OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); |
1019 | 1019 |
1020 // What is supposed to happen if a figure has a closerequestfcn or | 1020 // What is supposed to happen if a figure has a closerequestfcn or |
1021 // deletefcn callback registered that creates other figures or | 1021 // deletefcn callback registered that creates other figures or |
1022 // variables? What if those variables are classdef objects with | 1022 // variables? What if those variables are classdef objects with |
1023 // destructors that can create figures? The possibilities are | 1023 // destructors that can create figures? The possibilities are |
1024 // endless. At some point, we have to give up and force execution | 1024 // endless. At some point, we have to give up and force execution |
1025 // to end. | 1025 // to end. |
1026 | 1026 |
1027 // Note that we again don't force symbols to be cleared, so we | 1027 // Note that we again don't force symbols to be cleared, so we |
1028 // continue to respect mlock here. Later, we'll force all variables | 1028 // continue to respect mlock here. Later, we'll force all variables |
1029 // and functions to be cleared. | 1029 // and functions to be cleared. |
1030 | 1030 |
1031 OCTAVE_SAFE_CALL (clear_all, ()); | 1031 OCTAVE_SAFE_CALL (clear_all, ()); |
1032 | 1032 |
1033 // Do this explicitly so that destructors for mex file objects | 1033 // Do this explicitly so that destructors for mex file objects |
1034 // are called, so that functions registered with mexAtExit are | 1034 // are called, so that functions registered with mexAtExit are |
1035 // called. | 1035 // called. |
1036 | 1036 |
1037 OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ()); | 1037 OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ()); |
1038 | 1038 |
1039 OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ()); | 1039 OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ()); |
1040 | 1040 |
1041 OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ()); | 1041 OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ()); |
1042 | 1042 |
1043 if (! command_history::ignoring_entries ()) | 1043 if (! command_history::ignoring_entries ()) |
1044 OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ()); | 1044 OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ()); |
1045 | 1045 |
1046 OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ()); | 1046 OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ()); |
1047 | 1047 |
1048 // Now that the graphics toolkits have been unloaded, force all | 1048 // Now that the graphics toolkits have been unloaded, force all |
1049 // symbols to be cleared. | 1049 // symbols to be cleared. |
1050 | 1050 |
1051 OCTAVE_SAFE_CALL (clear_all, (true)); | 1051 OCTAVE_SAFE_CALL (clear_all, (true)); |
1052 | 1052 |
1053 // FIXME: May still need something like this to ensure that | 1053 // FIXME: May still need something like this to ensure that |
1054 // destructors for class objects will run properly. Should that be | 1054 // destructors for class objects will run properly. Should that be |
1055 // done earlier? Before or after atexit functions are executed? | 1055 // done earlier? Before or after atexit functions are executed? |
1056 // What will happen if the destructor for an obect attempts to | 1056 // What will happen if the destructor for an obect attempts to |
1057 // display a figure? | 1057 // display a figure? |
1058 | 1058 |
1059 OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ()); | 1059 OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ()); |
1060 | 1060 |
1061 OCTAVE_SAFE_CALL (sysdep_cleanup, ()); | 1061 OCTAVE_SAFE_CALL (sysdep_cleanup, ()); |
1062 | 1062 |
1063 OCTAVE_SAFE_CALL (flush_stdout, ()); | 1063 OCTAVE_SAFE_CALL (flush_stdout, ()); |
1064 | 1064 |
1065 // Don't call singleton_cleanup_list::cleanup until we have the | 1065 // Don't call singleton_cleanup_list::cleanup until we have the |
1066 // problems with registering/unregistering types worked out. For | 1066 // problems with registering/unregistering types worked out. For |
1067 // example, uncomment the following line, then use the make_int | 1067 // example, uncomment the following line, then use the make_int |
1068 // function from the examples directory to create an integer | 1068 // function from the examples directory to create an integer |
1069 // object and then exit Octave. Octave should crash with a | 1069 // object and then exit Octave. Octave should crash with a |
1070 // segfault when cleaning up the typinfo singleton. We need some | 1070 // segfault when cleaning up the typinfo singleton. We need some |
1071 // way to force new octave_value_X types that are created in | 1071 // way to force new octave_value_X types that are created in |
1072 // .oct files to be unregistered when the .oct file shared library | 1072 // .oct files to be unregistered when the .oct file shared library |
1073 // is unloaded. | 1073 // is unloaded. |
1074 // | 1074 // |
1075 // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); | 1075 // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); |
1076 } | 1076 } |
1077 | 1077 |
1078 void interpreter::execute_atexit_fcns (void) | 1078 void interpreter::execute_atexit_fcns (void) |
1079 { | 1079 { |
1080 // Prevent atexit functions from adding new functions to the list. | 1080 // Prevent atexit functions from adding new functions to the list. |
1081 m_executing_atexit = true; | 1081 m_executing_atexit = true; |
1082 | 1082 |
1083 while (! m_atexit_fcns.empty ()) | 1083 while (! m_atexit_fcns.empty ()) |
1084 { | 1084 { |
1085 std::string fcn = m_atexit_fcns.front (); | 1085 std::string fcn = m_atexit_fcns.front (); |
1086 | 1086 |
1087 m_atexit_fcns.pop_front (); | 1087 m_atexit_fcns.pop_front (); |
1088 | 1088 |
1089 OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0)); | 1089 OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0)); |
1090 | 1090 |
1091 OCTAVE_SAFE_CALL (flush_stdout, ()); | 1091 OCTAVE_SAFE_CALL (flush_stdout, ()); |
1092 } | 1092 } |
1093 } | 1093 } |
1094 | 1094 |
1095 void interpreter::display_startup_message (void) const | 1095 void interpreter::display_startup_message (void) const |
1096 { | 1096 { |
1097 bool inhibit_startup_message = false; | 1097 bool inhibit_startup_message = false; |
1098 | 1098 |
1099 if (m_app_context) | 1099 if (m_app_context) |
1100 { | 1100 { |
1101 const cmdline_options& options = m_app_context->options (); | 1101 const cmdline_options& options = m_app_context->options (); |
1102 | 1102 |
1103 inhibit_startup_message = options.inhibit_startup_message (); | 1103 inhibit_startup_message = options.inhibit_startup_message (); |
1104 } | 1104 } |
1105 | 1105 |
1106 if (m_interactive && ! inhibit_startup_message) | 1106 if (m_interactive && ! inhibit_startup_message) |
1107 std::cout << octave_startup_message () << "\n" << std::endl; | 1107 std::cout << octave_startup_message () << "\n" << std::endl; |
1108 } | 1108 } |
1109 | 1109 |
1110 // Initialize by reading startup files. Return non-zero if an exception | 1110 // Initialize by reading startup files. Return non-zero if an exception |
1111 // occurs when reading any of them, but don't exit early because of an | 1111 // occurs when reading any of them, but don't exit early because of an |
1112 // exception. | 1112 // exception. |
1113 | 1113 |
1114 int interpreter::execute_startup_files (void) | 1114 int interpreter::execute_startup_files (void) |
1115 { | 1115 { |
1116 bool read_site_files = m_read_site_files; | 1116 bool read_site_files = m_read_site_files; |
1117 bool read_init_files = m_read_init_files; | 1117 bool read_init_files = m_read_init_files; |
1118 bool verbose = m_verbose; | 1118 bool verbose = m_verbose; |
1119 bool inhibit_startup_message = m_inhibit_startup_message; | 1119 bool inhibit_startup_message = m_inhibit_startup_message; |
1120 | 1120 |
1121 if (m_app_context) | 1121 if (m_app_context) |
1122 { | 1122 { |
1123 const cmdline_options& options = m_app_context->options (); | 1123 const cmdline_options& options = m_app_context->options (); |
1124 | 1124 |
1125 read_site_files = options.read_site_files (); | 1125 read_site_files = options.read_site_files (); |
1126 read_init_files = options.read_init_files (); | 1126 read_init_files = options.read_init_files (); |
1127 verbose = options.verbose_flag (); | 1127 verbose = options.verbose_flag (); |
1128 inhibit_startup_message = options.inhibit_startup_message (); | 1128 inhibit_startup_message = options.inhibit_startup_message (); |
1129 } | 1129 } |
1130 | 1130 |
1131 verbose = (verbose && ! inhibit_startup_message); | 1131 verbose = (verbose && ! inhibit_startup_message); |
1132 | 1132 |
1133 bool require_file = false; | 1133 bool require_file = false; |
1134 | 1134 |
1135 std::string context; | 1135 std::string context; |
1136 | 1136 |
1137 int exit_status = 0; | 1137 int exit_status = 0; |
1138 | 1138 |
1139 if (read_site_files) | 1139 if (read_site_files) |
1140 { | 1140 { |
1141 // Execute commands from the site-wide configuration file. | 1141 // Execute commands from the site-wide configuration file. |
1142 // First from the file $(prefix)/lib/octave/site/m/octaverc | 1142 // First from the file $(prefix)/lib/octave/site/m/octaverc |
1143 // (if it exists), then from the file | 1143 // (if it exists), then from the file |
1144 // $(prefix)/share/octave/$(version)/m/octaverc (if it exists). | 1144 // $(prefix)/share/octave/$(version)/m/octaverc (if it exists). |
1145 | 1145 |
1146 int status = safe_source_file (config::local_site_defaults_file (), | 1146 int status = safe_source_file (config::local_site_defaults_file (), |
1147 context, verbose, require_file); | 1147 context, verbose, require_file); |
1148 | 1148 |
1149 if (status) | 1149 if (status) |
1150 exit_status = status; | 1150 exit_status = status; |
1151 | 1151 |
1152 status = safe_source_file (config::site_defaults_file (), | 1152 status = safe_source_file (config::site_defaults_file (), |
1153 context, verbose, require_file); | 1153 context, verbose, require_file); |
1154 | 1154 |
1155 if (status) | 1155 if (status) |
1156 exit_status = status; | 1156 exit_status = status; |
1157 } | 1157 } |
1158 | 1158 |
1159 if (read_init_files) | 1159 if (read_init_files) |
1160 { | 1160 { |
1161 // Try to execute commands from the Matlab compatible startup.m file | 1161 // Try to execute commands from the Matlab compatible startup.m file |
1162 // if it exists anywhere in the load path when starting Octave. | 1162 // if it exists anywhere in the load path when starting Octave. |
1163 std::string ff_startup_m = file_in_path ("startup.m", ""); | 1163 std::string ff_startup_m = file_in_path ("startup.m", ""); |
1164 | 1164 |
1165 if (! ff_startup_m.empty ()) | 1165 if (! ff_startup_m.empty ()) |
1166 { | 1166 { |
1167 int parse_status = 0; | 1167 int parse_status = 0; |
1168 | 1168 |
1169 try | 1169 try |
1170 { | 1170 { |
1171 eval_string (std::string ("startup"), false, parse_status, 0); | 1171 eval_string (std::string ("startup"), false, parse_status, 0); |
1172 } | 1172 } |
1173 catch (const interrupt_exception&) | 1173 catch (const interrupt_exception&) |
1174 { | 1174 { |
1175 recover_from_exception (); | 1175 recover_from_exception (); |
1176 } | 1176 } |
1177 catch (const execution_exception& ee) | 1177 catch (const execution_exception& ee) |
1178 { | 1178 { |
1179 handle_exception (ee); | 1179 handle_exception (ee); |
1180 } | 1180 } |
1181 } | 1181 } |
1182 | 1182 |
1183 // Try to execute commands from $CONFIG/octave/octaverc, where | 1183 // Try to execute commands from $CONFIG/octave/octaverc, where |
1184 // $CONFIG is the platform-dependent location for user local | 1184 // $CONFIG is the platform-dependent location for user local |
1185 // configuration files. | 1185 // configuration files. |
1186 | 1186 |
1187 std::string user_config_dir = sys::env::get_user_config_directory (); | 1187 std::string user_config_dir = sys::env::get_user_config_directory (); |
1188 | 1188 |
1189 std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str () | 1189 std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str () |
1190 + "octave"; | 1190 + "octave"; |
1191 | 1191 |
1192 std::string cfg_rc = sys::env::make_absolute ("octaverc", cfg_dir); | 1192 std::string cfg_rc = sys::env::make_absolute ("octaverc", cfg_dir); |
1193 | 1193 |
1194 if (! cfg_rc.empty ()) | 1194 if (! cfg_rc.empty ()) |
1195 { | 1195 { |
1196 int status = safe_source_file (cfg_rc, context, verbose, | 1196 int status = safe_source_file (cfg_rc, context, verbose, |
1197 require_file); | 1197 require_file); |
1198 | 1198 |
1199 if (status) | 1199 if (status) |
1200 exit_status = status; | 1200 exit_status = status; |
1201 } | 1201 } |
1202 | 1202 |
1203 // Try to execute commands from $HOME/$OCTAVE_INITFILE and | 1203 // Try to execute commands from $HOME/$OCTAVE_INITFILE and |
1204 // $OCTAVE_INITFILE. If $OCTAVE_INITFILE is not set, | 1204 // $OCTAVE_INITFILE. If $OCTAVE_INITFILE is not set, |
1205 // .octaverc is assumed. | 1205 // .octaverc is assumed. |
1206 | 1206 |
1207 bool home_rc_already_executed = false; | 1207 bool home_rc_already_executed = false; |
1208 | 1208 |
1209 std::string initfile = sys::env::getenv ("OCTAVE_INITFILE"); | 1209 std::string initfile = sys::env::getenv ("OCTAVE_INITFILE"); |
1210 | 1210 |
1211 if (initfile.empty ()) | 1211 if (initfile.empty ()) |
1212 initfile = ".octaverc"; | 1212 initfile = ".octaverc"; |
1213 | 1213 |
1214 std::string home_dir = sys::env::get_home_directory (); | 1214 std::string home_dir = sys::env::get_home_directory (); |
1215 | 1215 |
1216 std::string home_rc = sys::env::make_absolute (initfile, home_dir); | 1216 std::string home_rc = sys::env::make_absolute (initfile, home_dir); |
1217 | 1217 |
1218 std::string local_rc; | 1218 std::string local_rc; |
1219 | 1219 |
1220 if (! home_rc.empty ()) | 1220 if (! home_rc.empty ()) |
1221 { | 1221 { |
1222 int status = safe_source_file (home_rc, context, verbose, | 1222 int status = safe_source_file (home_rc, context, verbose, |
1223 require_file); | 1223 require_file); |
1224 | 1224 |
1225 if (status) | 1225 if (status) |
1226 exit_status = status; | 1226 exit_status = status; |
1227 | 1227 |
1228 // Names alone are not enough. | 1228 // Names alone are not enough. |
1229 | 1229 |
1230 sys::file_stat fs_home_rc (home_rc); | 1230 sys::file_stat fs_home_rc (home_rc); |
1231 | 1231 |
1232 if (fs_home_rc) | 1232 if (fs_home_rc) |
1233 { | 1233 { |
1234 // We want to check for curr_dir after executing home_rc | 1234 // We want to check for curr_dir after executing home_rc |
1235 // because doing that may change the working directory. | 1235 // because doing that may change the working directory. |
1236 | 1236 |
1237 local_rc = sys::env::make_absolute (initfile); | |
1238 | |
1239 home_rc_already_executed = same_file (home_rc, local_rc); | |
1240 } | |
1241 } | |
1242 | |
1243 if (! home_rc_already_executed) | |
1244 { | |
1245 if (local_rc.empty ()) | |
1246 local_rc = sys::env::make_absolute (initfile); | 1237 local_rc = sys::env::make_absolute (initfile); |
1247 | 1238 |
1248 int status = safe_source_file (local_rc, context, verbose, | 1239 home_rc_already_executed = same_file (home_rc, local_rc); |
1249 require_file); | 1240 } |
1250 | 1241 } |
1251 if (status) | 1242 |
1252 exit_status = status; | 1243 if (! home_rc_already_executed) |
1253 } | 1244 { |
1254 } | 1245 if (local_rc.empty ()) |
1255 | 1246 local_rc = sys::env::make_absolute (initfile); |
1256 if (m_interactive && verbose) | 1247 |
1257 std::cout << std::endl; | 1248 int status = safe_source_file (local_rc, context, verbose, |
1258 | 1249 require_file); |
1259 return exit_status; | 1250 |
1260 } | 1251 if (status) |
1261 | 1252 exit_status = status; |
1262 // Execute any code specified with --eval 'CODE' | 1253 } |
1263 | 1254 } |
1264 int interpreter::execute_eval_option_code (void) | 1255 |
1265 { | 1256 if (m_interactive && verbose) |
1266 if (! m_app_context) | 1257 std::cout << std::endl; |
1267 return 0; | 1258 |
1268 | 1259 return exit_status; |
1269 const cmdline_options& options = m_app_context->options (); | 1260 } |
1270 | 1261 |
1271 std::string code_to_eval = options.code_to_eval (); | 1262 // Execute any code specified with --eval 'CODE' |
1272 | 1263 |
1273 unwind_protect_var<bool> upv (m_interactive, false); | 1264 int interpreter::execute_eval_option_code (void) |
1274 | 1265 { |
1275 int parse_status = 0; | 1266 if (! m_app_context) |
1276 | 1267 return 0; |
1277 try | 1268 |
1278 { | 1269 const cmdline_options& options = m_app_context->options (); |
1279 eval_string (code_to_eval, false, parse_status, 0); | 1270 |
1280 } | 1271 std::string code_to_eval = options.code_to_eval (); |
1281 catch (const interrupt_exception&) | 1272 |
1282 { | 1273 unwind_protect_var<bool> upv (m_interactive, false); |
1283 recover_from_exception (); | 1274 |
1284 | 1275 int parse_status = 0; |
1285 return 1; | 1276 |
1286 } | 1277 try |
1287 catch (const execution_exception& ee) | 1278 { |
1288 { | 1279 eval_string (code_to_eval, false, parse_status, 0); |
1289 handle_exception (ee); | 1280 } |
1290 | 1281 catch (const interrupt_exception&) |
1291 return 1; | 1282 { |
1292 } | 1283 recover_from_exception (); |
1293 | 1284 |
1294 return parse_status; | 1285 return 1; |
1295 } | 1286 } |
1296 | 1287 catch (const execution_exception& ee) |
1297 int interpreter::execute_command_line_file (void) | 1288 { |
1298 { | 1289 handle_exception (ee); |
1299 if (! m_app_context) | 1290 |
1300 return 0; | 1291 return 1; |
1301 | 1292 } |
1302 const cmdline_options& options = m_app_context->options (); | 1293 |
1303 | 1294 return parse_status; |
1304 string_vector args = options.all_args (); | 1295 } |
1305 | 1296 |
1306 void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive; | 1297 int interpreter::execute_command_line_file (void) |
1307 unwind_action restore_interactive (interactive_fptr, this, m_interactive); | 1298 { |
1308 | 1299 if (! m_app_context) |
1309 unwind_action restore_argv (&application::intern_argv, m_app_context, args); | 1300 return 0; |
1310 | 1301 |
1311 unwind_action restore_nargin (&interpreter::intern_nargin, this, | 1302 const cmdline_options& options = m_app_context->options (); |
1312 args.numel () - 1); | 1303 |
1313 | 1304 string_vector args = options.all_args (); |
1314 void (application::*program_invocation_name_fptr) (const std::string&) | 1305 |
1315 = &application::program_invocation_name; | 1306 void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive; |
1316 unwind_action restore_program_invocation_name | 1307 unwind_action restore_interactive (interactive_fptr, this, m_interactive); |
1317 (program_invocation_name_fptr, m_app_context, | 1308 |
1318 application::program_invocation_name ()); | 1309 unwind_action restore_argv (&application::intern_argv, m_app_context, args); |
1319 | 1310 |
1320 void (application::*program_name_fptr) (const std::string&) | 1311 unwind_action restore_nargin (&interpreter::intern_nargin, this, |
1321 = &application::program_name; | 1312 args.numel () - 1); |
1322 unwind_action restore_program_name | 1313 |
1323 (program_name_fptr, m_app_context, application::program_name ()); | 1314 void (application::*program_invocation_name_fptr) (const std::string&) |
1324 | 1315 = &application::program_invocation_name; |
1325 m_interactive = false; | 1316 unwind_action restore_program_invocation_name |
1326 | 1317 (program_invocation_name_fptr, m_app_context, |
1327 // If we are running an executable script (#! /bin/octave) then | 1318 application::program_invocation_name ()); |
1328 // we should only see the args passed to the script. | 1319 |
1329 | 1320 void (application::*program_name_fptr) (const std::string&) |
1330 string_vector script_args = options.remaining_args (); | 1321 = &application::program_name; |
1331 | 1322 unwind_action restore_program_name |
1332 m_app_context->intern_argv (script_args); | 1323 (program_name_fptr, m_app_context, application::program_name ()); |
1333 intern_nargin (script_args.numel () - 1); | 1324 |
1334 | 1325 m_interactive = false; |
1335 std::string fname = script_args[0]; | 1326 |
1336 | 1327 // If we are running an executable script (#! /bin/octave) then |
1337 m_app_context->set_program_names (fname); | 1328 // we should only see the args passed to the script. |
1338 | 1329 |
1339 std::string context; | 1330 string_vector script_args = options.remaining_args (); |
1340 bool verbose = false; | 1331 |
1341 bool require_file = true; | 1332 m_app_context->intern_argv (script_args); |
1342 | 1333 intern_nargin (script_args.numel () - 1); |
1343 return safe_source_file (fname, context, verbose, require_file); | 1334 |
1344 } | 1335 std::string fname = script_args[0]; |
1345 | 1336 |
1346 int interpreter::main_loop (void) | 1337 m_app_context->set_program_names (fname); |
1347 { | 1338 |
1348 command_editor::add_event_hook (release_unreferenced_dynamic_libraries); | 1339 std::string context; |
1349 | 1340 bool verbose = false; |
1350 return m_evaluator.repl (); | 1341 bool require_file = true; |
1351 } | 1342 |
1352 | 1343 return safe_source_file (fname, context, verbose, require_file); |
1353 int interpreter::server_loop (void) | 1344 } |
1354 { | 1345 |
1355 return m_evaluator.server_loop (); | 1346 int interpreter::main_loop (void) |
1356 } | 1347 { |
1357 | 1348 command_editor::add_event_hook (release_unreferenced_dynamic_libraries); |
1358 tree_evaluator& interpreter::get_evaluator (void) | 1349 |
1359 { | 1350 return m_evaluator.repl (); |
1360 return m_evaluator; | 1351 } |
1361 } | 1352 |
1362 | 1353 int interpreter::server_loop (void) |
1363 stream_list& interpreter::get_stream_list (void) | 1354 { |
1364 { | 1355 return m_evaluator.server_loop (); |
1365 return m_stream_list; | 1356 } |
1366 } | 1357 |
1367 | 1358 tree_evaluator& interpreter::get_evaluator (void) |
1368 url_handle_manager& interpreter::get_url_handle_manager (void) | 1359 { |
1369 { | 1360 return m_evaluator; |
1370 return m_url_handle_manager; | 1361 } |
1371 } | 1362 |
1372 | 1363 stream_list& interpreter::get_stream_list (void) |
1373 symbol_scope | 1364 { |
1374 interpreter::get_top_scope (void) const | 1365 return m_stream_list; |
1375 { | 1366 } |
1376 return m_evaluator.get_top_scope (); | 1367 |
1377 } | 1368 url_handle_manager& interpreter::get_url_handle_manager (void) |
1378 | 1369 { |
1379 symbol_scope | 1370 return m_url_handle_manager; |
1380 interpreter::get_current_scope (void) const | 1371 } |
1381 { | 1372 |
1382 return m_evaluator.get_current_scope (); | 1373 symbol_scope |
1383 } | 1374 interpreter::get_top_scope (void) const |
1384 | 1375 { |
1385 symbol_scope | 1376 return m_evaluator.get_top_scope (); |
1386 interpreter::require_current_scope (const std::string& who) const | 1377 } |
1387 { | 1378 |
1388 symbol_scope scope = get_current_scope (); | 1379 symbol_scope |
1389 | 1380 interpreter::get_current_scope (void) const |
1390 if (! scope) | 1381 { |
1391 error ("%s: symbol table scope missing", who.c_str ()); | 1382 return m_evaluator.get_current_scope (); |
1392 | 1383 } |
1393 return scope; | 1384 |
1394 } | 1385 symbol_scope |
1395 | 1386 interpreter::require_current_scope (const std::string& who) const |
1396 profiler& interpreter::get_profiler (void) | 1387 { |
1397 { | 1388 symbol_scope scope = get_current_scope (); |
1398 return m_evaluator.get_profiler (); | 1389 |
1399 } | 1390 if (! scope) |
1400 | 1391 error ("%s: symbol table scope missing", who.c_str ()); |
1401 int interpreter::chdir (const std::string& dir) | 1392 |
1402 { | 1393 return scope; |
1403 std::string xdir = sys::file_ops::tilde_expand (dir); | 1394 } |
1404 | 1395 |
1405 int cd_ok = sys::env::chdir (xdir); | 1396 profiler& interpreter::get_profiler (void) |
1406 | 1397 { |
1407 if (! cd_ok) | 1398 return m_evaluator.get_profiler (); |
1408 error ("%s: %s", dir.c_str (), std::strerror (errno)); | 1399 } |
1409 | 1400 |
1410 Vlast_chdir_time.stamp (); | 1401 int interpreter::chdir (const std::string& dir) |
1411 | 1402 { |
1412 // FIXME: should these actions be handled as a list of functions | 1403 std::string xdir = sys::file_ops::tilde_expand (dir); |
1413 // to call so users can add their own chdir handlers? | 1404 |
1414 | 1405 int cd_ok = sys::env::chdir (xdir); |
1415 m_load_path.read_dir_config ("."); | 1406 |
1416 m_load_path.update (); | 1407 if (! cd_ok) |
1417 | 1408 error ("%s: %s", dir.c_str (), std::strerror (errno)); |
1418 m_event_manager.directory_changed (sys::env::get_current_directory ()); | 1409 |
1419 | 1410 Vlast_chdir_time.stamp (); |
1420 return cd_ok; | 1411 |
1421 } | 1412 // FIXME: should these actions be handled as a list of functions |
1422 | 1413 // to call so users can add their own chdir handlers? |
1423 void interpreter::mlock (bool skip_first) const | 1414 |
1424 { | 1415 m_load_path.read_dir_config ("."); |
1425 m_evaluator.mlock (skip_first); | 1416 m_load_path.update (); |
1426 } | 1417 |
1427 | 1418 m_event_manager.directory_changed (sys::env::get_current_directory ()); |
1428 void interpreter::munlock (bool skip_first) const | 1419 |
1429 { | 1420 return cd_ok; |
1430 m_evaluator.munlock (skip_first); | 1421 } |
1431 } | 1422 |
1432 | 1423 void interpreter::mlock (bool skip_first) const |
1433 bool interpreter::mislocked (bool skip_first) const | 1424 { |
1434 { | 1425 m_evaluator.mlock (skip_first); |
1435 return m_evaluator.mislocked (skip_first); | 1426 } |
1436 } | 1427 |
1437 | 1428 void interpreter::munlock (bool skip_first) const |
1438 void interpreter::munlock (const char *nm) | 1429 { |
1439 { | 1430 m_evaluator.munlock (skip_first); |
1440 if (! nm) | 1431 } |
1441 error ("munlock: invalid value for NAME"); | 1432 |
1442 | 1433 bool interpreter::mislocked (bool skip_first) const |
1443 munlock (std::string (nm)); | 1434 { |
1444 } | 1435 return m_evaluator.mislocked (skip_first); |
1445 | 1436 } |
1446 void interpreter::munlock (const std::string& nm) | 1437 |
1447 { | 1438 void interpreter::munlock (const char *nm) |
1448 octave_value val = m_symbol_table.find_function (nm); | 1439 { |
1449 | 1440 if (! nm) |
1450 if (val.is_defined ()) | 1441 error ("munlock: invalid value for NAME"); |
1451 { | 1442 |
1452 octave_function *fcn = val.function_value (); | 1443 munlock (std::string (nm)); |
1453 | 1444 } |
1454 if (fcn) | 1445 |
1455 fcn->unlock (); | 1446 void interpreter::munlock (const std::string& nm) |
1456 } | 1447 { |
1457 } | 1448 octave_value val = m_symbol_table.find_function (nm); |
1458 | 1449 |
1459 bool interpreter::mislocked (const char *nm) | 1450 if (val.is_defined ()) |
1460 { | 1451 { |
1461 if (! nm) | 1452 octave_function *fcn = val.function_value (); |
1462 error ("mislocked: invalid value for NAME"); | 1453 |
1463 | 1454 if (fcn) |
1464 return mislocked (std::string (nm)); | 1455 fcn->unlock (); |
1465 } | 1456 } |
1466 | 1457 } |
1467 bool interpreter::mislocked (const std::string& nm) | 1458 |
1468 { | 1459 bool interpreter::mislocked (const char *nm) |
1469 bool retval = false; | 1460 { |
1470 | 1461 if (! nm) |
1471 octave_value val = m_symbol_table.find_function (nm); | 1462 error ("mislocked: invalid value for NAME"); |
1472 | 1463 |
1473 if (val.is_defined ()) | 1464 return mislocked (std::string (nm)); |
1474 { | 1465 } |
1475 octave_function *fcn = val.function_value (); | 1466 |
1476 | 1467 bool interpreter::mislocked (const std::string& nm) |
1477 if (fcn) | 1468 { |
1478 retval = fcn->islocked (); | 1469 bool retval = false; |
1479 } | 1470 |
1480 | 1471 octave_value val = m_symbol_table.find_function (nm); |
1481 return retval; | 1472 |
1482 } | 1473 if (val.is_defined ()) |
1483 | 1474 { |
1484 std::string interpreter::mfilename (const std::string& opt) const | 1475 octave_function *fcn = val.function_value (); |
1485 { | 1476 |
1486 return m_evaluator.mfilename (opt); | 1477 if (fcn) |
1487 } | 1478 retval = fcn->islocked (); |
1488 | 1479 } |
1489 octave_value_list interpreter::eval_string (const std::string& eval_str, | 1480 |
1490 bool silent, int& parse_status, | 1481 return retval; |
1491 int nargout) | 1482 } |
1492 { | 1483 |
1493 return m_evaluator.eval_string (eval_str, silent, parse_status, nargout); | 1484 std::string interpreter::mfilename (const std::string& opt) const |
1494 } | 1485 { |
1495 | 1486 return m_evaluator.mfilename (opt); |
1496 octave_value interpreter::eval_string (const std::string& eval_str, | 1487 } |
1497 bool silent, int& parse_status) | 1488 |
1498 { | 1489 octave_value_list interpreter::eval_string (const std::string& eval_str, |
1499 return m_evaluator.eval_string (eval_str, silent, parse_status); | 1490 bool silent, int& parse_status, |
1500 } | 1491 int nargout) |
1501 | 1492 { |
1502 octave_value_list interpreter::eval_string (const octave_value& arg, | 1493 return m_evaluator.eval_string (eval_str, silent, parse_status, nargout); |
1503 bool silent, int& parse_status, | 1494 } |
1504 int nargout) | 1495 |
1505 { | 1496 octave_value interpreter::eval_string (const std::string& eval_str, |
1506 return m_evaluator.eval_string (arg, silent, parse_status, nargout); | 1497 bool silent, int& parse_status) |
1507 } | 1498 { |
1508 | 1499 return m_evaluator.eval_string (eval_str, silent, parse_status); |
1509 octave_value_list interpreter::eval (const std::string& try_code, | 1500 } |
1501 | |
1502 octave_value_list interpreter::eval_string (const octave_value& arg, | |
1503 bool silent, int& parse_status, | |
1504 int nargout) | |
1505 { | |
1506 return m_evaluator.eval_string (arg, silent, parse_status, nargout); | |
1507 } | |
1508 | |
1509 octave_value_list interpreter::eval (const std::string& try_code, | |
1510 int nargout) | |
1511 { | |
1512 return m_evaluator.eval (try_code, nargout); | |
1513 } | |
1514 | |
1515 octave_value_list interpreter::eval (const std::string& try_code, | |
1516 const std::string& catch_code, | |
1517 int nargout) | |
1518 { | |
1519 return m_evaluator.eval (try_code, catch_code, nargout); | |
1520 } | |
1521 | |
1522 octave_value_list interpreter::evalin (const std::string& context, | |
1523 const std::string& try_code, | |
1510 int nargout) | 1524 int nargout) |
1511 { | 1525 { |
1512 return m_evaluator.eval (try_code, nargout); | 1526 return m_evaluator.evalin (context, try_code, nargout); |
1513 } | 1527 } |
1514 | 1528 |
1515 octave_value_list interpreter::eval (const std::string& try_code, | 1529 octave_value_list interpreter::evalin (const std::string& context, |
1530 const std::string& try_code, | |
1516 const std::string& catch_code, | 1531 const std::string& catch_code, |
1517 int nargout) | 1532 int nargout) |
1518 { | 1533 { |
1519 return m_evaluator.eval (try_code, catch_code, nargout); | 1534 return m_evaluator.evalin (context, try_code, catch_code, nargout); |
1520 } | 1535 } |
1521 | 1536 |
1522 octave_value_list interpreter::evalin (const std::string& context, | 1537 //! Evaluate an Octave function (built-in or interpreted) and return |
1523 const std::string& try_code, | 1538 //! the list of result values. |
1524 int nargout) | 1539 //! |
1525 { | 1540 //! @param name The name of the function to call. |
1526 return m_evaluator.evalin (context, try_code, nargout); | 1541 //! @param args The arguments to the function. |
1527 } | 1542 //! @param nargout The number of output arguments expected. |
1528 | 1543 //! @return A list of output values. The length of the list is not |
1529 octave_value_list interpreter::evalin (const std::string& context, | 1544 //! necessarily the same as @c nargout. |
1530 const std::string& try_code, | 1545 |
1531 const std::string& catch_code, | 1546 octave_value_list interpreter::feval (const char *name, |
1532 int nargout) | 1547 const octave_value_list& args, |
1533 { | 1548 int nargout) |
1534 return m_evaluator.evalin (context, try_code, catch_code, nargout); | 1549 { |
1535 } | 1550 return feval (std::string (name), args, nargout); |
1536 | 1551 } |
1537 //! Evaluate an Octave function (built-in or interpreted) and return | 1552 |
1538 //! the list of result values. | 1553 octave_value_list interpreter::feval (const std::string& name, |
1539 //! | 1554 const octave_value_list& args, |
1540 //! @param name The name of the function to call. | 1555 int nargout) |
1541 //! @param args The arguments to the function. | 1556 { |
1542 //! @param nargout The number of output arguments expected. | 1557 octave_value fcn = m_symbol_table.find_function (name, args); |
1543 //! @return A list of output values. The length of the list is not | 1558 |
1544 //! necessarily the same as @c nargout. | 1559 if (fcn.is_undefined ()) |
1545 | 1560 error ("feval: function '%s' not found", name.c_str ()); |
1546 octave_value_list interpreter::feval (const char *name, | 1561 |
1547 const octave_value_list& args, | 1562 octave_function *of = fcn.function_value (); |
1548 int nargout) | 1563 |
1549 { | 1564 return of->call (m_evaluator, nargout, args); |
1550 return feval (std::string (name), args, nargout); | 1565 } |
1551 } | 1566 |
1552 | 1567 octave_value_list interpreter::feval (octave_function *fcn, |
1553 octave_value_list interpreter::feval (const std::string& name, | 1568 const octave_value_list& args, |
1554 const octave_value_list& args, | 1569 int nargout) |
1555 int nargout) | 1570 { |
1556 { | 1571 if (fcn) |
1557 octave_value fcn = m_symbol_table.find_function (name, args); | 1572 return fcn->call (m_evaluator, nargout, args); |
1558 | 1573 |
1559 if (fcn.is_undefined ()) | 1574 return octave_value_list (); |
1560 error ("feval: function '%s' not found", name.c_str ()); | 1575 } |
1561 | 1576 |
1562 octave_function *of = fcn.function_value (); | 1577 octave_value_list interpreter::feval (const octave_value& val, |
1563 | 1578 const octave_value_list& args, |
1564 return of->call (m_evaluator, nargout, args); | 1579 int nargout) |
1565 } | 1580 { |
1566 | 1581 // FIXME: do we really want to silently return an empty ovl if |
1567 octave_value_list interpreter::feval (octave_function *fcn, | 1582 // the function object is undefined? It's essentially what the |
1568 const octave_value_list& args, | 1583 // version above that accepts a pointer to an octave_function |
1569 int nargout) | 1584 // object does and some code was apparently written to rely on it |
1570 { | 1585 // (for example, __ode15__). |
1571 if (fcn) | 1586 |
1572 return fcn->call (m_evaluator, nargout, args); | 1587 if (val.is_undefined ()) |
1573 | |
1574 return octave_value_list (); | |
1575 } | |
1576 | |
1577 octave_value_list interpreter::feval (const octave_value& val, | |
1578 const octave_value_list& args, | |
1579 int nargout) | |
1580 { | |
1581 // FIXME: do we really want to silently return an empty ovl if | |
1582 // the function object is undefined? It's essentially what the | |
1583 // version above that accepts a pointer to an octave_function | |
1584 // object does and some code was apparently written to rely on it | |
1585 // (for example, __ode15__). | |
1586 | |
1587 if (val.is_undefined ()) | |
1588 return ovl (); | |
1589 | |
1590 if (val.is_function ()) | |
1591 { | |
1592 return feval (val.function_value (), args, nargout); | |
1593 } | |
1594 else if (val.is_function_handle () || val.is_inline_function ()) | |
1595 { | |
1596 // This covers function handles, inline functions, and anonymous | |
1597 // functions. | |
1598 | |
1599 std::list<octave_value_list> arg_list; | |
1600 arg_list.push_back (args); | |
1601 | |
1602 // FIXME: could we make octave_value::subsref a const method? | |
1603 // It would be difficult because there are instances of | |
1604 // incrementing the reference count inside subsref methods, | |
1605 // which means they can't be const with the current way of | |
1606 // handling reference counting. | |
1607 | |
1608 octave_value xval = val; | |
1609 return xval.subsref ("(", arg_list, nargout); | |
1610 } | |
1611 else if (val.is_string ()) | |
1612 { | |
1613 return feval (val.string_value (), args, nargout); | |
1614 } | |
1615 else | |
1616 error ("feval: first argument must be a string, inline function, or a function handle"); | |
1617 | |
1618 return ovl (); | 1588 return ovl (); |
1619 } | 1589 |
1620 | 1590 if (val.is_function ()) |
1621 //! Evaluate an Octave function (built-in or interpreted) and return | 1591 { |
1622 //! the list of result values. | 1592 return feval (val.function_value (), args, nargout); |
1623 //! | 1593 } |
1624 //! @param args The first element of @c args is the function to call. | 1594 else if (val.is_function_handle () || val.is_inline_function ()) |
1625 //! It may be the name of the function as a string, a function | 1595 { |
1626 //! handle, or an inline function. The remaining arguments are | 1596 // This covers function handles, inline functions, and anonymous |
1627 //! passed to the function. | 1597 // functions. |
1628 //! @param nargout The number of output arguments expected. | 1598 |
1629 //! @return A list of output values. The length of the list is not | 1599 std::list<octave_value_list> arg_list; |
1630 //! necessarily the same as @c nargout. | 1600 arg_list.push_back (args); |
1631 | 1601 |
1632 octave_value_list interpreter::feval (const octave_value_list& args, | 1602 // FIXME: could we make octave_value::subsref a const method? |
1633 int nargout) | 1603 // It would be difficult because there are instances of |
1634 { | 1604 // incrementing the reference count inside subsref methods, |
1635 if (args.length () == 0) | 1605 // which means they can't be const with the current way of |
1636 error ("feval: first argument must be a string, inline function, or a function handle"); | 1606 // handling reference counting. |
1637 | 1607 |
1638 octave_value f_arg = args(0); | 1608 octave_value xval = val; |
1639 | 1609 return xval.subsref ("(", arg_list, nargout); |
1640 octave_value_list tmp_args = args.slice (1, args.length () - 1, true); | 1610 } |
1641 | 1611 else if (val.is_string ()) |
1642 return feval (f_arg, tmp_args, nargout); | 1612 { |
1643 } | 1613 return feval (val.string_value (), args, nargout); |
1644 | 1614 } |
1645 octave_value interpreter::make_function_handle (const std::string& name) | 1615 else |
1646 { | 1616 error ("feval: first argument must be a string, inline function, or a function handle"); |
1647 return m_evaluator.make_fcn_handle (name); | 1617 |
1648 } | 1618 return ovl (); |
1649 | 1619 } |
1650 void interpreter::install_variable (const std::string& name, | 1620 |
1651 const octave_value& value, bool global) | 1621 //! Evaluate an Octave function (built-in or interpreted) and return |
1652 { | 1622 //! the list of result values. |
1653 m_evaluator.install_variable (name, value, global); | 1623 //! |
1654 } | 1624 //! @param args The first element of @c args is the function to call. |
1655 | 1625 //! It may be the name of the function as a string, a function |
1656 octave_value interpreter::global_varval (const std::string& name) const | 1626 //! handle, or an inline function. The remaining arguments are |
1657 { | 1627 //! passed to the function. |
1658 return m_evaluator.global_varval (name); | 1628 //! @param nargout The number of output arguments expected. |
1659 } | 1629 //! @return A list of output values. The length of the list is not |
1660 | 1630 //! necessarily the same as @c nargout. |
1661 void interpreter::global_assign (const std::string& name, | 1631 |
1662 const octave_value& val) | 1632 octave_value_list interpreter::feval (const octave_value_list& args, |
1663 { | 1633 int nargout) |
1664 m_evaluator.global_assign (name, val); | 1634 { |
1665 } | 1635 if (args.length () == 0) |
1666 | 1636 error ("feval: first argument must be a string, inline function, or a function handle"); |
1667 octave_value interpreter::top_level_varval (const std::string& name) const | 1637 |
1668 { | 1638 octave_value f_arg = args(0); |
1669 return m_evaluator.top_level_varval (name); | 1639 |
1670 } | 1640 octave_value_list tmp_args = args.slice (1, args.length () - 1, true); |
1671 | 1641 |
1672 void interpreter::top_level_assign (const std::string& name, | 1642 return feval (f_arg, tmp_args, nargout); |
1673 const octave_value& val) | 1643 } |
1674 { | 1644 |
1675 m_evaluator.top_level_assign (name, val); | 1645 octave_value interpreter::make_function_handle (const std::string& name) |
1676 } | 1646 { |
1677 | 1647 return m_evaluator.make_fcn_handle (name); |
1678 bool interpreter::is_variable (const std::string& name) const | 1648 } |
1679 { | 1649 |
1680 return m_evaluator.is_variable (name); | 1650 void interpreter::install_variable (const std::string& name, |
1681 } | 1651 const octave_value& value, bool global) |
1682 | 1652 { |
1683 bool interpreter::is_local_variable (const std::string& name) const | 1653 m_evaluator.install_variable (name, value, global); |
1684 { | 1654 } |
1685 return m_evaluator.is_local_variable (name); | 1655 |
1686 } | 1656 octave_value interpreter::global_varval (const std::string& name) const |
1687 | 1657 { |
1688 octave_value interpreter::varval (const std::string& name) const | 1658 return m_evaluator.global_varval (name); |
1689 { | 1659 } |
1690 return m_evaluator.varval (name); | 1660 |
1691 } | 1661 void interpreter::global_assign (const std::string& name, |
1692 | 1662 const octave_value& val) |
1693 void interpreter::assign (const std::string& name, | 1663 { |
1664 m_evaluator.global_assign (name, val); | |
1665 } | |
1666 | |
1667 octave_value interpreter::top_level_varval (const std::string& name) const | |
1668 { | |
1669 return m_evaluator.top_level_varval (name); | |
1670 } | |
1671 | |
1672 void interpreter::top_level_assign (const std::string& name, | |
1673 const octave_value& val) | |
1674 { | |
1675 m_evaluator.top_level_assign (name, val); | |
1676 } | |
1677 | |
1678 bool interpreter::is_variable (const std::string& name) const | |
1679 { | |
1680 return m_evaluator.is_variable (name); | |
1681 } | |
1682 | |
1683 bool interpreter::is_local_variable (const std::string& name) const | |
1684 { | |
1685 return m_evaluator.is_local_variable (name); | |
1686 } | |
1687 | |
1688 octave_value interpreter::varval (const std::string& name) const | |
1689 { | |
1690 return m_evaluator.varval (name); | |
1691 } | |
1692 | |
1693 void interpreter::assign (const std::string& name, | |
1694 const octave_value& val) | |
1695 { | |
1696 m_evaluator.assign (name, val); | |
1697 } | |
1698 | |
1699 void interpreter::assignin (const std::string& context, | |
1700 const std::string& name, | |
1694 const octave_value& val) | 1701 const octave_value& val) |
1695 { | 1702 { |
1696 m_evaluator.assign (name, val); | 1703 m_evaluator.assignin (context, name, val); |
1697 } | 1704 } |
1698 | 1705 |
1699 void interpreter::assignin (const std::string& context, | 1706 void interpreter::source_file (const std::string& file_name, |
1700 const std::string& name, | 1707 const std::string& context, bool verbose, |
1701 const octave_value& val) | 1708 bool require_file) |
1702 { | 1709 { |
1703 m_evaluator.assignin (context, name, val); | 1710 m_evaluator.source_file (file_name, context, verbose, require_file); |
1704 } | 1711 } |
1705 | 1712 |
1706 void interpreter::source_file (const std::string& file_name, | 1713 bool interpreter::at_top_level (void) const |
1707 const std::string& context, bool verbose, | 1714 { |
1708 bool require_file) | 1715 return m_evaluator.at_top_level (); |
1709 { | 1716 } |
1710 m_evaluator.source_file (file_name, context, verbose, require_file); | 1717 |
1711 } | 1718 bool interpreter::isglobal (const std::string& name) const |
1712 | 1719 { |
1713 bool interpreter::at_top_level (void) const | 1720 return m_evaluator.is_global (name); |
1714 { | 1721 } |
1715 return m_evaluator.at_top_level (); | 1722 |
1716 } | 1723 octave_value interpreter::find (const std::string& name) |
1717 | 1724 { |
1718 bool interpreter::isglobal (const std::string& name) const | 1725 return m_evaluator.find (name); |
1719 { | 1726 } |
1720 return m_evaluator.is_global (name); | 1727 |
1721 } | 1728 void interpreter::clear_all (bool force) |
1722 | 1729 { |
1723 octave_value interpreter::find (const std::string& name) | 1730 m_evaluator.clear_all (force); |
1724 { | 1731 } |
1725 return m_evaluator.find (name); | 1732 |
1726 } | 1733 void interpreter::clear_objects (void) |
1727 | 1734 { |
1728 void interpreter::clear_all (bool force) | 1735 m_evaluator.clear_objects (); |
1729 { | 1736 } |
1730 m_evaluator.clear_all (force); | 1737 |
1731 } | 1738 void interpreter::clear_variable (const std::string& name) |
1732 | 1739 { |
1733 void interpreter::clear_objects (void) | 1740 m_evaluator.clear_variable (name); |
1734 { | 1741 } |
1735 m_evaluator.clear_objects (); | 1742 |
1736 } | 1743 void interpreter::clear_variable_pattern (const std::string& pattern) |
1737 | 1744 { |
1738 void interpreter::clear_variable (const std::string& name) | 1745 m_evaluator.clear_variable_pattern (pattern); |
1739 { | 1746 } |
1740 m_evaluator.clear_variable (name); | 1747 |
1741 } | 1748 void interpreter::clear_variable_regexp (const std::string& pattern) |
1742 | 1749 { |
1743 void interpreter::clear_variable_pattern (const std::string& pattern) | 1750 m_evaluator.clear_variable_regexp (pattern); |
1744 { | 1751 } |
1745 m_evaluator.clear_variable_pattern (pattern); | 1752 |
1746 } | 1753 void interpreter::clear_variables (void) |
1747 | 1754 { |
1748 void interpreter::clear_variable_regexp (const std::string& pattern) | 1755 m_evaluator.clear_variables (); |
1749 { | 1756 } |
1750 m_evaluator.clear_variable_regexp (pattern); | 1757 |
1751 } | 1758 void interpreter::clear_global_variable (const std::string& name) |
1752 | 1759 { |
1753 void interpreter::clear_variables (void) | 1760 m_evaluator.clear_global_variable (name); |
1754 { | 1761 } |
1755 m_evaluator.clear_variables (); | 1762 |
1756 } | 1763 void interpreter::clear_global_variable_pattern (const std::string& pattern) |
1757 | 1764 { |
1758 void interpreter::clear_global_variable (const std::string& name) | 1765 m_evaluator.clear_global_variable_pattern (pattern); |
1759 { | 1766 } |
1760 m_evaluator.clear_global_variable (name); | 1767 |
1761 } | 1768 void interpreter::clear_global_variable_regexp (const std::string& pattern) |
1762 | 1769 { |
1763 void interpreter::clear_global_variable_pattern (const std::string& pattern) | 1770 m_evaluator.clear_global_variable_regexp (pattern); |
1764 { | 1771 } |
1765 m_evaluator.clear_global_variable_pattern (pattern); | 1772 |
1766 } | 1773 void interpreter::clear_global_variables (void) |
1767 | 1774 { |
1768 void interpreter::clear_global_variable_regexp (const std::string& pattern) | 1775 m_evaluator.clear_global_variables (); |
1769 { | 1776 } |
1770 m_evaluator.clear_global_variable_regexp (pattern); | 1777 |
1771 } | 1778 void interpreter::clear_functions (bool force) |
1772 | 1779 { |
1773 void interpreter::clear_global_variables (void) | 1780 m_symbol_table.clear_functions (force); |
1774 { | 1781 } |
1775 m_evaluator.clear_global_variables (); | 1782 |
1776 } | 1783 void interpreter::clear_function (const std::string& name) |
1777 | 1784 { |
1778 void interpreter::clear_functions (bool force) | 1785 m_symbol_table.clear_function (name); |
1779 { | 1786 } |
1780 m_symbol_table.clear_functions (force); | 1787 |
1781 } | 1788 void interpreter::clear_symbol (const std::string& name) |
1782 | 1789 { |
1783 void interpreter::clear_function (const std::string& name) | 1790 m_evaluator.clear_symbol (name); |
1784 { | 1791 } |
1785 m_symbol_table.clear_function (name); | 1792 |
1786 } | 1793 void interpreter::clear_function_pattern (const std::string& pat) |
1787 | 1794 { |
1788 void interpreter::clear_symbol (const std::string& name) | 1795 m_symbol_table.clear_function_pattern (pat); |
1789 { | 1796 } |
1790 m_evaluator.clear_symbol (name); | 1797 |
1791 } | 1798 void interpreter::clear_function_regexp (const std::string& pat) |
1792 | 1799 { |
1793 void interpreter::clear_function_pattern (const std::string& pat) | 1800 m_symbol_table.clear_function_regexp (pat); |
1794 { | 1801 } |
1795 m_symbol_table.clear_function_pattern (pat); | 1802 |
1796 } | 1803 void interpreter::clear_symbol_pattern (const std::string& pat) |
1797 | 1804 { |
1798 void interpreter::clear_function_regexp (const std::string& pat) | 1805 return m_evaluator.clear_symbol_pattern (pat); |
1799 { | 1806 } |
1800 m_symbol_table.clear_function_regexp (pat); | 1807 |
1801 } | 1808 void interpreter::clear_symbol_regexp (const std::string& pat) |
1802 | 1809 { |
1803 void interpreter::clear_symbol_pattern (const std::string& pat) | 1810 return m_evaluator.clear_symbol_regexp (pat); |
1804 { | 1811 } |
1805 return m_evaluator.clear_symbol_pattern (pat); | 1812 |
1806 } | 1813 std::list<std::string> interpreter::global_variable_names (void) |
1807 | 1814 { |
1808 void interpreter::clear_symbol_regexp (const std::string& pat) | 1815 return m_evaluator.global_variable_names (); |
1809 { | 1816 } |
1810 return m_evaluator.clear_symbol_regexp (pat); | 1817 |
1811 } | 1818 std::list<std::string> interpreter::top_level_variable_names (void) |
1812 | 1819 { |
1813 std::list<std::string> interpreter::global_variable_names (void) | 1820 return m_evaluator.top_level_variable_names (); |
1814 { | 1821 } |
1815 return m_evaluator.global_variable_names (); | 1822 |
1816 } | 1823 std::list<std::string> interpreter::variable_names (void) |
1817 | 1824 { |
1818 std::list<std::string> interpreter::top_level_variable_names (void) | 1825 return m_evaluator.variable_names (); |
1819 { | 1826 } |
1820 return m_evaluator.top_level_variable_names (); | 1827 |
1821 } | 1828 std::list<std::string> interpreter::user_function_names (void) |
1822 | 1829 { |
1823 std::list<std::string> interpreter::variable_names (void) | 1830 return m_symbol_table.user_function_names (); |
1824 { | 1831 } |
1825 return m_evaluator.variable_names (); | 1832 |
1826 } | 1833 std::list<std::string> interpreter::autoloaded_functions (void) const |
1827 | 1834 { |
1828 std::list<std::string> interpreter::user_function_names (void) | 1835 return m_evaluator.autoloaded_functions (); |
1829 { | 1836 } |
1830 return m_symbol_table.user_function_names (); | 1837 |
1831 } | 1838 // May be used to send an interrupt signal to the the interpreter from |
1832 | 1839 // another thread (for example, the GUI). |
1833 std::list<std::string> interpreter::autoloaded_functions (void) const | 1840 |
1834 { | 1841 void interpreter::interrupt (void) |
1835 return m_evaluator.autoloaded_functions (); | 1842 { |
1836 } | 1843 static int sigint = 0; |
1837 | 1844 static bool first = true; |
1838 // May be used to send an interrupt signal to the the interpreter from | 1845 |
1839 // another thread (for example, the GUI). | 1846 if (first) |
1840 | 1847 { |
1841 void interpreter::interrupt (void) | 1848 octave_get_sig_number ("SIGINT", &sigint); |
1842 { | 1849 first = false; |
1843 static int sigint = 0; | 1850 } |
1844 static bool first = true; | 1851 |
1845 | 1852 // Send SIGINT to Octave and (optionally) all other processes in its |
1846 if (first) | 1853 // process group. The signal handler for SIGINT will set a global |
1847 { | 1854 // variable indicating an interrupt has happened. That variable is |
1848 octave_get_sig_number ("SIGINT", &sigint); | 1855 // checked in many places in the Octave interpreter and eventually |
1849 first = false; | 1856 // results in an interrupt_exception being thrown. Finally, that |
1850 } | 1857 // exception is caught and returns control to one of the |
1851 | 1858 // read-eval-print loops or to the server loop. We use a signal |
1852 // Send SIGINT to Octave and (optionally) all other processes in its | 1859 // instead of just setting the global variables here so that we will |
1853 // process group. The signal handler for SIGINT will set a global | 1860 // probably send interrupt signals to any subprocesses as well as |
1854 // variable indicating an interrupt has happened. That variable is | 1861 // interrupt execution of the interpreter. |
1855 // checked in many places in the Octave interpreter and eventually | 1862 |
1856 // results in an interrupt_exception being thrown. Finally, that | 1863 pid_t pid |
1857 // exception is caught and returns control to one of the | 1864 = m_interrupt_all_in_process_group ? 0 : octave_getpid_wrapper (); |
1858 // read-eval-print loops or to the server loop. We use a signal | 1865 |
1859 // instead of just setting the global variables here so that we will | 1866 octave_kill_wrapper (pid, sigint); |
1860 // probably send interrupt signals to any subprocesses as well as | 1867 } |
1861 // interrupt execution of the interpreter. | 1868 |
1862 | 1869 void interpreter::pause (void) |
1863 pid_t pid | 1870 { |
1864 = m_interrupt_all_in_process_group ? 0 : octave_getpid_wrapper (); | 1871 // FIXME: To be reliable, these tree_evaluator functions must be |
1865 | 1872 // made thread safe. |
1866 octave_kill_wrapper (pid, sigint); | 1873 |
1867 } | 1874 m_evaluator.break_on_next_statement (true); |
1868 | 1875 m_evaluator.reset_debug_state (); |
1869 void interpreter::pause (void) | 1876 } |
1870 { | 1877 |
1871 // FIXME: To be reliable, these tree_evaluator functions must be | 1878 void interpreter::stop (void) |
1872 // made thread safe. | 1879 { |
1873 | 1880 // FIXME: To be reliable, these tree_evaluator functions must be |
1874 m_evaluator.break_on_next_statement (true); | 1881 // made thread safe. |
1875 m_evaluator.reset_debug_state (); | 1882 |
1876 } | 1883 if (m_evaluator.in_debug_repl ()) |
1877 | 1884 m_evaluator.dbquit (true); |
1878 void interpreter::stop (void) | 1885 else |
1879 { | 1886 interrupt (); |
1880 // FIXME: To be reliable, these tree_evaluator functions must be | 1887 } |
1881 // made thread safe. | 1888 |
1882 | 1889 void interpreter::resume (void) |
1883 if (m_evaluator.in_debug_repl ()) | 1890 { |
1884 m_evaluator.dbquit (true); | 1891 // FIXME: To be reliable, these tree_evaluator functions must be |
1885 else | 1892 // made thread safe. |
1886 interrupt (); | 1893 |
1887 } | 1894 // FIXME: Should there be any feeback about not doing anything if |
1888 | 1895 // not in debug mode? |
1889 void interpreter::resume (void) | 1896 |
1890 { | 1897 if (m_evaluator.in_debug_repl ()) |
1891 // FIXME: To be reliable, these tree_evaluator functions must be | 1898 m_evaluator.dbcont (); |
1892 // made thread safe. | 1899 } |
1893 | 1900 |
1894 // FIXME: Should there be any feeback about not doing anything if | 1901 // Provided for convenience. Will be removed once we eliminate the |
1895 // not in debug mode? | 1902 // old terminal widget. |
1896 | 1903 bool interpreter::experimental_terminal_widget (void) const |
1897 if (m_evaluator.in_debug_repl ()) | 1904 { |
1898 m_evaluator.dbcont (); | 1905 if (! m_app_context) |
1899 } | 1906 return false; |
1900 | 1907 |
1901 // Provided for convenience. Will be removed once we eliminate the | 1908 // Embedded interpreters don't execute command line options. |
1902 // old terminal widget. | 1909 const cmdline_options& options = m_app_context->options (); |
1903 bool interpreter::experimental_terminal_widget (void) const | 1910 |
1904 { | 1911 return options.experimental_terminal_widget (); |
1905 if (! m_app_context) | 1912 } |
1906 return false; | 1913 |
1907 | 1914 void interpreter::add_debug_watch_expression (const std::string& expr) |
1908 // Embedded interpreters don't execute command line options. | 1915 { |
1909 const cmdline_options& options = m_app_context->options (); | 1916 m_evaluator.add_debug_watch_expression (expr); |
1910 | 1917 } |
1911 return options.experimental_terminal_widget (); | 1918 |
1912 } | 1919 void interpreter::remove_debug_watch_expression (const std::string& expr) |
1913 | 1920 { |
1914 void interpreter::add_debug_watch_expression (const std::string& expr) | 1921 m_evaluator.remove_debug_watch_expression (expr); |
1915 { | 1922 } |
1916 m_evaluator.add_debug_watch_expression (expr); | 1923 |
1917 } | 1924 void interpreter::clear_debug_watch_expressions (void) |
1918 | 1925 { |
1919 void interpreter::remove_debug_watch_expression (const std::string& expr) | 1926 m_evaluator.clear_debug_watch_expressions (); |
1920 { | 1927 } |
1921 m_evaluator.remove_debug_watch_expression (expr); | 1928 |
1922 } | 1929 std::set<std::string> interpreter::debug_watch_expressions (void) const |
1923 | 1930 { |
1924 void interpreter::clear_debug_watch_expressions (void) | 1931 return m_evaluator.debug_watch_expressions (); |
1925 { | 1932 } |
1926 m_evaluator.clear_debug_watch_expressions (); | 1933 |
1927 } | 1934 void interpreter::handle_exception (const execution_exception& ee) |
1928 | 1935 { |
1929 std::set<std::string> interpreter::debug_watch_expressions (void) const | 1936 m_error_system.save_exception (ee); |
1930 { | 1937 |
1931 return m_evaluator.debug_watch_expressions (); | 1938 // FIXME: use a separate stream instead of std::cerr directly so that |
1932 } | 1939 // error messages can be redirected more easily? Pass the message |
1933 | 1940 // to an event manager function? |
1934 void interpreter::handle_exception (const execution_exception& ee) | 1941 m_error_system.display_exception (ee); |
1935 { | 1942 |
1936 m_error_system.save_exception (ee); | 1943 recover_from_exception (); |
1937 | 1944 } |
1938 // FIXME: use a separate stream instead of std::cerr directly so that | 1945 |
1939 // error messages can be redirected more easily? Pass the message | 1946 void interpreter::recover_from_exception (void) |
1940 // to an event manager function? | 1947 { |
1941 m_error_system.display_exception (ee); | 1948 if (octave_interrupt_state) |
1942 | 1949 m_event_manager.interpreter_interrupted (); |
1943 recover_from_exception (); | 1950 |
1944 } | 1951 can_interrupt = true; |
1945 | 1952 octave_interrupt_state = 0; |
1946 void interpreter::recover_from_exception (void) | 1953 octave_signal_caught = 0; |
1947 { | 1954 octave_restore_signal_mask (); |
1948 if (octave_interrupt_state) | 1955 catch_interrupts (); |
1949 m_event_manager.interpreter_interrupted (); | 1956 } |
1950 | 1957 |
1951 can_interrupt = true; | 1958 void interpreter::mark_for_deletion (const std::string& file) |
1952 octave_interrupt_state = 0; | 1959 { |
1953 octave_signal_caught = 0; | 1960 m_tmp_files.insert (file); |
1954 octave_restore_signal_mask (); | 1961 } |
1955 catch_interrupts (); | 1962 |
1956 } | 1963 void interpreter::cleanup_tmp_files (void) |
1957 | 1964 { |
1958 void interpreter::mark_for_deletion (const std::string& file) | 1965 m_tmp_files.cleanup (); |
1959 { | 1966 } |
1960 m_tmp_files.insert (file); | 1967 |
1961 } | 1968 void interpreter::quit (int exit_status, bool force, bool confirm) |
1962 | 1969 { |
1963 void interpreter::cleanup_tmp_files (void) | 1970 if (! force) |
1964 { | 1971 { |
1965 m_tmp_files.cleanup (); | 1972 try |
1966 } | 1973 { |
1967 | 1974 bool cancel = false; |
1968 void interpreter::quit (int exit_status, bool force, bool confirm) | 1975 |
1969 { | 1976 if (symbol_exist ("finish.m", "file")) |
1970 if (! force) | 1977 { |
1971 { | 1978 unwind_protect_var<bool> upv1 (m_executing_finish_script, true); |
1972 try | 1979 unwind_protect_var<bool> upv2 (m_cancel_quit); |
1973 { | 1980 |
1974 bool cancel = false; | 1981 evalin ("base", "finish", 0); |
1975 | 1982 |
1976 if (symbol_exist ("finish.m", "file")) | 1983 cancel = m_cancel_quit; |
1977 { | 1984 } |
1978 unwind_protect_var<bool> upv1 (m_executing_finish_script, true); | 1985 |
1979 unwind_protect_var<bool> upv2 (m_cancel_quit); | 1986 if (cancel) |
1980 | 1987 return; |
1981 evalin ("base", "finish", 0); | 1988 |
1982 | 1989 // Check for confirmation. |
1983 cancel = m_cancel_quit; | 1990 |
1984 } | 1991 if (confirm && ! m_event_manager.confirm_shutdown ()) |
1985 | 1992 return; |
1986 if (cancel) | 1993 } |
1987 return; | 1994 catch (const execution_exception&) |
1988 | 1995 { |
1989 // Check for confirmation. | 1996 // Catch execution_exceptions so we don't throw an |
1990 | 1997 // exit_exception if there is an in finish.m. But throw it |
1991 if (confirm && ! m_event_manager.confirm_shutdown ()) | 1998 // again so that will be handled as any other |
1992 return; | 1999 // execution_exception by the evaluator. This way, errors |
1993 } | 2000 // will be ignored properly and we won't exit if quit is |
1994 catch (const execution_exception&) | 2001 // called recursively from finish.m. |
1995 { | 2002 |
1996 // Catch execution_exceptions so we don't throw an | 2003 throw; |
1997 // exit_exception if there is an in finish.m. But throw it | 2004 } |
1998 // again so that will be handled as any other | 2005 } |
1999 // execution_exception by the evaluator. This way, errors | 2006 |
2000 // will be ignored properly and we won't exit if quit is | 2007 throw exit_exception (exit_status); |
2001 // called recursively from finish.m. | 2008 } |
2002 | 2009 |
2003 throw; | 2010 void interpreter::add_atexit_fcn (const std::string& fname) |
2004 } | 2011 { |
2005 } | 2012 if (m_executing_atexit) |
2006 | 2013 return; |
2007 throw exit_exception (exit_status); | 2014 |
2008 } | 2015 m_atexit_fcns.push_front (fname); |
2009 | 2016 } |
2010 void interpreter::add_atexit_fcn (const std::string& fname) | 2017 |
2011 { | 2018 bool interpreter::remove_atexit_fcn (const std::string& fname) |
2012 if (m_executing_atexit) | 2019 { |
2013 return; | 2020 bool found = false; |
2014 | 2021 |
2015 m_atexit_fcns.push_front (fname); | 2022 for (auto it = m_atexit_fcns.begin (); |
2016 } | 2023 it != m_atexit_fcns.end (); it++) |
2017 | 2024 { |
2018 bool interpreter::remove_atexit_fcn (const std::string& fname) | 2025 if (*it == fname) |
2019 { | 2026 { |
2020 bool found = false; | 2027 m_atexit_fcns.erase (it); |
2021 | 2028 found = true; |
2022 for (auto it = m_atexit_fcns.begin (); | 2029 break; |
2023 it != m_atexit_fcns.end (); it++) | 2030 } |
2024 { | 2031 } |
2025 if (*it == fname) | 2032 |
2026 { | 2033 return found; |
2027 m_atexit_fcns.erase (it); | 2034 } |
2028 found = true; | 2035 |
2029 break; | 2036 // What internal options get configured by --traditional. |
2030 } | 2037 |
2031 } | 2038 void interpreter::maximum_braindamage (void) |
2032 | 2039 { |
2033 return found; | 2040 m_input_system.PS1 (">> "); |
2034 } | 2041 m_input_system.PS2 (""); |
2035 | 2042 |
2036 // What internal options get configured by --traditional. | 2043 m_evaluator.PS4 (""); |
2037 | 2044 |
2038 void interpreter::maximum_braindamage (void) | 2045 m_load_save_system.crash_dumps_octave_core (false); |
2039 { | 2046 m_load_save_system.save_default_options ("-mat-binary"); |
2040 m_input_system.PS1 (">> "); | 2047 |
2041 m_input_system.PS2 (""); | 2048 m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%"); |
2042 | 2049 |
2043 m_evaluator.PS4 (""); | 2050 m_error_system.beep_on_error (true); |
2044 | 2051 |
2045 m_load_save_system.crash_dumps_octave_core (false); | 2052 Fconfirm_recursive_rmdir (octave_value (false)); |
2046 m_load_save_system.save_default_options ("-mat-binary"); | 2053 Foptimize_diagonal_matrix (octave_value (false)); |
2047 | 2054 Foptimize_permutation_matrix (octave_value (false)); |
2048 m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%"); | 2055 Foptimize_range (octave_value (false)); |
2049 | 2056 Ffixed_point_format (octave_value (true)); |
2050 m_error_system.beep_on_error (true); | 2057 Fprint_empty_dimensions (octave_value (false)); |
2051 | 2058 Fprint_struct_array_contents (octave_value (true)); |
2052 Fconfirm_recursive_rmdir (octave_value (false)); | 2059 Fstruct_levels_to_print (octave_value (0)); |
2053 Foptimize_diagonal_matrix (octave_value (false)); | 2060 |
2054 Foptimize_permutation_matrix (octave_value (false)); | 2061 m_error_system.disable_warning ("Octave:abbreviated-property-match"); |
2055 Foptimize_range (octave_value (false)); | 2062 m_error_system.disable_warning ("Octave:colon-nonscalar-argument"); |
2056 Ffixed_point_format (octave_value (true)); | 2063 m_error_system.disable_warning ("Octave:data-file-in-path"); |
2057 Fprint_empty_dimensions (octave_value (false)); | 2064 m_error_system.disable_warning ("Octave:empty-index"); |
2058 Fprint_struct_array_contents (octave_value (true)); | 2065 m_error_system.disable_warning ("Octave:function-name-clash"); |
2059 Fstruct_levels_to_print (octave_value (0)); | 2066 m_error_system.disable_warning ("Octave:possible-matlab-short-circuit-operator"); |
2060 | 2067 } |
2061 m_error_system.disable_warning ("Octave:abbreviated-property-match"); | 2068 |
2062 m_error_system.disable_warning ("Octave:colon-nonscalar-argument"); | 2069 void interpreter::execute_pkg_add (const std::string& dir) |
2063 m_error_system.disable_warning ("Octave:data-file-in-path"); | 2070 { |
2064 m_error_system.disable_warning ("Octave:empty-index"); | 2071 try |
2065 m_error_system.disable_warning ("Octave:function-name-clash"); | 2072 { |
2066 m_error_system.disable_warning ("Octave:possible-matlab-short-circuit-operator"); | 2073 m_load_path.execute_pkg_add (dir); |
2067 } | 2074 } |
2068 | 2075 catch (const interrupt_exception&) |
2069 void interpreter::execute_pkg_add (const std::string& dir) | 2076 { |
2070 { | 2077 recover_from_exception (); |
2071 try | 2078 } |
2072 { | 2079 catch (const execution_exception& ee) |
2073 m_load_path.execute_pkg_add (dir); | 2080 { |
2074 } | 2081 handle_exception (ee); |
2075 catch (const interrupt_exception&) | 2082 } |
2076 { | 2083 } |
2077 recover_from_exception (); | |
2078 } | |
2079 catch (const execution_exception& ee) | |
2080 { | |
2081 handle_exception (ee); | |
2082 } | |
2083 } | |
2084 | 2084 |
2085 OCTAVE_END_NAMESPACE(octave) | 2085 OCTAVE_END_NAMESPACE(octave) |