GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
pt-eval.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2009-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <cctype>
31 
32 #include <condition_variable>
33 #include <iostream>
34 #include <list>
35 #include <mutex>
36 #include <string>
37 #include <thread>
38 
39 #include "cmd-edit.h"
40 #include "file-ops.h"
41 #include "file-stat.h"
42 #include "lo-array-errwarn.h"
43 #include "lo-ieee.h"
44 #include "oct-env.h"
45 
46 #include "bp-table.h"
47 #include "call-stack.h"
48 #include "cdef-manager.h"
49 #include "defun.h"
50 #include "error.h"
51 #include "errwarn.h"
52 #include "event-manager.h"
53 #include "input.h"
54 #include "interpreter-private.h"
55 #include "interpreter.h"
56 #include "mex-private.h"
57 #include "octave.h"
58 #include "ov-classdef.h"
59 #include "ov-fcn-handle.h"
60 #include "ov-mex-fcn.h"
61 #include "ov-usr-fcn.h"
62 #include "ov-re-sparse.h"
63 #include "ov-cx-sparse.h"
64 #include "parse.h"
65 #include "profiler.h"
66 #include "pt-all.h"
67 #include "pt-anon-scopes.h"
68 #include "pt-eval.h"
69 #include "pt-tm-const.h"
70 #include "stack-frame.h"
71 #include "symtab.h"
72 #include "unwind-prot.h"
73 #include "utils.h"
74 #include "variables.h"
75 
77 
78 // Normal evaluator.
79 
80 class quit_debug_exception
81 {
82 public:
83 
84  quit_debug_exception (bool all = false) : m_all (all) { }
85 
86  quit_debug_exception (const quit_debug_exception&) = default;
87 
88  quit_debug_exception& operator = (const quit_debug_exception&) = default;
89 
90  ~quit_debug_exception () = default;
91 
92  bool all () const { return m_all; }
93 
94 private:
95 
96  bool m_all;
97 };
98 
99 class debugger
100 {
101 public:
102 
103  enum execution_mode
104  {
105  EX_NORMAL = 0,
106  EX_CONTINUE = 1,
107  EX_QUIT = 2,
108  EX_QUIT_ALL = 3
109  };
110 
111  debugger (interpreter& interp, std::size_t level)
112  : m_interpreter (interp), m_level (level),
113  m_execution_mode (EX_NORMAL), m_in_debug_repl (false)
114  { }
115 
116  int server_loop ();
117 
118  void repl (const std::string& prompt = "debug> ");
119 
120  bool in_debug_repl () const { return m_in_debug_repl; }
121 
122  void dbcont () { m_execution_mode = EX_CONTINUE; }
123 
124  void dbquit (bool all = false)
125  {
126  if (all)
127  m_execution_mode = EX_QUIT_ALL;
128  else
129  m_execution_mode = EX_QUIT;
130  }
131 
132  bool quitting_debugger () const;
133 
134 private:
135 
136  interpreter& m_interpreter;
137 
138  std::size_t m_level;
139  execution_mode m_execution_mode;
140  bool m_in_debug_repl;
141 };
142 
143 // FIXME: Could the debugger server_loop and repl functions be merged
144 // with the corresponding tree_evaluator functions or do they need to
145 // remain separate? They perform nearly the same functions.
146 
147 int
148 debugger::server_loop ()
149 {
150  // Process events from the event queue.
151 
152  tree_evaluator& tw = m_interpreter.get_evaluator ();
153 
154  void (tree_evaluator::*server_mode_fptr) (bool)
156  unwind_action act (server_mode_fptr, &tw, true);
157 
158  int exit_status = 0;
159 
160  do
161  {
162  if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ())
163  break;
164 
165  if (quitting_debugger ())
166  break;
167 
168  try
169  {
170  // FIXME: Should we call octave_quit in the octave::sleep
171  // and/or command_editor::run_event_hooks functions?
172 
173  octave_quit ();
174 
175  // FIXME: Running the event queue should be decoupled from
176  // the command_editor.
177 
178  // FIXME: Is it OK to use command_editor::run_event_hooks
179  // here? It may run more than one queued function per call,
180  // and it seems that the checks at the top of the loop
181  // probably need to be done after each individual event
182  // function is executed. For now, maybe the simplest thing
183  // would be to pass a predicate function (lambda expression)
184  // to the command_editor::run_event_hooks and have it check
185  // that and break out of the eval loop(s) if the condition
186  // is met?
187 
188  // FIXME: We should also use a condition variable to manage
189  // the execution of entries in the queue and eliminate the
190  // need for the busy-wait loop.
191 
193 
195 
196  sleep (0.1);
197  }
198  catch (const interrupt_exception&)
199  {
201  m_interpreter.recover_from_exception ();
202 
203  // Required newline when the user does Ctrl+C at the prompt.
204  if (m_interpreter.interactive ())
205  octave_stdout << "\n";
206  }
207  catch (const index_exception& e)
208  {
209  m_interpreter.recover_from_exception ();
210 
211  std::cerr << "error: unhandled index exception: "
212  << e.message () << " -- trying to return to prompt"
213  << std::endl;
214  }
215  catch (const execution_exception& ee)
216  {
217  error_system& es = m_interpreter.get_error_system ();
218 
219  es.save_exception (ee);
220  es.display_exception (ee);
221 
222  if (m_interpreter.interactive ())
223  {
224  m_interpreter.recover_from_exception ();
225  }
226  else
227  {
228  // We should exit with a nonzero status.
229  exit_status = 1;
230  break;
231  }
232  }
233  catch (const quit_debug_exception& qde)
234  {
235  if (qde.all ())
236  throw;
237 
238  // Continue in this debug level.
239  }
240  catch (const std::bad_alloc&)
241  {
242  m_interpreter.recover_from_exception ();
243 
244  std::cerr << "error: out of memory -- trying to return to prompt"
245  << std::endl;
246  }
247  }
248  while (exit_status == 0);
249 
250  if (exit_status == EOF)
251  {
252  if (m_interpreter.interactive ())
253  octave_stdout << "\n";
254 
255  exit_status = 0;
256  }
257 
258  return exit_status;
259 }
260 
261 void
262 debugger::repl (const std::string& prompt_arg)
263 {
264  unwind_protect frame;
265 
266  frame.protect_var (m_in_debug_repl);
267  frame.protect_var (m_execution_mode);
268 
269  m_in_debug_repl = true;
270 
271  tree_evaluator& tw = m_interpreter.get_evaluator ();
272 
273  bool silent = tw.quiet_breakpoint_flag (false);
274 
275  frame.add (&tree_evaluator::restore_frame, &tw,
277 
278  tw.goto_frame (tw.debug_frame ());
279 
280  octave_user_code *caller = tw.current_user_code ();
281  std::string fcn_file_nm, fcn_nm;
282 
283  if (caller)
284  {
285  fcn_file_nm = caller->fcn_file_name ();
286  fcn_nm = fcn_file_nm.empty () ? caller->name () : fcn_file_nm;
287  }
288 
289  int curr_debug_line = tw.current_line ();
290 
291  std::ostringstream buf;
292 
293  input_system& input_sys = m_interpreter.get_input_system ();
294 
295  event_manager& evmgr = m_interpreter.get_event_manager ();
296 
297  if (! fcn_nm.empty ())
298  {
299  if (input_sys.gud_mode ())
300  {
301  static char ctrl_z = 'Z' & 0x1f;
302 
303  buf << ctrl_z << ctrl_z << fcn_nm << ':' << curr_debug_line;
304  }
305  else
306  {
307  // FIXME: we should come up with a clean way to detect
308  // that we are stopped on the no-op command that marks the
309  // end of a function or script.
310 
311  if (! silent)
312  {
313  std::shared_ptr<stack_frame> frm = tw.current_user_frame ();
314 
315  frm->display_stopped_in_message (buf);
316  }
317 
318  evmgr.enter_debugger_event (fcn_nm, fcn_file_nm, curr_debug_line);
319 
320  evmgr.set_workspace ();
321 
323  fcn_nm, curr_debug_line);
324 
325  if (! silent)
326  {
327  std::string line_buf;
328 
329  if (caller)
330  line_buf = caller->get_code_line (curr_debug_line);
331 
332  if (! line_buf.empty ())
333  buf << curr_debug_line << ": " << line_buf;
334  }
335  }
336  }
337 
338  if (silent)
340 
341  std::string stopped_in_msg = buf.str ();
342 
343  if (m_interpreter.server_mode ())
344  {
345  if (! stopped_in_msg.empty ())
346  octave_stdout << stopped_in_msg << std::endl;
347 
348  evmgr.push_event_queue ();
349 
350  frame.add (&event_manager::pop_event_queue, &evmgr);
351 
352  frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ());
353 
354  std::shared_ptr<push_parser>
355  debug_parser (new push_parser (m_interpreter));
356 
357  tw.set_parser (debug_parser);
358 
359  server_loop ();
360  }
361  else
362  {
363  if (! stopped_in_msg.empty ())
364  std::cerr << stopped_in_msg << std::endl;
365 
366  std::string tmp_prompt = prompt_arg;
367  if (m_level > 0)
368  tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg;
369 
370  frame.add (&interpreter::set_PS1, &m_interpreter, m_interpreter.PS1 ());
371  m_interpreter.PS1 (tmp_prompt);
372 
373  if (! m_interpreter.interactive ())
374  {
375  void (interpreter::*interactive_fptr) (bool)
377  frame.add (interactive_fptr, &m_interpreter,
378  m_interpreter.interactive ());
379 
380  m_interpreter.interactive (true);
381 
382  // FIXME: should debugging be possible in an embedded
383  // interpreter?
384 
385  application *app = application::app ();
386 
387  if (app)
388  {
389  void (application::*forced_interactive_fptr) (bool)
391  frame.add (forced_interactive_fptr, app,
392  app->forced_interactive ());
393 
394  app->forced_interactive (true);
395  }
396  }
397 
398 #if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)
399 
400  input_reader reader (m_interpreter);
401 
402  push_parser debug_parser (m_interpreter);
403 
404 #else
405 
406  parser debug_parser (m_interpreter);
407 
408 #endif
409 
410  error_system& es = m_interpreter.get_error_system ();
411 
412  while (m_in_debug_repl)
413  {
414  if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ())
415  break;
416 
417  if (quitting_debugger ())
418  break;
419 
420  try
421  {
422  debug_parser.reset ();
423 
424 #if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)
425 
426  int retval = 0;
427 
428  std::string prompt
430 
431  do
432  {
433  bool eof = false;
434  std::string input_line = reader.get_input (prompt, eof);
435 
436  if (eof)
437  {
438  retval = EOF;
439  break;
440  }
441 
442  retval = debug_parser.run (input_line, false);
443 
444  prompt = command_editor::decode_prompt_string (m_interpreter.PS2 ());
445  }
446  while (retval < 0);
447 
448 #else
449 
450  int retval = debug_parser.run ();
451 
452 #endif
453  if (command_editor::interrupt (false))
454  {
455  // Break regardless of m_execution_mode value.
456 
457  quitting_debugger ();
458 
459  break;
460  }
461  else
462  {
463  if (retval == 0)
464  {
465  std::shared_ptr<tree_statement_list> stmt_list
466  = debug_parser.statement_list ();
467 
468  if (stmt_list)
469  stmt_list->accept (tw);
470 
473 
474  // FIXME: the following statement is here because
475  // the last command may have been a dbup, dbdown, or
476  // dbstep command that changed the current debug
477  // frame. If so, we need to reset the current frame
478  // for the call stack. But is this right way to do
479  // this job? What if the statement list was
480  // something like "dbup; dbstack"? Will the call to
481  // dbstack use the right frame? If not, how can we
482  // fix this problem?
483  tw.goto_frame (tw.debug_frame ());
484  }
485 
486  octave_quit ();
487  }
488  }
489  catch (const execution_exception& ee)
490  {
491  es.save_exception (ee);
492  es.display_exception (ee);
493 
494  // Ignore errors when in debugging mode;
495  m_interpreter.recover_from_exception ();
496  }
497  catch (const quit_debug_exception& qde)
498  {
499  if (qde.all ())
500  throw;
501 
502  // Continue in this debug level.
503  }
504  }
505  }
506 }
507 
508 bool
509 debugger::quitting_debugger () const
510 {
511  if (m_execution_mode == EX_QUIT)
512  {
513  // If there is no enclosing debug level or the top-level
514  // repl is not active, handle dbquit the same as dbcont.
515 
516  if (m_level > 0 || m_interpreter.server_mode ()
517  || m_interpreter.in_top_level_repl ())
518  throw quit_debug_exception ();
519  else
520  return true;
521  }
522 
523  if (m_execution_mode == EX_QUIT_ALL)
524  {
525  // If the top-level repl is not active, handle "dbquit all"
526  // the same as dbcont.
527 
528  if (m_interpreter.server_mode () || m_interpreter.in_top_level_repl ())
529  throw quit_debug_exception (true);
530  else
531  return true;
532  }
533 
534  return false;
535 }
536 
537 bool
539 {
540  return m_call_stack.at_top_level ();
541 }
542 
543 std::string
544 tree_evaluator::mfilename (const std::string& opt) const
545 {
546  std::string fname;
547 
548  octave_user_code *fcn = m_call_stack.current_user_code ();
549 
550  if (fcn)
551  {
552  fname = fcn->fcn_file_name ();
553 
554  if (fname.empty ())
555  fname = fcn->name ();
556  }
557 
558  if (opt == "fullpathext")
559  return fname;
560 
561  std::size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ());
562  std::size_t epos = fname.rfind ('.');
563 
564  if (epos <= dpos+1)
565  epos = std::string::npos;
566 
567  if (epos != std::string::npos)
568  fname = fname.substr (0, epos);
569 
570  if (opt == "fullpath")
571  return fname;
572 
573  if (dpos != std::string::npos)
574  fname = fname.substr (dpos+1);
575 
576  return fname;
577 }
578 
579 void
580 tree_evaluator::parse_and_execute (const std::string& input,
581  bool& incomplete_parse)
582 {
583  incomplete_parse = false;
584 
585  unwind_protect_var<bool> upv (m_in_top_level_repl, true);
586 
587  if (at_top_level ())
588  {
589  dbstep_flag (0);
591  }
592 
593  // FIXME: OK to do this job here, or should it be in the functions
594  // that do the actual prompting?
595 
596  // Update the time stamp for the "prompt" so that automatically
597  // finding modified files based on file modification times will
598  // work. In the future, we may do something completely different to
599  // check for changes to files but for now, we rely on the prompt
600  // time stamp to limit the checks for file modification times.
601 
602  Vlast_prompt_time.stamp ();
603 
604  bool eof = false;
605 
606  event_manager& evmgr = m_interpreter.get_event_manager ();
607 
608  if (command_history::add (input))
609  evmgr.append_history (input);
610 
611  m_exit_status = m_parser->run (input, eof);
612 
613  if (m_exit_status == 0)
614  {
615  std::shared_ptr<tree_statement_list>
616  stmt_list = m_parser->statement_list ();
617 
618  if (stmt_list)
619  {
621 
622  eval (stmt_list, m_interpreter.interactive ());
623 
624  evmgr.set_workspace ();
625  }
626  else if (m_parser->at_end_of_input ())
627  m_exit_status = EOF;
628  }
629  else
630  incomplete_parse = true;
631 
632  // FIXME: Should we be checking m_exit_status or incomplete_parse or
633  // both here? Could EOF have a value other than -1, and is there
634  // possible confusion between that state and the parser returning -1?
635 
636  if (m_exit_status == -1)
637  m_exit_status = 0;
638  else
639  m_parser->reset ();
640 
641  evmgr.pre_input_event ();
642 }
643 
644 void
646 {
647  std::mutex mtx;
648  std::unique_lock<std::mutex> lock (mtx);
649  std::condition_variable cv;
650  bool incomplete_parse = false;
651  bool evaluation_pending = false;
652  bool exiting = false;
653 
654  event_manager& evmgr = m_interpreter.get_event_manager ();
655 
656  while (true)
657  {
658  // FIXME: Detect EOF? Use readline? If
659  // so, then we need to disable idle event loop hook function
660  // execution.
661 
662  std::string ps
663  = incomplete_parse ? m_interpreter.PS2 () : m_interpreter.PS1 ();
664 
665  std::cout << command_editor::decode_prompt_string (ps);
666 
667  std::string input;
668  std::getline (std::cin, input);
669 
670  if (input.empty ())
671  continue;
672 
673  incomplete_parse = false;
674  evaluation_pending = true;
675  exiting = false;
676 
677  evmgr.post_event
678  ([&] (interpreter& interp)
679  {
680  // INTERPRETER THREAD
681 
682  std::lock_guard<std::mutex> local_lock (mtx);
683 
684  try
685  {
686  interp.parse_and_execute (input, incomplete_parse);
687  }
688  catch (const exit_exception&)
689  {
690  evaluation_pending = false;
691  exiting = true;
692  cv.notify_all ();
693  throw;
694  }
695  catch (const execution_exception& ee)
696  {
697  error_system& es = m_interpreter.get_error_system ();
698 
699  es.save_exception (ee);
700  es.display_exception (ee);
701 
702  if (m_interpreter.interactive ())
703  {
704  m_interpreter.recover_from_exception ();
705  m_parser->reset ();
706  evaluation_pending = false;
707  cv.notify_all ();
708  }
709  else
710  {
711  evaluation_pending = false;
712  cv.notify_all ();
713  throw exit_exception (1);
714  }
715  }
716  catch (...)
717  {
718  evaluation_pending = false;
719  cv.notify_all ();
720  throw;
721  }
722 
723  evaluation_pending = false;
724  cv.notify_all ();
725  });
726 
727  // Wait until evaluation is finished before prompting for input
728  // again.
729 
730  cv.wait (lock, [&] { return ! evaluation_pending; });
731 
732  if (exiting)
733  break;
734  }
735 }
736 
737 int
739 {
740  // The big loop. Read, Eval, Print, Loop. Normally user
741  // interaction at the command line in a terminal session, but we may
742  // also end up here when reading from a pipe or when stdin is
743  // connected to a file by the magic of input redirection.
744 
745  int exit_status = 0;
746 
747  // FIXME: should this choice be a command-line option? Note that we
748  // intend that the push parser interface only be used for
749  // interactive sessions.
750 
751 #if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER)
752  static bool use_command_line_push_parser = true;
753 #else
754  static bool use_command_line_push_parser = false;
755 #endif
756 
757  // The following logic is written as it is to allow easy transition
758  // to setting USE_COMMAND_LINE_PUSH_PARSER at run time and to
759  // simplify the logic of the main loop below by using the same
760  // base_parser::run interface for both push and pull parsers.
761 
762  std::shared_ptr<base_parser> repl_parser;
763 
764  if (m_interpreter.interactive ())
765  {
766  if (use_command_line_push_parser)
767  {
768  push_parser *pp
769  = new push_parser (m_interpreter,
770  new input_reader (m_interpreter));
771 
772  repl_parser = std::shared_ptr<base_parser> (pp);
773  }
774  else
775  {
776  parser *pp = new parser (new lexer (m_interpreter));
777  repl_parser = std::shared_ptr<base_parser> (pp);
778  }
779  }
780  else
781  {
782  parser *pp = new parser (new lexer (stdin, m_interpreter));
783  repl_parser = std::shared_ptr<base_parser> (pp);
784  }
785 
786  do
787  {
788  try
789  {
790  unwind_protect_var<bool> upv (m_in_top_level_repl, true);
791 
792  repl_parser->reset ();
793 
794  if (at_top_level ())
795  {
796  dbstep_flag (0);
798  }
799 
800  exit_status = repl_parser->run ();
801 
802  if (exit_status == 0)
803  {
804  std::shared_ptr<tree_statement_list>
805  stmt_list = repl_parser->statement_list ();
806 
807  if (stmt_list)
808  {
810 
811  eval (stmt_list, m_interpreter.interactive ());
812  }
813  else if (repl_parser->at_end_of_input ())
814  {
815  exit_status = EOF;
816  break;
817  }
818  }
819  }
820  catch (const interrupt_exception&)
821  {
822  m_interpreter.recover_from_exception ();
823 
824  // Required newline when the user does Ctrl+C at the prompt.
825  if (m_interpreter.interactive ())
826  octave_stdout << "\n";
827  }
828  catch (const index_exception& ie)
829  {
830  m_interpreter.recover_from_exception ();
831 
832  std::cerr << "error: unhandled index exception: "
833  << ie.message () << " -- trying to return to prompt"
834  << std::endl;
835  }
836  catch (const execution_exception& ee)
837  {
838  error_system& es = m_interpreter.get_error_system ();
839 
840  es.save_exception (ee);
841  es.display_exception (ee);
842 
843  if (m_interpreter.interactive ())
844  m_interpreter.recover_from_exception ();
845  else
846  {
847  // We should exit with a nonzero status.
848  exit_status = 1;
849  break;
850  }
851  }
852  catch (const quit_debug_exception&)
853  {
854  m_interpreter.recover_from_exception ();
855 
856  // FIXME: Does anything else need to happen here?
857  }
858  catch (const std::bad_alloc&)
859  {
860  m_interpreter.recover_from_exception ();
861 
862  std::cerr << "error: out of memory -- trying to return to prompt"
863  << std::endl;
864  }
865  }
866  while (exit_status == 0);
867 
868  if (exit_status == EOF)
869  {
870  if (m_interpreter.interactive ())
871  octave_stdout << "\n";
872 
873  exit_status = 0;
874  }
875 
876  return exit_status;
877 }
878 
879 int
881 {
882  // Process events from the event queue.
883 
884  unwind_protect_var<bool> upv1 (m_server_mode, true);
885 
886  m_exit_status = 0;
887 
888  std::shared_ptr<push_parser> parser (new push_parser (m_interpreter));
890 
891  // FIXME: We are currently resetting the parser after every call to
892  // recover_from_exception. This action should probably be handled
893  // in a more consistent way, but resetting the parser in every call
894  // to interpreter::recover_from_exception appears to cause
895  // segfaults in the test suite.
896 
897  do
898  {
899  try
900  {
901  // FIXME: Should we call octave_quit in the octave::sleep
902  // and/or command_editor::run_event_hooks functions?
903 
904  octave_quit ();
905 
906  // FIXME: Running the event queue should be decoupled from
907  // the command_editor. We should also use a condition
908  // variable to manage the execution of entries in the queue
909  // and eliminate the need for the busy-wait loop.
910 
912 
914 
915  sleep (0.1);
916  }
917  catch (const interrupt_exception&)
918  {
920  m_interpreter.recover_from_exception ();
921  m_parser->reset ();
922 
923  // Required newline when the user does Ctrl+C at the prompt.
924  if (m_interpreter.interactive ())
925  octave_stdout << "\n";
926  }
927  catch (const index_exception& e)
928  {
929  m_interpreter.recover_from_exception ();
930  m_parser->reset ();
931 
932  std::cerr << "error: unhandled index exception: "
933  << e.message () << " -- trying to return to prompt"
934  << std::endl;
935  }
936  catch (const execution_exception& ee)
937  {
938  error_system& es = m_interpreter.get_error_system ();
939 
940  es.save_exception (ee);
941  es.display_exception (ee);
942 
943  if (m_interpreter.interactive ())
944  {
945  m_interpreter.recover_from_exception ();
946  m_parser->reset ();
947  }
948  else
949  {
950  // We should exit with a nonzero status.
951  m_exit_status = 1;
952  break;
953  }
954  }
955  catch (const quit_debug_exception&)
956  {
958  m_interpreter.recover_from_exception ();
959  m_parser->reset ();
960  }
961  catch (const exit_exception& xe)
962  {
963  m_exit_status = xe.exit_status ();
964  break;
965  }
966  catch (const std::bad_alloc&)
967  {
968  m_interpreter.recover_from_exception ();
969  m_parser->reset ();
970 
971  std::cerr << "error: out of memory -- trying to return to prompt"
972  << std::endl;
973  }
974  }
975  while (m_exit_status == 0);
976 
977  if (m_exit_status == EOF)
978  {
979  if (m_interpreter.interactive ())
980  octave_stdout << "\n";
981 
982  m_exit_status = 0;
983  }
984 
985  return m_exit_status;
986 }
987 
988 void
989 tree_evaluator::eval (std::shared_ptr<tree_statement_list>& stmt_list,
990  bool interactive)
991 {
992  try
993  {
994  stmt_list->accept (*this);
995 
996  octave_quit ();
997 
998  if (! interactive)
999  {
1000  bool quit = (m_returning || m_breaking);
1001 
1002  if (m_returning)
1003  m_returning = 0;
1004 
1005  if (m_breaking)
1006  m_breaking--;
1007 
1008  if (quit)
1009  return;
1010  }
1011 
1014  }
1015  catch (const quit_debug_exception&)
1016  {
1017  m_interpreter.recover_from_exception ();
1018  }
1019 }
1020 
1022 tree_evaluator::eval_string (const std::string& eval_str, bool silent,
1023  int& parse_status, int nargout)
1024 {
1025  octave_value_list retval;
1026 
1027  parser eval_parser (eval_str, m_interpreter);
1028 
1029  do
1030  {
1031  eval_parser.reset ();
1032 
1033  // If we are looking at
1034  //
1035  // val = eval ("code");
1036  //
1037  // then don't allow code to be parsed as a command.
1038 
1039  if (nargout > 0)
1040  eval_parser.disallow_command_syntax ();
1041 
1042  parse_status = eval_parser.run ();
1043 
1044  if (parse_status == 0)
1045  {
1046  std::shared_ptr<tree_statement_list> stmt_list
1047  = eval_parser.statement_list ();
1048 
1049  if (stmt_list)
1050  {
1051  tree_statement *stmt = nullptr;
1052 
1053  if (stmt_list->length () == 1
1054  && (stmt = stmt_list->front ())
1055  && stmt->is_expression ())
1056  {
1057  tree_expression *expr = stmt->expression ();
1058 
1059  if (silent)
1060  expr->set_print_flag (false);
1061 
1062  retval = expr->evaluate_n (*this, nargout);
1063 
1064  bool do_bind_ans = false;
1065 
1066  if (expr->is_identifier ())
1067  do_bind_ans = ! is_variable (expr);
1068  else
1069  do_bind_ans = ! expr->is_assignment_expression ();
1070 
1071  if (do_bind_ans && ! retval.empty ())
1072  bind_ans (retval(0), expr->print_result ());
1073 
1074  if (nargout == 0)
1075  retval = octave_value_list ();
1076  }
1077  else if (nargout == 0)
1078  stmt_list->accept (*this);
1079  else
1080  error ("eval: invalid use of statement list");
1081 
1082  if (returning () || breaking () || continuing ())
1083  break;
1084  }
1085  else if (eval_parser.at_end_of_input ())
1086  break;
1087  }
1088  }
1089  while (parse_status == 0);
1090 
1091  return retval;
1092 }
1093 
1095 tree_evaluator::eval_string (const std::string& eval_str,
1096  bool silent, int& parse_status)
1097 {
1098  octave_value retval;
1099 
1100  octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1);
1101 
1102  if (! tmp.empty ())
1103  retval = tmp(0);
1104 
1105  return retval;
1106 }
1107 
1110  bool silent, int& parse_status,
1111  int nargout)
1112 {
1113  std::string s = arg.xstring_value ("eval: expecting string argument");
1114 
1115  return eval_string (s, silent, parse_status, nargout);
1116 }
1117 
1119 tree_evaluator::eval (const std::string& try_code,
1120  int nargout)
1121 {
1122  int parse_status = 0;
1123 
1124  return eval_string (try_code, nargout > 0, parse_status, nargout);
1125 }
1126 
1128 tree_evaluator::eval (const std::string& try_code,
1129  const std::string& catch_code,
1130  int nargout)
1131 {
1132  octave_value_list retval;
1133 
1134  error_system& es = m_interpreter.get_error_system ();
1135 
1136  int parse_status = 0;
1137 
1138  bool execution_error = false;
1139 
1140  octave_value_list tmp;
1141 
1142  try
1143  {
1144  tmp = eval_string (try_code, nargout > 0, parse_status, nargout);
1145  }
1146  catch (const execution_exception& ee)
1147  {
1148  es.save_exception (ee);
1149  m_interpreter.recover_from_exception ();
1150 
1151  execution_error = true;
1152  }
1153 
1154  if (parse_status != 0 || execution_error)
1155  {
1156  tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
1157 
1158  retval = (nargout > 0) ? tmp : octave_value_list ();
1159  }
1160  else
1161  {
1162  if (nargout > 0)
1163  retval = tmp;
1164 
1165  // FIXME: we should really be rethrowing whatever
1166  // exception occurred, not just throwing an
1167  // execution exception.
1168  if (execution_error)
1169  throw execution_exception ();
1170  }
1171 
1172  return retval;
1173 }
1174 
1176 tree_evaluator::evalin (const std::string& context,
1177  const std::string& try_code,
1178  int nargout)
1179 {
1180  unwind_action act ([=] (std::size_t frm)
1181  {
1182  m_call_stack.restore_frame (frm);
1183  }, m_call_stack.current_frame ());
1184 
1185  if (context == "caller")
1186  m_call_stack.goto_caller_frame ();
1187  else if (context == "base")
1188  m_call_stack.goto_base_frame ();
1189  else
1190  error (R"(evalin: CONTEXT must be "caller" or "base")");
1191 
1192  int parse_status = 0;
1193 
1194  return eval_string (try_code, nargout > 0, parse_status, nargout);
1195 }
1196 
1198 tree_evaluator::evalin (const std::string& context,
1199  const std::string& try_code,
1200  const std::string& catch_code,
1201  int nargout)
1202 {
1203  octave_value_list retval;
1204 
1205  unwind_action act1 ([=] (std::size_t frm)
1206  {
1207  m_call_stack.restore_frame (frm);
1208  }, m_call_stack.current_frame ());
1209 
1210  if (context == "caller")
1211  m_call_stack.goto_caller_frame ();
1212  else if (context == "base")
1213  m_call_stack.goto_base_frame ();
1214  else
1215  error (R"(evalin: CONTEXT must be "caller" or "base")");
1216 
1217  error_system& es = m_interpreter.get_error_system ();
1218 
1219  int parse_status = 0;
1220 
1221  bool execution_error = false;
1222 
1223  octave_value_list tmp;
1224 
1225  try
1226  {
1227  tmp = eval_string (try_code, nargout > 0, parse_status, nargout);
1228  }
1229  catch (const execution_exception& ee)
1230  {
1231  es.save_exception (ee);
1232  m_interpreter.recover_from_exception ();
1233 
1234  execution_error = true;
1235  }
1236 
1237  if (parse_status != 0 || execution_error)
1238  {
1239  tmp = eval_string (catch_code, nargout > 0, parse_status, nargout);
1240 
1241  retval = (nargout > 0) ? tmp : octave_value_list ();
1242  }
1243  else
1244  {
1245  if (nargout > 0)
1246  retval = tmp;
1247 
1248  // FIXME: we should really be rethrowing whatever
1249  // exception occurred, not just throwing an
1250  // execution exception.
1251  if (execution_error)
1252  throw execution_exception ();
1253  }
1254 
1255  return retval;
1256 }
1257 
1258 void
1260 {
1261  panic_impossible ();
1262 }
1263 
1264 void
1266 {
1267  panic_impossible ();
1268 }
1269 
1270 void
1272 {
1273  warning ("function arguments validation blocks are not supported; INCORRECT RESULTS ARE POSSIBLE");
1274 }
1275 
1276 void
1278 {
1279  panic_impossible ();
1280 }
1281 
1282 void
1284 {
1285  panic_impossible ();
1286 }
1287 
1288 void
1290 {
1291  panic_impossible ();
1292 }
1293 
1294 void
1296 {
1297  panic_impossible ();
1298 }
1299 
1300 void
1302 {
1303  panic_impossible ();
1304 }
1305 
1306 void
1308 {
1309  panic_impossible ();
1310 }
1311 
1312 void
1314 {
1315  panic_impossible ();
1316 }
1317 
1318 void
1320 {
1321  panic_impossible ();
1322 }
1323 
1324 void
1326 {
1327  if (m_echo_state)
1328  {
1329  int line = cmd.line ();
1330  if (line < 0)
1331  line = 1;
1332  echo_code (line);
1333  m_echo_file_pos = line + 1;
1334  }
1335 
1336  if (m_debug_mode)
1337  do_breakpoint (cmd.is_active_breakpoint (*this));
1338 
1339  if (m_in_loop_command)
1340  m_breaking = 1;
1341  else
1342  error ("break must appear in a loop in the same file as loop command");
1343 }
1344 
1345 void
1347 {
1348  panic_impossible ();
1349 }
1350 
1351 void
1353 {
1354  if (m_echo_state)
1355  {
1356  int line = cmd.line ();
1357  if (line < 0)
1358  line = 1;
1359  echo_code (line);
1360  m_echo_file_pos = line + 1;
1361  }
1362 
1363  if (m_debug_mode)
1364  do_breakpoint (cmd.is_active_breakpoint (*this));
1365 
1366  if (m_in_loop_command)
1367  m_continuing = 1;
1368 }
1369 
1370 bool
1372 {
1373  return ! (m_silent_functions && (m_statement_context == SC_FUNCTION
1374  || m_statement_context == SC_SCRIPT));
1375 }
1376 
1377 void
1379 {
1380  m_debug_mode = (m_bp_table.have_breakpoints ()
1381  || m_dbstep_flag != 0
1382  || m_break_on_next_stmt
1383  || in_debug_repl ());
1384 }
1385 
1386 void
1388 {
1389  m_debug_mode = mode;
1390 }
1391 
1392 void
1393 tree_evaluator::enter_debugger (const std::string& prompt)
1394 {
1395  unwind_protect frame;
1396 
1399 
1401 
1402  frame.add (&call_stack::restore_frame, &m_call_stack,
1403  m_call_stack.current_frame ());
1404 
1405  // Don't allow errors or warnings at the debug prompt to push us
1406  // into deeper levels of debugging.
1407 
1408  error_system& es = m_interpreter.get_error_system ();
1409 
1411 
1413  es.debug_on_warning ());
1414 
1415  es.debug_on_error (false);
1416  es.debug_on_warning (false);
1417 
1418  // Go up to the nearest user code frame.
1419 
1420  m_debug_frame = m_call_stack.dbupdown (0);
1421 
1422  // FIXME: probably we just want to print one line, not the
1423  // entire statement, which might span many lines...
1424  //
1425  // tree_print_code tpc (octave_stdout);
1426  // stmt.accept (tpc);
1427 
1428  debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ());
1429 
1430  m_debugger_stack.push (dbgr);
1431 
1432  frame.add ([=] ()
1433  {
1434  delete m_debugger_stack.top ();
1435  m_debugger_stack.pop ();
1436  reset_debug_state ();
1437  });
1438 
1439  dbgr->repl (prompt);
1440 }
1441 
1442 void
1443 tree_evaluator::keyboard (const std::string& prompt)
1444 {
1445  enter_debugger (prompt);
1446 }
1447 
1448 void
1449 tree_evaluator::dbupdown (int n, bool verbose)
1450 {
1451  m_debug_frame = m_call_stack.dbupdown (n, verbose);
1452 }
1453 
1454 Matrix
1456 {
1457  Matrix retval;
1458 
1459  const std::list<octave_lvalue> *lvalues = m_lvalue_list;
1460 
1461  if (! lvalues)
1462  return retval;
1463 
1464  octave_idx_type nbh = 0;
1465 
1466  for (const auto& lval : *lvalues)
1467  nbh += lval.is_black_hole ();
1468 
1469  if (nbh > 0)
1470  {
1471  retval.resize (1, nbh);
1472 
1473  octave_idx_type k = 0;
1474  octave_idx_type l = 0;
1475 
1476  for (const auto& lval : *lvalues)
1477  {
1478  if (lval.is_black_hole ())
1479  retval(l++) = k+1;
1480 
1481  k += lval.numel ();
1482  }
1483  }
1484 
1485  return retval;
1486 }
1487 
1488 // If NAME is an operator (like "+", "-", ...), convert it to the
1489 // corresponding function name ("plus", "minus", ...).
1490 
1491 static std::string
1492 get_operator_function_name (const std::string& name)
1493 {
1494  // Bow to the god of compatibility.
1495 
1496  // FIXME: it seems ugly to put this here, but there is no single
1497  // function in the parser that converts from the operator name to
1498  // the corresponding function name. At least try to do it without N
1499  // string compares.
1500 
1501  std::size_t len = name.length ();
1502 
1503  if (len == 2)
1504  {
1505  if (name[0] == '.')
1506  {
1507  switch (name[1])
1508  {
1509  case '\'':
1510  return "transpose";
1511 
1512  case '*':
1513  return "times";
1514 
1515  case '/':
1516  return "rdivide";
1517 
1518  case '^':
1519  return "power";
1520 
1521  case '\\':
1522  return "ldivide";
1523 
1524  default:
1525  break;
1526  }
1527  }
1528  else if (name[1] == '=')
1529  {
1530  switch (name[0])
1531  {
1532  case '<':
1533  return "le";
1534 
1535  case '=':
1536  return "eq";
1537 
1538  case '>':
1539  return "ge";
1540 
1541  case '~':
1542  case '!':
1543  return "ne";
1544 
1545  default:
1546  break;
1547  }
1548  }
1549  }
1550  else if (len == 1)
1551  {
1552  switch (name[0])
1553  {
1554  case '~':
1555  case '!':
1556  return "not";
1557 
1558  case '\'':
1559  return "ctranspose";
1560 
1561  case '+':
1562  return "plus";
1563 
1564  case '-':
1565  return "minus";
1566 
1567  case '*':
1568  return "mtimes";
1569 
1570  case '/':
1571  return "mrdivide";
1572 
1573  case '^':
1574  return "mpower";
1575 
1576  case '\\':
1577  return "mldivide";
1578 
1579  case '<':
1580  return "lt";
1581 
1582  case '>':
1583  return "gt";
1584 
1585  case '&':
1586  return "and";
1587 
1588  case '|':
1589  return "or";
1590 
1591  default:
1592  break;
1593  }
1594  }
1595 
1596  return name;
1597 }
1598 
1599 // Creates a function handle that takes into account the context,
1600 // finding local, nested, private, or sub functions.
1601 
1603 tree_evaluator::make_fcn_handle (const std::string& name)
1604 {
1605  octave_value retval;
1606 
1607  // The str2func function can create a function handle with the name
1608  // of an operator (for example, "+"). If so, it is converted to the
1609  // name of the corresponding function ("+" -> "plus") and we create
1610  // a simple function handle using that name.
1611 
1612  std::string fcn_name = get_operator_function_name (name);
1613 
1614  // If FCN_NAME is different from NAME, then NAME is an operator. As
1615  // of version 2020a, Matlab apparently uses the function name
1616  // corresponding to the operator to search for private and local
1617  // functions in the current scope but not(!) nested functions.
1618 
1619  bool name_is_operator = fcn_name != name;
1620 
1621  std::size_t pos = fcn_name.find ('.');
1622 
1623  if (pos != std::string::npos)
1624  {
1625  // Recognize (some of? which ones?) the following cases
1626  // and create something other than a simple function handle?
1627  // Should we just be checking for the last two when the first
1628  // element of the dot-separated list is an object? If so, then
1629  // should this syntax be limited to a dot-separated list with
1630  // exactly two elements?
1631  //
1632  // object . method
1633  // object . static-method
1634  //
1635  // Code to do that duplicates some of simple_fcn_handle::call.
1636 
1637  // Only accept expressions that contain one '.' separator.
1638 
1639  // FIXME: The logic here is a bit complicated. Is there a good
1640  // way to simplify it?
1641 
1642  std::string meth_nm = fcn_name.substr (pos+1);
1643 
1644  if (meth_nm.find ('.') == std::string::npos)
1645  {
1646  std::string obj_nm = fcn_name.substr (0, pos);
1647 
1648  // If obj_nm is an object in the current scope with a
1649  // method named meth_nm, create a classsimple handle.
1650 
1651  octave_value object = varval (obj_nm);
1652 
1653  if (object.is_defined () && object.is_classdef_object ())
1654  {
1655  octave_classdef *cdef = object.classdef_object_value ();
1656 
1657  if (cdef)
1658  {
1659  std::string class_nm = cdef->class_name ();
1660 
1661  cdef_object cdef_obj = cdef->get_object ();
1662 
1663  cdef_class cls = cdef_obj.get_class ();
1664 
1665  cdef_method meth = cls.find_method (meth_nm);
1666 
1667  if (meth.ok ())
1668  {
1669  // If the method we found is static, create a
1670  // new function name from the class name and
1671  // method name and create a simple function
1672  // handle below. Otherwise, create a class
1673  // simple function handle.
1674 
1675  if (meth.is_static ())
1676  fcn_name = class_nm + '.' + meth_nm;
1677  else
1678  {
1679  octave_value meth_fcn = meth.get_function ();
1680 
1681  octave_fcn_handle *fh
1682  = new octave_fcn_handle (object, meth_fcn,
1683  class_nm, meth_nm);
1684 
1685  return octave_value (fh);
1686  }
1687  }
1688  }
1689  }
1690  }
1691 
1692  // We didn't match anything above, so create handle to SIMPLE
1693  // package function or static class method. Function resolution
1694  // is performed when the handle is used.
1695 
1696  return octave_value (new octave_fcn_handle (fcn_name));
1697  }
1698 
1699  // If the function name refers to a sub/local/private function or a
1700  // class method/constructor, create scoped function handle that is
1701  // bound to that function. Use the same precedence list as
1702  // fcn_info::find but limit search to the following types of
1703  // functions:
1704  //
1705  // nested functions (and subfunctions)
1706  // local functions in the current file
1707  // private function
1708  // class method
1709  //
1710  // For anything else we create a simple function handle that will be
1711  // resolved dynamically in the scope where it is evaluated.
1712 
1713  symbol_scope curr_scope = get_current_scope ();
1714 
1715  symbol_table& symtab = m_interpreter.get_symbol_table ();
1716 
1717  if (curr_scope)
1718  {
1719  octave_value ov_fcn
1720  = symtab.find_scoped_function (fcn_name, curr_scope);
1721 
1722  // If name is operator, we are in Fstr2func, so skip the stack
1723  // frame for that function.
1724 
1725  bool skip_first = name_is_operator;
1726  octave_function *curr_fcn = current_function (skip_first);
1727 
1728  if (ov_fcn.is_defined ())
1729  {
1730  octave_function *fcn = ov_fcn.function_value ();
1731 
1732  if (fcn->is_nested_function ())
1733  {
1734  if (! name_is_operator)
1735  {
1736  // Get current stack frame and return handle to nested
1737  // function.
1738 
1739  std::shared_ptr<stack_frame> frame
1740  = m_call_stack.get_current_stack_frame ();
1741 
1742  // If we are creating a handle to the current
1743  // function or a handle to a sibling function (i.e.,
1744  // not a child of the current function), then use
1745  // the calling stack frame as the context instead of
1746  // the current stack frame.
1747 
1748  // FIXME: Do we need both checks here or is it
1749  // sufficient to check that the parent of curr_fcn
1750  // is the same as the parent of fcn? Is there any
1751  // case where curr_fcn could be nullptr, or does
1752  // that indicate an internal error of some kind?
1753 
1754  if (curr_fcn
1755  && (fcn_name == curr_fcn->name ()
1756  || fcn->parent_fcn_name () == curr_fcn->parent_fcn_name ()))
1757  frame = frame->access_link ();
1758 
1759  octave_fcn_handle *fh
1760  = new octave_fcn_handle (ov_fcn, fcn_name, frame);
1761 
1762  return octave_value (fh);
1763  }
1764  }
1765  else if (fcn->is_subfunction ()
1766  /* || fcn->is_localfunction () */
1767  || fcn->is_private_function ())
1768  {
1769  // Create handle to SCOPED function (sub/local function
1770  // or private function).
1771 
1772  std::list<std::string> parentage = fcn->parent_fcn_names ();
1773 
1774  octave_fcn_handle *fh
1775  = new octave_fcn_handle (ov_fcn, fcn_name, parentage);
1776 
1777  return octave_value (fh);
1778  }
1779  }
1780 
1781  if (curr_fcn && (curr_fcn->is_class_method ()
1782  || curr_fcn->is_class_constructor ()))
1783  {
1784  std::string dispatch_class = curr_fcn->dispatch_class ();
1785 
1786  octave_value ov_meth
1787  = symtab.find_method (fcn_name, dispatch_class);
1788 
1789  if (ov_meth.is_defined ())
1790  {
1791  octave_function *fcn = ov_meth.function_value ();
1792 
1793  // FIXME: do we need to check that it is a method of
1794  // dispatch_class, or is it sufficient to just check
1795  // that it is a method?
1796 
1797  if (fcn->is_class_method ())
1798  {
1799  // Create CLASSSIMPLE handle to method but don't
1800  // bind to the method. Lookup will be done later.
1801 
1802  octave_fcn_handle *fh
1803  = new octave_fcn_handle (dispatch_class, fcn_name);
1804 
1805  return octave_value (fh);
1806  }
1807  }
1808  }
1809  }
1810 
1811  octave_value ov_fcn = symtab.find_user_function (fcn_name);
1812 
1813  // Create handle to SIMPLE function. If the function is not found
1814  // now, then we will look for it again when the handle is used.
1815 
1816  return octave_value (new octave_fcn_handle (ov_fcn, fcn_name));
1817 }
1818 
1819 /*
1820 %!test
1821 %! x = {".'", "transpose";
1822 %! ".*", "times";
1823 %! "./", "rdivide";
1824 %! ".^", "power";
1825 %! ".\\", "ldivide";
1826 %! "<=", "le";
1827 %! "==", "eq";
1828 %! ">=", "ge";
1829 %! "!=", "ne";
1830 %! "~=", "ne";
1831 %! "~", "not";
1832 %! "!", "not";
1833 %! "\'", "ctranspose";
1834 %! "+", "plus";
1835 %! "-", "minus";
1836 %! "*", "mtimes";
1837 %! "/", "mrdivide";
1838 %! "^", "mpower";
1839 %! "\\", "mldivide";
1840 %! "<", "lt";
1841 %! ">", "gt";
1842 %! "&", "and";
1843 %! "|", "or"};
1844 %! for i = 1:rows (x)
1845 %! assert (functions (str2func (x{i,1})).function, x{i,2});
1846 %! endfor
1847 */
1848 
1851 {
1852  // Do not allow functions to return null values.
1853 
1854  tree_identifier *id = elt->ident ();
1855 
1856  return id ? id->evaluate (*this).storable_value () : octave_value ();
1857 }
1858 
1859 bool
1860 tree_evaluator::is_variable (const std::string& name) const
1861 {
1862  std::shared_ptr<stack_frame> frame
1863  = m_call_stack.get_current_stack_frame ();
1864 
1865  return frame->is_variable (name);
1866 }
1867 
1868 bool
1869 tree_evaluator::is_local_variable (const std::string& name) const
1870 {
1871  std::shared_ptr<stack_frame> frame
1872  = m_call_stack.get_current_stack_frame ();
1873 
1874  return frame->is_local_variable (name);
1875 }
1876 
1877 bool
1879 {
1880  if (expr->is_identifier ())
1881  {
1882  const tree_identifier *id
1883  = dynamic_cast<const tree_identifier *> (expr);
1884 
1885  if (id->is_black_hole ())
1886  return false;
1887 
1888  return is_variable (id->symbol ());
1889  }
1890 
1891  return false;
1892 }
1893 
1894 bool
1896 {
1897  if (expr->is_identifier ())
1898  {
1899  const tree_identifier *id
1900  = dynamic_cast<const tree_identifier *> (expr);
1901 
1902  return is_defined (id->symbol ());
1903  }
1904 
1905  return false;
1906 }
1907 
1908 bool
1910 {
1911  std::shared_ptr<stack_frame> frame
1912  = m_call_stack.get_current_stack_frame ();
1913 
1914  return frame->is_variable (sym);
1915 }
1916 
1917 bool
1919 {
1920  std::shared_ptr<stack_frame> frame
1921  = m_call_stack.get_current_stack_frame ();
1922 
1923  return frame->is_defined (sym);
1924 }
1925 
1926 bool
1927 tree_evaluator::is_global (const std::string& name) const
1928 {
1929  std::shared_ptr<stack_frame> frame
1930  = m_call_stack.get_current_stack_frame ();
1931 
1932  return frame->is_global (name);
1933 }
1934 
1937 {
1938  std::shared_ptr<stack_frame> frame
1939  = m_call_stack.get_current_stack_frame ();
1940 
1941  return frame->varval (sym);
1942 }
1943 
1945 tree_evaluator::varval (const std::string& name) const
1946 {
1947  std::shared_ptr<stack_frame> frame
1948  = m_call_stack.get_current_stack_frame ();
1949 
1950  return frame->varval (name);
1951 }
1952 
1953 void
1954 tree_evaluator::install_variable (const std::string& name,
1955  const octave_value& value,
1956  bool global)
1957 {
1958  std::shared_ptr<stack_frame> frame
1959  = m_call_stack.get_current_stack_frame ();
1960 
1961  return frame->install_variable (name, value, global);
1962 }
1963 
1965 tree_evaluator::global_varval (const std::string& name) const
1966 {
1967  return m_call_stack.global_varval (name);
1968 }
1969 
1970 octave_value&
1971 tree_evaluator::global_varref (const std::string& name)
1972 {
1973  return m_call_stack.global_varref (name);
1974 }
1975 
1976 void
1977 tree_evaluator::global_assign (const std::string& name,
1978  const octave_value& val)
1979 {
1980  m_call_stack.global_varref (name) = val;
1981 }
1982 
1984 tree_evaluator::top_level_varval (const std::string& name) const
1985 {
1986  return m_call_stack.get_top_level_value (name);
1987 }
1988 
1989 void
1990 tree_evaluator::top_level_assign (const std::string& name,
1991  const octave_value& val)
1992 {
1993  m_call_stack.set_top_level_value (name, val);
1994 }
1995 
1996 void
1997 tree_evaluator::assign (const std::string& name, const octave_value& val)
1998 {
1999  std::shared_ptr<stack_frame> frame
2000  = m_call_stack.get_current_stack_frame ();
2001 
2002  frame->assign (name, val);
2003 }
2004 
2005 void
2006 tree_evaluator::assignin (const std::string& context,
2007  const std::string& name, const octave_value& val)
2008 {
2009  // FIXME: Can this be done without an unwind-protect frame, simply
2010  // by getting a reference to the caller or base stack frame and
2011  // calling assign on that?
2012 
2013  unwind_action act ([=] (std::size_t frm)
2014  {
2015  m_call_stack.restore_frame (frm);
2016  }, m_call_stack.current_frame ());
2017 
2018  if (context == "caller")
2019  m_call_stack.goto_caller_frame ();
2020  else if (context == "base")
2021  m_call_stack.goto_base_frame ();
2022  else
2023  error (R"(assignin: CONTEXT must be "caller" or "base")");
2024 
2025  if (valid_identifier (name))
2026  {
2027  // Put the check here so that we don't slow down assignments
2028  // generally. Any that go through Octave's parser should have
2029  // already been checked.
2030 
2031  if (iskeyword (name))
2032  error ("assignin: invalid assignment to keyword '%s'",
2033  name.c_str ());
2034 
2035  assign (name, val);
2036  }
2037  else
2038  error ("assignin: invalid variable name '%s'", name.c_str ());
2039 }
2040 
2041 void
2042 tree_evaluator::source_file (const std::string& file_name,
2043  const std::string& context,
2044  bool verbose, bool require_file)
2045 {
2046  // Map from absolute name of script file to recursion level. We
2047  // use a map instead of simply placing a limit on recursion in the
2048  // source_file function so that two mutually recursive scripts
2049  // written as
2050  //
2051  // foo1.m:
2052  // ------
2053  // foo2
2054  //
2055  // foo2.m:
2056  // ------
2057  // foo1
2058  //
2059  // and called with
2060  //
2061  // foo1
2062  //
2063  // (for example) will behave the same if they are written as
2064  //
2065  // foo1.m:
2066  // ------
2067  // source ("foo2.m")
2068  //
2069  // foo2.m:
2070  // ------
2071  // source ("foo1.m")
2072  //
2073  // and called with
2074  //
2075  // source ("foo1.m")
2076  //
2077  // (for example).
2078 
2079  static std::map<std::string, int> source_call_depth;
2080 
2081  std::string file_full_name
2082  = sys::file_ops::tilde_expand (file_name);
2083 
2084  std::size_t pos
2085  = file_full_name.find_last_of (sys::file_ops::dir_sep_str ());
2086 
2087  std::string dir_name = file_full_name.substr (0, pos);
2088 
2089  file_full_name = sys::env::make_absolute (file_full_name);
2090 
2091  unwind_protect frame;
2092 
2093  if (source_call_depth.find (file_full_name) == source_call_depth.end ())
2094  source_call_depth[file_full_name] = -1;
2095 
2096  frame.protect_var (source_call_depth[file_full_name]);
2097 
2098  source_call_depth[file_full_name]++;
2099 
2100  if (source_call_depth[file_full_name] >= max_recursion_depth ())
2101  error ("max_recursion_depth exceeded");
2102 
2103  if (! context.empty ())
2104  {
2105  frame.add (&call_stack::restore_frame, &m_call_stack,
2106  m_call_stack.current_frame ());
2107 
2108  if (context == "caller")
2109  m_call_stack.goto_caller_frame ();
2110  else if (context == "base")
2111  m_call_stack.goto_base_frame ();
2112  else
2113  error (R"(source: CONTEXT must be "caller" or "base")");
2114  }
2115 
2116  // Find symbol name that would be in symbol_table, if it were loaded.
2117  std::size_t dir_end
2118  = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
2119  dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1;
2120 
2121  std::size_t extension = file_name.find_last_of ('.');
2122  if (extension == std::string::npos)
2123  extension = file_name.length ();
2124 
2125  std::string symbol = file_name.substr (dir_end, extension - dir_end);
2126  std::string full_name = sys::canonicalize_file_name (file_name);
2127 
2128  // Check if this file is already loaded (or in the path)
2129  symbol_table& symtab = m_interpreter.get_symbol_table ();
2130  octave_value ov_code = symtab.fcn_table_find (symbol);
2131 
2132  // For compatibility with Matlab, accept both scripts and
2133  // functions.
2134 
2135  if (ov_code.is_user_code ())
2136  {
2137  octave_user_code *code = ov_code.user_code_value ();
2138 
2139  if (! code
2141  != full_name))
2142  {
2143  // Wrong file, so load it below.
2144  ov_code = octave_value ();
2145  }
2146  }
2147  else
2148  {
2149  // Not a script, so load it below.
2150  ov_code = octave_value ();
2151  }
2152 
2153  // If no symbol of this name, or the symbol is for a different
2154  // file, load.
2155 
2156  if (ov_code.is_undefined ())
2157  {
2158  try
2159  {
2160  ov_code = parse_fcn_file (m_interpreter, file_full_name,
2161  file_name, dir_name, "", "",
2162  require_file, true, false, false);
2163  }
2164  catch (execution_exception& ee)
2165  {
2166  error (ee, "source: error sourcing file '%s'",
2167  file_full_name.c_str ());
2168  }
2169  }
2170 
2171  // Return or error if we don't have a valid script or function.
2172 
2173  if (ov_code.is_undefined ())
2174  return;
2175 
2176  if (! ov_code.is_user_code ())
2177  error ("source: %s is not a script", full_name.c_str ());
2178 
2179  if (verbose)
2180  {
2181  octave_stdout << "executing commands from " << full_name << " ... ";
2182  octave_stdout.flush ();
2183  }
2184 
2185  octave_user_code *code = ov_code.user_code_value ();
2186 
2187  code->call (*this, 0, octave_value_list ());
2188 
2189  if (verbose)
2190  octave_stdout << "done." << std::endl;
2191 }
2192 
2193 void
2195  const octave_value& val)
2196 {
2197  m_call_stack.set_auto_fcn_var (avt, val);
2198 }
2199 
2200 void
2202 {
2203  m_call_stack.set_nargin (nargin);
2204 }
2205 
2206 void
2208 {
2209  m_call_stack.set_nargout (nargout);
2210 }
2211 
2214 {
2215  return m_call_stack.get_auto_fcn_var (avt);
2216 }
2217 
2218 void
2220  (tree_parameter_list *param_list, const octave_value_list& args)
2221 {
2222  if (! param_list || param_list->varargs_only ())
2223  return;
2224 
2225  int i = -1;
2226 
2227  for (tree_decl_elt *elt : *param_list)
2228  {
2229  i++;
2230 
2231  octave_lvalue ref = elt->lvalue (*this);
2232 
2233  if (i < args.length ())
2234  {
2235  if (args(i).is_defined () && args(i).is_magic_colon ())
2236  {
2237  if (! eval_decl_elt (elt))
2238  error ("no default value for argument %d", i+1);
2239  }
2240  else
2241  ref.define (args(i));
2242  }
2243  else
2244  eval_decl_elt (elt);
2245  }
2246 }
2247 
2248 void
2250 {
2251  for (tree_decl_elt *elt : *param_list)
2252  {
2253  octave_lvalue ref = elt->lvalue (*this);
2254 
2256  }
2257 }
2258 
2259 DEFMETHOD (end, interp, args, ,
2260  doc: /* -*- texinfo -*-
2261 @deftypefn {} {} end
2262 Last element of an array or the end of any @code{for}, @code{parfor},
2263 @code{if}, @code{do}, @code{while}, @code{function}, @code{switch},
2264 @code{try}, or @code{unwind_protect} block.
2265 
2266 As an index of an array, the magic index @qcode{"end"} refers to the
2267 last valid entry in an indexing operation.
2268 
2269 Example:
2270 
2271 @example
2272 @group
2273 @var{x} = [ 1 2 3; 4 5 6 ];
2274 @var{x}(1,end)
2275  @result{} 3
2276 @var{x}(end,1)
2277  @result{} 4
2278 @var{x}(end,end)
2279  @result{} 6
2280 @end group
2281 @end example
2282 
2283 Programming notes:
2284 @enumerate
2285 @item
2286 The @code{end} keyword cannot be used within @code{subsref},
2287 @code{subsasgn}, or @code{substruct} for manual indexing operations.
2288 
2289 @item
2290 For custom classes, to enable use of @code{end} in indexing expressions it
2291 must be overloaded with a function definition such as:
2292 @example
2293 @group
2294 function last_index = end (obj, end_dim, ndim_obj)
2295   if (end_dim == ndim_obj)
2296     last_index = prod (size (obj)(end_dim:ndim_obj));
2297   else
2298     last_index = size (obj, end_dim);
2299   endif
2300 endfunction
2301 @end group
2302 @end example
2303 For more information see
2304 @ref{Object Oriented Programming, , Object Oriented Programming}.
2305 @end enumerate
2306 
2307 @seealso{for, parfor, if, do, while, function, switch, try, unwind_protect}
2308 @end deftypefn */)
2309 {
2310  tree_evaluator& tw = interp.get_evaluator ();
2311 
2312  return tw.evaluate_end_expression (args);
2313 }
2314 
2315 /*
2316 %!test <*58830>
2317 %! fail ("__undef_sym__ (end)",
2318 %! "invalid use of 'end': may only be used to index existing value");
2319 
2320 %!test <*58953>
2321 %! x = 1:10;
2322 %! assert (x(end), 10);
2323 %! assert (x(minus (end, 1)), 9);
2324 %! assert (x(minus (minus (end, 1), 1)), 8);
2325 */
2326 
2329 {
2330  std::list<octave_value> arg_vals;
2331 
2332  for (auto elt : *args)
2333  {
2334  // FIXME: is it possible for elt to be invalid?
2335 
2336  if (! elt)
2337  break;
2338 
2339  // Evaluate with unknown number of output arguments
2340  octave_value tmp = elt->evaluate (*this, -1);
2341 
2342  if (tmp.is_cs_list ())
2343  {
2344  octave_value_list tmp_ovl = tmp.list_value ();
2345 
2346  for (octave_idx_type i = 0; i < tmp_ovl.length (); i++)
2347  arg_vals.push_back (tmp_ovl(i));
2348  }
2349  else if (tmp.is_defined ())
2350  arg_vals.push_back (tmp);
2351  }
2352 
2353  return octave_value_list (arg_vals);
2354 }
2355 
2358 (tree_parameter_list *ret_list, int nargout, const Cell& varargout)
2359 {
2360  octave_idx_type vlen = varargout.numel ();
2361  int len = ret_list->length ();
2362 
2363  // Special case. Will do a shallow copy.
2364  if (len == 0)
2365  return varargout;
2366  else
2367  {
2368  int i = 0;
2369 
2370  if (nargout <= len)
2371  {
2372  int nout = nargout > 0 ? nargout : 1;
2373  octave_value_list retval (nout);
2374 
2375  for (tree_decl_elt *elt : *ret_list)
2376  {
2377  if (nargout == 0 && ! is_defined (elt->ident ()))
2378  break;
2379 
2380  if (is_defined (elt->ident ()))
2381  retval(i) = evaluate (elt);
2382 
2383  i++;
2384 
2385  if (i == nout)
2386  break;
2387  }
2388 
2389  return retval;
2390  }
2391  else
2392  {
2393  octave_value_list retval (len + vlen);
2394 
2395  for (tree_decl_elt *elt : *ret_list)
2396  {
2397  if (is_defined (elt->ident ()))
2398  retval(i) = evaluate (elt);
2399 
2400  i++;
2401  }
2402 
2403  for (octave_idx_type j = 0; j < vlen; j++)
2404  retval(i++) = varargout(j);
2405 
2406  return retval;
2407  }
2408  }
2409 }
2410 
2411 bool
2413 {
2414  bool retval = false;
2415 
2416  tree_identifier *id = elt->ident ();
2417  tree_expression *expr = elt->expression ();
2418 
2419  if (id && expr)
2420  {
2421  octave_lvalue ult = id->lvalue (*this);
2422 
2423  octave_value init_val = expr->evaluate (*this);
2424 
2425  ult.assign (octave_value::op_asn_eq, init_val);
2426 
2427  retval = true;
2428  }
2429 
2430  return retval;
2431 }
2432 
2433 bool
2435  const octave_value& val)
2436 {
2437  tree_expression *label = expr->case_label ();
2438 
2439  octave_value label_value = label->evaluate (*this);
2440 
2441  if (label_value.is_defined ())
2442  {
2443  if (label_value.iscell ())
2444  {
2445  Cell cell (label_value.cell_value ());
2446 
2447  for (octave_idx_type i = 0; i < cell.rows (); i++)
2448  {
2449  for (octave_idx_type j = 0; j < cell.columns (); j++)
2450  {
2451  bool match = val.is_equal (cell(i,j));
2452 
2453  if (match)
2454  return true;
2455  }
2456  }
2457  }
2458  else
2459  return val.is_equal (label_value);
2460  }
2461 
2462  return false;
2463 }
2464 
2465 void
2467 {
2468  m_call_stack.push (scope);
2469 }
2470 
2471 void
2473  const std::shared_ptr<stack_frame>& closure_frames)
2474 {
2475  m_call_stack.push (fcn, closure_frames);
2476 }
2477 
2478 void
2480  const stack_frame::local_vars_map& local_vars,
2481  const std::shared_ptr<stack_frame>& closure_frames)
2482 {
2483  m_call_stack.push (fcn, local_vars, closure_frames);
2484 }
2485 
2486 void
2488 {
2489  m_call_stack.push (script);
2490 }
2491 
2492 void
2494 {
2495  m_call_stack.push (fcn);
2496 }
2497 
2498 void
2500 {
2501  m_call_stack.pop ();
2502 }
2503 
2504 std::shared_ptr<stack_frame>
2506 {
2507  return m_call_stack.pop_return ();
2508 }
2509 
2510 int
2512 {
2513  return m_call_stack.current_line ();
2514 }
2515 
2516 int
2518 {
2519  return m_call_stack.current_column ();
2520 }
2521 
2522 int
2524 {
2525  return m_call_stack.debug_user_code_line ();
2526 }
2527 
2528 int
2530 {
2531  return m_call_stack.debug_user_code_column ();
2532 }
2533 
2534 void
2535 tree_evaluator::debug_where (std::ostream& os) const
2536 {
2537  std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame ();
2538 
2539  frm->display_stopped_in_message (os);
2540 }
2541 
2544 {
2545  return m_call_stack.current_user_code ();
2546 }
2547 
2550 {
2551  return m_call_stack.curr_fcn_unwind_protect_frame ();
2552 }
2553 
2556 {
2557  return m_call_stack.debug_user_code ();
2558 }
2559 
2561 tree_evaluator::current_function (bool skip_first) const
2562 {
2563  return m_call_stack.current_function (skip_first);
2564 }
2565 
2568 {
2569  return m_call_stack.current_function (true);
2570 }
2571 
2572 bool
2573 tree_evaluator::goto_frame (std::size_t n, bool verbose)
2574 {
2575  return m_call_stack.goto_frame (n, verbose);
2576 }
2577 
2578 void
2580 {
2581  m_call_stack.goto_caller_frame ();
2582 }
2583 
2584 void
2586 {
2587  m_call_stack.goto_base_frame ();
2588 }
2589 
2590 void
2592 {
2593  return m_call_stack.restore_frame (n);
2594 }
2595 
2596 std::string
2598 {
2599  return m_call_stack.get_dispatch_class ();
2600 }
2601 
2602 void
2603 tree_evaluator::set_dispatch_class (const std::string& class_name)
2604 {
2605  m_call_stack.set_dispatch_class (class_name);
2606 }
2607 
2608 bool
2610 {
2611  return m_call_stack.is_class_method_executing (dclass);
2612 }
2613 
2614 bool
2616 {
2617  return m_call_stack.is_class_constructor_executing (dclass);
2618 }
2619 
2620 std::list<std::shared_ptr<stack_frame>>
2622 {
2623  return m_call_stack.backtrace_frames (curr_user_frame);
2624 }
2625 
2626 std::list<std::shared_ptr<stack_frame>>
2628 {
2629  return m_call_stack.backtrace_frames ();
2630 }
2631 
2632 std::list<frame_info>
2634  bool print_subfn) const
2635 {
2636  return m_call_stack.backtrace_info (curr_user_frame, print_subfn);
2637 }
2638 
2639 std::list<frame_info>
2641 {
2642  return m_call_stack.backtrace_info ();
2643 }
2644 
2645 octave_map
2647  bool print_subfn) const
2648 {
2649  return m_call_stack.backtrace (curr_user_frame, print_subfn);
2650 }
2651 
2652 octave_map
2654 {
2655  return m_call_stack.backtrace ();
2656 }
2657 
2658 octave_map
2660 {
2661  return m_call_stack.empty_backtrace ();
2662 }
2663 
2664 std::string
2666 {
2667  std::list<frame_info> frames = backtrace_info ();
2668 
2669  std::ostringstream buf;
2670 
2671  for (const auto& frm : frames)
2672  {
2673  buf << " " << frm.fcn_name ();
2674 
2675  int line = frm.line ();
2676 
2677  if (line > 0)
2678  {
2679  buf << " at line " << line;
2680 
2681  int column = frm.column ();
2682 
2683  if (column > 0)
2684  buf << " column " << column;
2685 
2686  buf << "\n";
2687  }
2688  }
2689 
2690  return buf.str ();
2691 }
2692 
2693 void
2694 tree_evaluator::push_dummy_scope (const std::string& name)
2695 {
2696  symbol_scope dummy_scope (name + "$dummy");
2697 
2698  m_call_stack.push (dummy_scope);
2699 }
2700 
2701 void
2703 {
2704  m_call_stack.pop ();
2705 }
2706 
2709 {
2710  return m_call_stack.top_scope ();
2711 }
2712 
2715 {
2716  return m_call_stack.current_scope ();
2717 }
2718 
2719 void
2720 tree_evaluator::mlock (bool skip_first) const
2721 {
2722  octave_function *fcn = m_call_stack.current_function (skip_first);
2723 
2724  if (! fcn)
2725  error ("mlock: invalid use outside a function");
2726 
2727  if (fcn->is_builtin_function ())
2728  {
2729  warning ("mlock: locking built-in function has no effect");
2730  return;
2731  }
2732 
2733  fcn->lock ();
2734 }
2735 
2736 void
2737 tree_evaluator::munlock (bool skip_first) const
2738 {
2739  octave_function *fcn = m_call_stack.current_function (skip_first);
2740 
2741  if (! fcn)
2742  error ("munlock: invalid use outside a function");
2743 
2744  if (fcn->is_builtin_function ())
2745  {
2746  warning ("munlock: unlocking built-in function has no effect");
2747  return;
2748  }
2749 
2750  fcn->unlock ();
2751 }
2752 
2753 bool
2754 tree_evaluator::mislocked (bool skip_first) const
2755 {
2756  octave_function *fcn = m_call_stack.current_function (skip_first);
2757 
2758  if (! fcn)
2759  error ("mislocked: invalid use outside a function");
2760 
2761  return fcn->islocked ();
2762 }
2763 
2766 {
2767  return m_call_stack.max_stack_depth (args, nargout);
2768 }
2769 
2770 void
2772 {
2773  m_call_stack.display ();
2774 }
2775 
2777 tree_evaluator::find (const std::string& name)
2778 {
2779  std::shared_ptr<stack_frame> frame
2780  = m_call_stack.get_current_stack_frame ();
2781 
2782  octave_value val = frame->varval (name);
2783 
2784  if (val.is_defined ())
2785  return val;
2786 
2787  // Subfunction. I think it only makes sense to check for
2788  // subfunctions if we are currently executing a function defined
2789  // from a .m file.
2790 
2791  octave_value fcn = frame->find_subfunction (name);
2792 
2793  if (fcn.is_defined ())
2794  return fcn;
2795 
2796  symbol_table& symtab = m_interpreter.get_symbol_table ();
2797 
2798  return symtab.fcn_table_find (name, ovl ());
2799 }
2800 
2801 void
2803 {
2804  std::shared_ptr<stack_frame> frame
2805  = m_call_stack.get_current_stack_frame ();
2806 
2807  frame->clear_objects ();
2808 }
2809 
2810 void
2811 tree_evaluator::clear_variable (const std::string& name)
2812 {
2813  std::shared_ptr<stack_frame> frame
2814  = m_call_stack.get_current_stack_frame ();
2815 
2816  frame->clear_variable (name);
2817 }
2818 
2819 void
2820 tree_evaluator::clear_variable_pattern (const std::string& pattern)
2821 {
2822  std::shared_ptr<stack_frame> frame
2823  = m_call_stack.get_current_stack_frame ();
2824 
2825  frame->clear_variable_pattern (pattern);
2826 }
2827 
2828 void
2829 tree_evaluator::clear_variable_regexp (const std::string& pattern)
2830 {
2831  std::shared_ptr<stack_frame> frame
2832  = m_call_stack.get_current_stack_frame ();
2833 
2834  frame->clear_variable_regexp (pattern);
2835 }
2836 
2837 void
2839 {
2840  std::shared_ptr<stack_frame> frame
2841  = m_call_stack.get_current_stack_frame ();
2842 
2843  frame->clear_variables ();
2844 }
2845 
2846 void
2847 tree_evaluator::clear_global_variable (const std::string& name)
2848 {
2849  m_call_stack.clear_global_variable (name);
2850 }
2851 
2852 void
2854 {
2855  m_call_stack.clear_global_variable_pattern (pattern);
2856 }
2857 
2858 void
2860 {
2861  m_call_stack.clear_global_variable_regexp (pattern);
2862 }
2863 
2864 void
2866 {
2867  m_call_stack.clear_global_variables ();
2868 }
2869 
2870 void
2872 {
2873  // FIXME: should this also clear objects?
2874 
2875  clear_variables ();
2877 
2878  symbol_table& symtab = m_interpreter.get_symbol_table ();
2879 
2880  symtab.clear_functions (force);
2881 }
2882 
2883 void
2884 tree_evaluator::clear_symbol (const std::string& name)
2885 {
2886  // FIXME: are we supposed to do both here?
2887 
2888  clear_variable (name);
2889 
2890  symbol_table& symtab = m_interpreter.get_symbol_table ();
2891 
2892  symtab.clear_function (name);
2893 }
2894 
2895 void
2896 tree_evaluator::clear_symbol_pattern (const std::string& pattern)
2897 {
2898  // FIXME: are we supposed to do both here?
2899 
2900  clear_variable_pattern (pattern);
2901 
2902  symbol_table& symtab = m_interpreter.get_symbol_table ();
2903 
2904  symtab.clear_function_pattern (pattern);
2905 }
2906 
2907 void
2908 tree_evaluator::clear_symbol_regexp (const std::string& pattern)
2909 {
2910  // FIXME: are we supposed to do both here?
2911 
2912  clear_variable_regexp (pattern);
2913 
2914  symbol_table& symtab = m_interpreter.get_symbol_table ();
2915 
2916  symtab.clear_function_regexp (pattern);
2917 }
2918 
2919 std::list<std::string>
2921 {
2922  return m_call_stack.global_variable_names ();
2923 }
2924 
2925 std::list<std::string>
2927 {
2928  return m_call_stack.top_level_variable_names ();
2929 }
2930 
2931 std::list<std::string>
2933 {
2934  return m_call_stack.variable_names ();
2935 }
2936 
2937 // Return a pointer to the user-defined function FNAME. If FNAME is empty,
2938 // search backward for the first user-defined function in the
2939 // current call stack.
2940 
2942 tree_evaluator::get_user_code (const std::string& fname)
2943 {
2944  octave_user_code *user_code = nullptr;
2945 
2946  if (fname.empty ())
2947  user_code = m_call_stack.debug_user_code ();
2948  else
2949  {
2950  std::string name = fname;
2951 
2952  if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@')
2953  {
2954  auto beg = name.begin () + 2; // never have @/method
2955  auto end = name.end () - 1; // never have trailing '/'
2956  std::replace (beg, end, '/', sys::file_ops::dir_sep_char ());
2957  }
2958 
2959  std::size_t name_len = name.length ();
2960 
2961  if (name_len > 2 && name.substr (name_len-2) == ".m")
2962  name = name.substr (0, name_len-2);
2963 
2964  if (name.empty ())
2965  return nullptr;
2966 
2967  symbol_table& symtab = m_interpreter.get_symbol_table ();
2968 
2969  octave_value fcn;
2970  std::size_t p2 = std::string::npos;
2971 
2972  if (name[0] == '@')
2973  {
2974  std::size_t p1 = name.find (sys::file_ops::dir_sep_char (), 1);
2975 
2976  if (p1 == std::string::npos)
2977  return nullptr;
2978 
2979  std::string dispatch_type = name.substr (1, p1-1);
2980 
2981  p2 = name.find ('>', p1);
2982 
2983  std::string method = name.substr (p1+1, p2-1);
2984 
2985  // first check for classdef method
2986  cdef_manager& cdm = m_interpreter.get_cdef_manager ();
2987 
2988 // fcn = cdm.find_method_symbol (method, dispatch_type);
2989 
2990  cdef_class cls = cdm.find_class (dispatch_type, false);
2991  if (cls.ok () && cls.get_name () == dispatch_type)
2992  fcn = cls.find_method (method).get_function ();
2993 
2994  // If there is no classdef method, then try legacy classes.
2995  if (fcn.is_undefined ())
2996  fcn = symtab.find_method (method, dispatch_type);
2997  }
2998  else
2999  {
3000  p2 = name.find ('>');
3001 
3002  std::string main_fcn = name.substr (0, p2);
3003 
3004  fcn = symtab.find_function (main_fcn);
3005  }
3006 
3007  // List of function names sub1>sub2>...
3008  std::string subfuns;
3009 
3010  if (p2 != std::string::npos)
3011  subfuns = name.substr (p2+1);
3012 
3013  if (fcn.is_defined () && fcn.is_user_code ())
3014  user_code = fcn.user_code_value ();
3015 
3016  if (! user_code || subfuns.empty ())
3017  return user_code;
3018 
3019  fcn = user_code->find_subfunction (subfuns);
3020 
3021  if (fcn.is_undefined ())
3022  return nullptr;
3023 
3024  user_code = fcn.user_code_value ();
3025  }
3026 
3027  return user_code;
3028 }
3029 
3030 std::string
3032 {
3033  octave_function *curfcn = m_call_stack.current_function (skip_first);
3034 
3035  if (curfcn)
3036  return curfcn->name ();
3037 
3038  return "";
3039 }
3040 
3041 bool
3043 {
3044  return m_call_stack.current_user_code () != nullptr;
3045 }
3046 
3047 void
3049 {
3050  if (m_echo_state)
3051  {
3052  int line = cmd.line ();
3053  if (line < 0)
3054  line = 1;
3055  echo_code (line);
3056  m_echo_file_pos = line + 1;
3057  }
3058 
3059  if (m_debug_mode)
3060  do_breakpoint (cmd.is_active_breakpoint (*this));
3061 
3062  // FIXME: tree_decl_init_list is not derived from tree, so should it
3063  // really have an accept method?
3064 
3065  tree_decl_init_list *init_list = cmd.initializer_list ();
3066 
3067  if (init_list)
3068  init_list->accept (*this);
3069 }
3070 
3071 void
3073 {
3074  tree_identifier *id = elt.ident ();
3075 
3076  if (id)
3077  {
3078  if (elt.is_global ())
3079  m_call_stack.make_global (id->symbol ());
3080  else if (elt.is_persistent ())
3081  m_call_stack.make_persistent (id->symbol ());
3082  else
3083  error ("declaration list element not global or persistent");
3084 
3085  octave_lvalue ult = id->lvalue (*this);
3086 
3087  if (ult.is_undefined ())
3088  {
3089  tree_expression *expr = elt.expression ();
3090 
3091  octave_value init_val;
3092 
3093  if (expr)
3094  init_val = expr->evaluate (*this);
3095  else
3096  init_val = Matrix ();
3097 
3098  ult.assign (octave_value::op_asn_eq, init_val);
3099  }
3100  }
3101 }
3102 
3103 template <typename T>
3104 void
3105 tree_evaluator::execute_range_loop (const range<T>& rng, int line,
3106  octave_lvalue& ult,
3107  tree_statement_list *loop_body)
3108 {
3109  octave_idx_type steps = rng.numel ();
3110 
3111  if (math::isinf (rng.limit ()) || math::isinf (rng.base ()))
3112  warning_with_id ("Octave:infinite-loop",
3113  "FOR loop limit is infinite, will stop after %"
3114  OCTAVE_IDX_TYPE_FORMAT " steps", steps);
3115 
3116  for (octave_idx_type i = 0; i < steps; i++)
3117  {
3118  if (m_echo_state)
3119  m_echo_file_pos = line;
3120 
3121  octave_value val (rng.elem (i));
3122 
3123  ult.assign (octave_value::op_asn_eq, val);
3124 
3125  if (loop_body)
3126  loop_body->accept (*this);
3127 
3128  if (quit_loop_now ())
3129  break;
3130  }
3131 }
3132 
3133 void
3135 {
3136  int line = cmd.line ();
3137  if (line < 0)
3138  line = 1;
3139 
3140  if (m_echo_state)
3141  {
3142  echo_code (line);
3143  line++;
3144  }
3145 
3146  if (m_debug_mode)
3147  do_breakpoint (cmd.is_active_breakpoint (*this));
3148 
3149  // FIXME: need to handle PARFOR loops here using cmd.in_parallel ()
3150  // and cmd.maxproc_expr ();
3151 
3152  unwind_protect_var<bool> upv (m_in_loop_command, true);
3153 
3154  tree_expression *expr = cmd.control_expr ();
3155 
3156  octave_value rhs = expr->evaluate (*this);
3157 
3158  if (rhs.is_undefined ())
3159  return;
3160 
3161  tree_expression *lhs = cmd.left_hand_side ();
3162 
3163  octave_lvalue ult = lhs->lvalue (*this);
3164 
3165  tree_statement_list *loop_body = cmd.body ();
3166 
3167  if (rhs.is_range ())
3168  {
3169  // FIXME: is there a better way to dispatch here?
3170 
3171  if (rhs.is_double_type ())
3172  {
3173  execute_range_loop (rhs.range_value (), line, ult, loop_body);
3174  return;
3175  }
3176 
3177  // For now, enable only range<double>.
3178  }
3179 
3180  if (rhs.is_scalar_type ())
3181  {
3182  if (m_echo_state)
3183  m_echo_file_pos = line;
3184 
3185  ult.assign (octave_value::op_asn_eq, rhs);
3186 
3187  if (loop_body)
3188  loop_body->accept (*this);
3189 
3190  // Maybe decrement break and continue states.
3191  quit_loop_now ();
3192 
3193  return;
3194  }
3195 
3196  // Also handle any range types not explicitly handled above, though
3197  // not as efficiently as the specialized code above.
3198 
3199  if (rhs.is_range () || rhs.is_matrix_type () || rhs.iscell ()
3200  || rhs.is_string () || rhs.isstruct ())
3201  {
3202  // A matrix or cell is reshaped to 2 dimensions and iterated by
3203  // columns.
3204 
3205  dim_vector dv = rhs.dims ().redim (2);
3206 
3207  octave_idx_type nrows = dv(0);
3208  octave_idx_type steps = dv(1);
3209 
3210  octave_value arg = rhs;
3211  if (rhs.ndims () > 2)
3212  arg = arg.reshape (dv);
3213 
3214  if (nrows > 0 && steps > 0)
3215  {
3216  octave_value_list idx;
3217  octave_idx_type iidx;
3218 
3219  // for row vectors, use single index to speed things up.
3220  if (nrows == 1)
3221  {
3222  idx.resize (1);
3223  iidx = 0;
3224  }
3225  else
3226  {
3227  idx.resize (2);
3228  idx(0) = octave_value::magic_colon_t;
3229  iidx = 1;
3230  }
3231 
3232  for (octave_idx_type i = 1; i <= steps; i++)
3233  {
3234  if (m_echo_state)
3235  m_echo_file_pos = line;
3236 
3237  // index_op expects one-based indices.
3238  idx(iidx) = i;
3239  octave_value val = arg.index_op (idx);
3240 
3241  ult.assign (octave_value::op_asn_eq, val);
3242 
3243  if (loop_body)
3244  loop_body->accept (*this);
3245 
3246  if (quit_loop_now ())
3247  break;
3248  }
3249  }
3250  else
3251  {
3252  // Handle empty cases, while still assigning to loop var.
3253  ult.assign (octave_value::op_asn_eq, arg);
3254  }
3255 
3256  return;
3257  }
3258 
3259  error ("invalid type in for loop expression near line %d, column %d",
3260  cmd.line (), cmd.column ());
3261 }
3262 
3263 void
3265 {
3266  int line = cmd.line ();
3267  if (line < 0)
3268  line = 1;
3269 
3270  if (m_echo_state)
3271  {
3272  echo_code (line);
3273  line++;
3274  }
3275 
3276  if (m_debug_mode)
3277  do_breakpoint (cmd.is_active_breakpoint (*this));
3278 
3279  unwind_protect_var<bool> upv (m_in_loop_command, true);
3280 
3281  tree_expression *expr = cmd.control_expr ();
3282 
3283  octave_value rhs = expr->evaluate (*this);
3284 
3285  if (rhs.is_undefined ())
3286  return;
3287 
3288  if (! rhs.isstruct ())
3289  error ("in statement 'for [X, Y] = VAL', VAL must be a structure");
3290 
3291  // Cycle through structure elements. First element of id_list
3292  // is set to value and the second is set to the name of the
3293  // structure element.
3294 
3295  tree_argument_list *lhs = cmd.left_hand_side ();
3296 
3297  auto p = lhs->begin ();
3298 
3299  tree_expression *elt = *p++;
3300 
3301  octave_lvalue val_ref = elt->lvalue (*this);
3302 
3303  elt = *p;
3304 
3305  octave_lvalue key_ref = elt->lvalue (*this);
3306 
3307  const octave_map tmp_val = rhs.map_value ();
3308 
3309  tree_statement_list *loop_body = cmd.body ();
3310 
3311  string_vector keys = tmp_val.keys ();
3312 
3313  octave_idx_type nel = keys.numel ();
3314 
3315  for (octave_idx_type i = 0; i < nel; i++)
3316  {
3317  if (m_echo_state)
3318  m_echo_file_pos = line;
3319 
3320  std::string key = keys[i];
3321 
3322  const Cell val_lst = tmp_val.contents (key);
3323 
3324  octave_idx_type n = val_lst.numel ();
3325 
3326  octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst);
3327 
3328  val_ref.assign (octave_value::op_asn_eq, val);
3329  key_ref.assign (octave_value::op_asn_eq, key);
3330 
3331  if (loop_body)
3332  loop_body->accept (*this);
3333 
3334  if (quit_loop_now ())
3335  break;
3336  }
3337 }
3338 
3339 void
3341 {
3342  // For now, we just execute the commands serially.
3343 
3344  tree_statement_list *body = cmd.body ();
3345 
3346  if (body)
3347  body->accept (*this);
3348 }
3349 
3352 {
3353  // FIXME: should CMD_LIST be limited to a single expression?
3354  // I think that is what Matlab does.
3355 
3356  symbol_scope scope = afh.scope ();
3357  symbol_scope new_scope = scope ? scope.dup () : symbol_scope::invalid ();
3358 
3359  tree_parameter_list *param_list = afh.parameter_list ();
3360  tree_parameter_list *param_list_dup
3361  = param_list ? param_list->dup (new_scope) : nullptr;
3362 
3363  tree_parameter_list *ret_list = nullptr;
3364 
3365  tree_statement_list *stmt_list = nullptr;
3366 
3367  symbol_scope parent_scope = get_current_scope ();
3368 
3369  new_scope.set_parent (parent_scope);
3370  new_scope.set_primary_parent (parent_scope);
3371 
3372  tree_expression *expr = afh.expression ();
3373  if (expr)
3374  {
3375  tree_expression *expr_dup = expr->dup (new_scope);
3376  tree_statement *stmt = new tree_statement (expr_dup, nullptr);
3377  stmt_list = new tree_statement_list (stmt);
3378  }
3379 
3380  tree_anon_scopes anon_fcn_ctx (afh);
3381 
3382  std::set<std::string> free_vars = anon_fcn_ctx.free_variables ();
3383 
3384  stack_frame::local_vars_map local_vars;
3385 
3386  std::shared_ptr<stack_frame> frame
3387  = m_call_stack.get_current_stack_frame ();
3388 
3389  for (auto& name : free_vars)
3390  {
3391  octave_value val = frame->varval (name);
3392 
3393  if (val.is_defined ())
3394  local_vars[name] = val;
3395  }
3396 
3398  = new octave_user_function (new_scope, param_list_dup, ret_list,
3399  stmt_list);
3400 
3401  octave_function *curr_fcn = m_call_stack.current_function ();
3402 
3403  bool is_nested = false;
3404 
3405  if (curr_fcn)
3406  {
3407  // FIXME: maybe it would be better to just stash curr_fcn
3408  // instead of individual bits of info about it?
3409 
3410  // An anonymous function defined inside another nested function
3411  // or parent of a nested function also behaves like a nested
3412  // function.
3413 
3414  if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ())
3415  {
3416  is_nested = true;
3417  af->mark_as_nested_function ();
3418  new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1);
3419  }
3420 
3421  af->stash_dir_name (curr_fcn->dir_name ());
3422 
3423  new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ());
3424  new_scope.cache_dir_name (curr_fcn->dir_name ());
3425 
3426  // The following is needed so that class method dispatch works
3427  // properly for anonymous functions that wrap class methods.
3428 
3429  if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ())
3430  af->stash_dispatch_class (curr_fcn->dispatch_class ());
3431 
3432  af->stash_fcn_file_name (curr_fcn->fcn_file_name ());
3433  }
3434 
3436 
3437  octave_value ov_fcn (af);
3438 
3439  return (is_nested
3440  ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame))
3441  : octave_value (new octave_fcn_handle (ov_fcn, local_vars)));
3442 }
3443 
3446  int nargout,
3447  const octave_value_list& args)
3448 {
3449  octave_value_list retval;
3450 
3451  if (args.has_magic_colon ())
3452  error ("invalid use of colon in function argument list");
3453 
3454  profiler::enter<octave_builtin> block (m_profiler, builtin_function);
3455 
3456  octave_builtin::fcn fcn = builtin_function.function ();
3457 
3458  // If number of outputs unknown (and this is not a complete statement),
3459  // pass nargout=1 to the function being called
3460  if (nargout < 0)
3461  nargout = 1;
3462 
3463  if (fcn)
3464  retval = (*fcn) (args, nargout);
3465  else
3466  {
3467  octave_builtin::meth meth = builtin_function.method ();
3468 
3469  retval = (*meth) (m_interpreter, args, nargout);
3470  }
3471 
3472  // Do not allow null values to be returned from functions.
3473  // FIXME: perhaps true builtins should be allowed?
3474 
3475  retval.make_storable_values ();
3476 
3477  // Fix the case of a single undefined value.
3478  // This happens when a compiled function uses
3479  //
3480  // octave_value retval;
3481  //
3482  // instead of
3483  //
3484  // octave_value_list retval;
3485  //
3486  // the idiom is very common, so we solve that here.
3487 
3488  if (retval.length () == 1 && retval.xelem (0).is_undefined ())
3489  retval.clear ();
3490 
3491  return retval;
3492 }
3493 
3496  int nargout,
3497  const octave_value_list& args)
3498 {
3499  octave_value_list retval;
3500 
3501  if (args.has_magic_colon ())
3502  error ("invalid use of colon in function argument list");
3503 
3504  profiler::enter<octave_mex_function> block (m_profiler, mex_function);
3505 
3506  // If number of outputs unknown (and this is not a complete statement),
3507  // pass nargout=1 to the function being called
3508  if (nargout < 0)
3509  nargout = 1;
3510 
3511  retval = call_mex (mex_function, args, nargout);
3512 
3513  return retval;
3514 }
3515 
3518  int nargout,
3519  const octave_value_list& args)
3520 {
3521  octave_value_list retval;
3522 
3523  std::string file_name = user_script.fcn_file_name ();
3524 
3525  if (args.length () != 0 || nargout != 0)
3526  error ("invalid call to script %s", file_name.c_str ());
3527 
3528  tree_statement_list *cmd_list = user_script.body ();
3529 
3530  if (! cmd_list)
3531  return retval;
3532 
3533  // FIXME: Maybe this check belongs in the places where we push a new
3534  // stack frame? Or in the call_stack push method itself?
3535 
3536  if (m_call_stack.size () >= static_cast<std::size_t> (m_max_recursion_depth))
3537  error ("max_recursion_depth exceeded");
3538 
3539  unwind_protect_var<stmt_list_type> upv (m_statement_context, SC_SCRIPT);
3540 
3541  profiler::enter<octave_user_script> block (m_profiler, user_script);
3542 
3543  if (echo ())
3545 
3546  // FIXME: Should we be using tree_evaluator::eval here?
3547 
3548  cmd_list->accept (*this);
3549 
3550  if (m_returning)
3551  m_returning = 0;
3552 
3553  if (m_breaking)
3554  m_breaking--;
3555 
3556  return retval;
3557 }
3558 
3559 void
3561 {
3562  // ??
3563  panic_impossible ();
3564 }
3565 
3568  int nargout,
3569  const octave_value_list& xargs)
3570 {
3571  octave_value_list retval;
3572 
3573  // If this function is a classdef constructor, extract the first input
3574  // argument, which must be the partially constructed object instance.
3575 
3576  octave_value_list args (xargs);
3577 
3578  // FIXME: this probably shouldn't be a double-precision matrix.
3579  Matrix ignored_outputs = ignored_fcn_outputs ();
3580 
3581  unwind_protect frame;
3582 
3583  if (! user_function.is_anonymous_function ())
3584  {
3585  frame.protect_var (m_lvalue_list);
3586  m_lvalue_list = nullptr;
3587  }
3588 
3589  octave_value_list ret_args;
3590 
3591  int nargin = args.length ();
3592 
3593  // If number of outputs unknown (and this is not a complete statement),
3594  // pass nargout=1 to the function being called
3595  if (nargout < 0)
3596  nargout = 1;
3597 
3598  if (user_function.is_classdef_constructor ())
3599  {
3600  if (nargin > 0)
3601  {
3602  ret_args = args.slice (0, 1, true);
3603  --nargin;
3604  args = args.slice (1, nargin, true);
3605  }
3606  else
3607  panic_impossible ();
3608  }
3609 
3610  tree_parameter_list *param_list = user_function.parameter_list ();
3611 
3612  bool takes_varargs = false;
3613  int max_inputs = 0;
3614 
3615  if (param_list)
3616  {
3617  takes_varargs = param_list->takes_varargs ();
3618  max_inputs = param_list->length ();
3619  }
3620 
3621  if (! takes_varargs && nargin > max_inputs)
3622  {
3623  std::string name = user_function.name ();
3624 
3625  if (name.empty ())
3626  name = "@<anonymous>";
3627 
3628  error_with_id ("Octave:invalid-fun-call",
3629  "%s: function called with too many inputs",
3630  name.c_str ());
3631  }
3632 
3633  define_parameter_list_from_arg_vector (param_list, args);
3634 
3635  tree_parameter_list *ret_list = user_function.return_list ();
3636 
3637  if (ret_list && ! ret_list->takes_varargs ())
3638  {
3639  int max_outputs = ret_list->length ();
3640 
3641  if (nargout > max_outputs)
3642  {
3643  std::string name = user_function.name ();
3644 
3645  error_with_id ("Octave:invalid-fun-call",
3646  "%s: function called with too many outputs",
3647  name.c_str ());
3648  }
3649  }
3650 
3651  bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin,
3652  nargout, user_function.takes_varargs (),
3653  user_function.all_va_args (args));
3654 
3655  // For classdef constructor, pre-populate the output arguments
3656  // with the pre-initialized object instance, extracted above.
3657 
3658  if (user_function.is_classdef_constructor ())
3659  {
3660  if (! ret_list)
3661  error ("%s: invalid classdef constructor, no output argument defined",
3662  user_function.dispatch_class ().c_str ());
3663 
3664  define_parameter_list_from_arg_vector (ret_list, ret_args);
3665  }
3666 
3667  // FIXME: Maybe this check belongs in the places where we push a
3668  // new stack frame? Or in the call_stack push method itself?
3669 
3670  if (m_call_stack.size () >= static_cast<std::size_t> (m_max_recursion_depth))
3671  error ("max_recursion_depth exceeded");
3672 
3673  unwind_action act2 ([&user_function] () {
3674  user_function.restore_warning_states ();
3675  });
3676 
3677  // Evaluate the commands that make up the function.
3678 
3679  unwind_protect_var<stmt_list_type> upv (m_statement_context, SC_FUNCTION);
3680 
3681  tree_statement_list *cmd_list = user_function.body ();
3682 
3683  if (cmd_list)
3684  {
3686  block (m_profiler, user_function);
3687 
3688  if (echo ())
3690  user_function.fcn_file_name ());
3691 
3692  if (user_function.is_special_expr ())
3693  {
3694  panic_if (cmd_list->length () != 1);
3695 
3696  tree_statement *stmt = cmd_list->front ();
3697 
3698  tree_expression *expr = stmt->expression ();
3699 
3700  if (expr)
3701  {
3702  m_call_stack.set_location (stmt->line (), stmt->column ());
3703 
3704  retval = expr->evaluate_n (*this, nargout);
3705 
3706  // Don't allow a comma-separated list to escape (see bug #64783).
3707 
3708  if (nargout <= 1 && retval.length () == 1 && retval(0).is_cs_list ())
3709  retval = retval(0).list_value ();
3710  }
3711  }
3712  else
3713  cmd_list->accept (*this);
3714 
3715  if (m_returning)
3716  m_returning = 0;
3717 
3718  if (m_breaking)
3719  m_breaking--;
3720  }
3721 
3722  // Copy return values out.
3723 
3724  if (ret_list && ! user_function.is_special_expr ())
3725  {
3726  Cell varargout;
3727 
3728  if (ret_list->takes_varargs ())
3729  {
3730  octave_value varargout_varval = varval ("varargout");
3731 
3732  if (varargout_varval.is_defined ())
3733  varargout = varargout_varval.xcell_value ("varargout must be a cell array object");
3734  }
3735 
3736  retval = convert_return_list_to_const_vector (ret_list, nargout, varargout);
3737  }
3738 
3739  return retval;
3740 }
3741 
3742 void
3744 {
3745  // ??
3746  panic_impossible ();
3747 }
3748 
3749 void
3751 {
3752  panic_impossible ();
3753 }
3754 
3755 void
3757 {
3758  panic_impossible ();
3759 }
3760 
3761 void
3763 {
3764  octave_value fcn = cmd.function ();
3765 
3766  octave_function *f = fcn.function_value ();
3767 
3768  if (f)
3769  {
3770  std::string nm = f->name ();
3771 
3772  symbol_table& symtab = m_interpreter.get_symbol_table ();
3773 
3774  symtab.install_cmdline_function (nm, fcn);
3775 
3776  // Make sure that any variable with the same name as the new
3777  // function is cleared.
3778 
3779  assign (nm);
3780  }
3781 }
3782 
3783 void
3785 {
3786  panic_impossible ();
3787 }
3788 
3789 void
3791 {
3792  panic_impossible ();
3793 }
3794 
3795 void
3797 {
3798  if (m_echo_state)
3799  {
3800  int line = cmd.line ();
3801  if (line < 0)
3802  line = 1;
3803  echo_code (line);
3804  m_echo_file_pos = line + 1;
3805  }
3806 
3807  // FIXME: tree_if_command_list is not derived from tree, so should it
3808  // really have an accept method?
3809 
3810  tree_if_command_list *lst = cmd.cmd_list ();
3811 
3812  if (lst)
3813  lst->accept (*this);
3814 }
3815 
3816 void
3818 {
3819  for (tree_if_clause *tic : lst)
3820  {
3821  tree_expression *expr = tic->condition ();
3822 
3823  if (! (in_debug_repl ()
3824  && m_call_stack.current_frame () == m_debug_frame))
3825  m_call_stack.set_location (tic->line (), tic->column ());
3826 
3827  if (m_debug_mode && ! tic->is_else_clause ())
3828  do_breakpoint (tic->is_active_breakpoint (*this));
3829 
3830  if (tic->is_else_clause () || is_logically_true (expr, "if"))
3831  {
3832  tree_statement_list *stmt_lst = tic->commands ();
3833 
3834  if (stmt_lst)
3835  stmt_lst->accept (*this);
3836 
3837  break;
3838  }
3839  }
3840 }
3841 
3842 void
3844 {
3845  panic_impossible ();
3846 }
3847 
3848 void
3850 {
3851  panic_impossible ();
3852 }
3853 
3854 void
3856 {
3857  panic_impossible ();
3858 }
3859 
3860 void
3862 {
3863  panic_impossible ();
3864 }
3865 
3866 void
3868 {
3869  if (m_echo_state)
3870  {
3871  int line = cmd.line ();
3872  if (line < 0)
3873  line = 1;
3874  echo_code (line);
3875  m_echo_file_pos = line + 1;
3876  }
3877 
3878  if (m_debug_mode && cmd.is_end_of_fcn_or_script ())
3879  do_breakpoint (cmd.is_active_breakpoint (*this), true);
3880 }
3881 
3882 void
3884 {
3885  panic_impossible ();
3886 }
3887 
3888 void
3890 {
3891  panic_impossible ();
3892 }
3893 
3894 void
3896 {
3897  panic_impossible ();
3898 }
3899 
3900 void
3902 {
3903  panic_impossible ();
3904 }
3905 
3906 void
3908 {
3909  panic_impossible ();
3910 }
3911 
3912 void
3914 {
3915  if (m_echo_state)
3916  {
3917  int line = cmd.line ();
3918  if (line < 0)
3919  line = 1;
3920  echo_code (line);
3921  m_echo_file_pos = line + 1;
3922  }
3923 
3924  if (m_debug_mode)
3925  do_breakpoint (cmd.is_active_breakpoint (*this));
3926 
3927  // Act like dbcont.
3928 
3929  if (in_debug_repl () && m_call_stack.current_frame () == m_debug_frame)
3930  dbcont ();
3931  else if (m_statement_context == SC_FUNCTION
3932  || m_statement_context == SC_SCRIPT
3933  || m_in_loop_command)
3934  m_returning = 1;
3935 }
3936 
3937 void
3939 {
3940  panic_impossible ();
3941 }
3942 
3943 void
3945 {
3946  tree_command *cmd = stmt.command ();
3947  tree_expression *expr = stmt.expression ();
3948 
3949  if (cmd || expr)
3950  {
3951  if (! (in_debug_repl ()
3952  && m_call_stack.current_frame () == m_debug_frame))
3953  m_call_stack.set_location (stmt.line (), stmt.column ());
3954 
3955  try
3956  {
3957  if (cmd)
3958  {
3960  upv (m_lvalue_list, nullptr);
3961 
3962  cmd->accept (*this);
3963  }
3964  else
3965  {
3966  if (m_echo_state)
3967  {
3968  int line = stmt.line ();
3969  if (line < 0)
3970  line = 1;
3971  echo_code (line);
3972  m_echo_file_pos = line + 1;
3973  }
3974 
3975  if (m_debug_mode)
3976  do_breakpoint (expr->is_active_breakpoint (*this));
3977 
3978  // FIXME: maybe all of this should be packaged in
3979  // one virtual function that returns a flag saying whether
3980  // or not the expression will take care of binding ans and
3981  // printing the result.
3982 
3983  // FIXME: it seems that we should just have to
3984  // evaluate the expression and that should take care of
3985  // everything, binding ans as necessary?
3986 
3987  octave_value tmp_result = expr->evaluate (*this, 0);
3988 
3989  if (tmp_result.is_defined ())
3990  {
3991  bool do_bind_ans = false;
3992 
3993  if (expr->is_identifier ())
3994  do_bind_ans = ! is_variable (expr);
3995  else
3996  do_bind_ans = ! expr->is_assignment_expression ();
3997 
3998  if (do_bind_ans)
3999  bind_ans (tmp_result, expr->print_result ()
4001  }
4002  }
4003  }
4004  catch (const std::bad_alloc&)
4005  {
4006  // FIXME: We want to use error_with_id here so that give users
4007  // control over this error message but error_with_id will
4008  // require some memory allocations. Is there anything we can
4009  // do to make those more likely to succeed?
4010 
4011  error_with_id ("Octave:bad-alloc",
4012  "out of memory or dimension too large for Octave's index type");
4013  }
4014  catch (const interrupt_exception&)
4015  {
4016  // If we are debugging, then continue with next statement.
4017  // Otherwise, jump out of here.
4018 
4019  if (m_debug_mode)
4020  m_interpreter.recover_from_exception ();
4021  else
4022  throw;
4023  }
4024  catch (const execution_exception& ee)
4025  {
4026  error_system& es = m_interpreter.get_error_system ();
4027 
4028  if ((m_interpreter.interactive ()
4030  && ((es.debug_on_error ()
4031  && m_bp_table.debug_on_err (es.last_error_id ()))
4032  || (es.debug_on_caught ()
4033  && m_bp_table.debug_on_caught (es.last_error_id ())))
4034  && in_user_code ())
4035  {
4036  es.save_exception (ee);
4037  es.display_exception (ee);
4038 
4039  enter_debugger ();
4040 
4041  // It doesn't make sense to continue execution after an
4042  // error occurs so force the debugger to quit all debug
4043  // levels and return the the top prompt.
4044 
4045  throw quit_debug_exception (true);
4046  }
4047  else
4048  throw;
4049  }
4050  }
4051 }
4052 
4053 void
4055 {
4056  // FIXME: commented out along with else clause below.
4057  // static octave_value_list empty_list;
4058 
4059  auto p = lst.begin ();
4060 
4061  if (p != lst.end ())
4062  {
4063  while (true)
4064  {
4065  tree_statement *elt = *p++;
4066 
4067  if (! elt)
4068  error ("invalid statement found in statement list!");
4069 
4070  octave_quit ();
4071 
4072  elt->accept (*this);
4073 
4074  if (m_breaking || m_continuing)
4075  break;
4076 
4077  if (m_returning)
4078  break;
4079 
4080  if (p == lst.end ())
4081  break;
4082  else
4083  {
4084  // Clear previous values before next statement is
4085  // evaluated so that we aren't holding an extra
4086  // reference to a value that may be used next. For
4087  // example, in code like this:
4088  //
4089  // X = rand (N); # refcount for X should be 1
4090  // # after this statement
4091  //
4092  // X(idx) = val; # no extra copy of X should be
4093  // # needed, but we will be faked
4094  // # out if retval is not cleared
4095  // # between statements here
4096 
4097  // result_values = empty_list;
4098  }
4099  }
4100  }
4101 }
4102 
4103 void
4105 {
4106  panic_impossible ();
4107 }
4108 
4109 void
4111 {
4112  panic_impossible ();
4113 }
4114 
4115 void
4117 {
4118  if (m_echo_state)
4119  {
4120  int line = cmd.line ();
4121  if (line < 0)
4122  line = 1;
4123  echo_code (line);
4124  m_echo_file_pos = line + 1;
4125  }
4126 
4127  if (m_debug_mode)
4128  do_breakpoint (cmd.is_active_breakpoint (*this));
4129 
4130  tree_expression *expr = cmd.switch_value ();
4131 
4132  if (! expr)
4133  error ("missing value in switch command near line %d, column %d",
4134  cmd.line (), cmd.column ());
4135 
4136  octave_value val = expr->evaluate (*this);
4137 
4138  tree_switch_case_list *lst = cmd.case_list ();
4139 
4140  if (lst)
4141  {
4142  for (tree_switch_case *t : *lst)
4143  {
4144  if (t->is_default_case () || switch_case_label_matches (t, val))
4145  {
4146  tree_statement_list *stmt_lst = t->commands ();
4147 
4148  if (stmt_lst)
4149  stmt_lst->accept (*this);
4150 
4151  break;
4152  }
4153  }
4154  }
4155 }
4156 
4157 void
4159 {
4160  if (m_echo_state)
4161  {
4162  int line = cmd.line ();
4163  if (line < 0)
4164  line = 1;
4165  echo_code (line);
4166  m_echo_file_pos = line + 1;
4167  }
4168 
4169  bool execution_error = false;
4170  octave_scalar_map err_map;
4171 
4172  tree_statement_list *try_code = cmd.body ();
4173 
4174  if (try_code)
4175  {
4176  // unwind frame before catch block
4177 
4178  unwind_protect frame;
4179 
4180  interpreter_try (frame);
4181 
4182  // The catch code is *not* added to unwind_protect stack; it
4183  // doesn't need to be run on interrupts.
4184 
4185  try
4186  {
4187  try_code->accept (*this);
4188  }
4189  catch (const execution_exception& ee)
4190  {
4191  execution_error = true;
4192 
4193  error_system& es = m_interpreter.get_error_system ();
4194 
4195  es.save_exception (ee);
4196 
4197  err_map.assign ("message", es.last_error_message ());
4198  err_map.assign ("identifier", es.last_error_id ());
4199  err_map.assign ("stack", es.last_error_stack ());
4200 
4201  m_interpreter.recover_from_exception ();
4202  }
4203 
4204  // Actions attached to unwind_protect frame will run here, prior
4205  // to executing the catch block.
4206  }
4207 
4208  if (execution_error)
4209  {
4210  tree_statement_list *catch_code = cmd.cleanup ();
4211 
4212  if (catch_code)
4213  {
4214  tree_identifier *expr_id = cmd.identifier ();
4215 
4216  if (expr_id)
4217  {
4218  octave_lvalue ult = expr_id->lvalue (*this);
4219 
4220  ult.assign (octave_value::op_asn_eq, err_map);
4221  }
4222 
4223  // perform actual "catch" block
4224  catch_code->accept (*this);
4225  }
4226  }
4227 }
4228 
4229 void
4231 {
4232  unwind_protect frame;
4233 
4236 
4237  // We want to preserve the last location info for possible
4238  // backtracking.
4239 
4240  frame.add (&call_stack::set_line, &m_call_stack,
4241  m_call_stack.current_line ());
4242 
4243  frame.add (&call_stack::set_column, &m_call_stack,
4244  m_call_stack.current_column ());
4245 
4246  // Similarly, if we have seen a return or break statement, allow all
4247  // the cleanup code to run before returning or handling the break.
4248  // We don't have to worry about continue statements because they can
4249  // only occur in loops.
4250 
4251  frame.protect_var (m_returning);
4252  m_returning = 0;
4253 
4254  frame.protect_var (m_breaking);
4255  m_breaking = 0;
4256 
4257  try
4258  {
4259  if (list)
4260  list->accept (*this);
4261  }
4262  catch (const execution_exception& ee)
4263  {
4264  error_system& es = m_interpreter.get_error_system ();
4265 
4266  es.save_exception (ee);
4267  m_interpreter.recover_from_exception ();
4268 
4269  if (m_breaking || m_returning)
4270  frame.discard (2);
4271  else
4272  frame.run (2);
4273 
4274  frame.discard (2);
4275 
4276  throw;
4277  }
4278 
4279  // The unwind_protects are popped off the stack in the reverse of
4280  // the order they are pushed on.
4281 
4282  // FIXME: these statements say that if we see a break or
4283  // return statement in the cleanup block, that we want to use the
4284  // new value of the breaking or returning flag instead of restoring
4285  // the previous value. Is that the right thing to do? I think so.
4286  // Consider the case of
4287  //
4288  // function foo ()
4289  // unwind_protect
4290  // fprintf (stderr, "1: this should always be executed\n");
4291  // break;
4292  // fprintf (stderr, "1: this should never be executed\n");
4293  // unwind_protect_cleanup
4294  // fprintf (stderr, "2: this should always be executed\n");
4295  // return;
4296  // fprintf (stderr, "2: this should never be executed\n");
4297  // end_unwind_protect
4298  // endfunction
4299  //
4300  // If we reset the value of the breaking flag, both the returning
4301  // flag and the breaking flag will be set, and we shouldn't have
4302  // both. So, use the most recent one. If there is no return or
4303  // break in the cleanup block, the values should be reset to
4304  // whatever they were when the cleanup block was entered.
4305 
4306  if (m_breaking || m_returning)
4307  frame.discard (2);
4308  else
4309  frame.run (2);
4310 }
4311 
4312 void
4314 {
4315  if (m_echo_state)
4316  {
4317  int line = cmd.line ();
4318  if (line < 0)
4319  line = 1;
4320  echo_code (line);
4321  m_echo_file_pos = line + 1;
4322  }
4323 
4324  tree_statement_list *cleanup_code = cmd.cleanup ();
4325 
4326  tree_statement_list *unwind_protect_code = cmd.body ();
4327 
4328  if (unwind_protect_code)
4329  {
4330  try
4331  {
4332  unwind_protect_code->accept (*this);
4333  }
4334  catch (const execution_exception& ee)
4335  {
4336  error_system& es = m_interpreter.get_error_system ();
4337 
4338  // FIXME: Maybe we should be able to temporarily set the
4339  // interpreter's exception handling state to something "safe"
4340  // while the cleanup block runs instead of just resetting it
4341  // here?
4342  es.save_exception (ee);
4343  m_interpreter.recover_from_exception ();
4344 
4345  // Run the cleanup code on exceptions, so that it is run even
4346  // in case of interrupt or out-of-memory.
4347  do_unwind_protect_cleanup_code (cleanup_code);
4348 
4349  // If an error occurs inside the cleanup code, a new
4350  // exception will be thrown instead of the original.
4351  throw;
4352  }
4353  catch (const interrupt_exception&)
4354  {
4355  // The comments above apply here as well.
4356  m_interpreter.recover_from_exception ();
4357  do_unwind_protect_cleanup_code (cleanup_code);
4358  throw;
4359  }
4360 
4361  // Also execute the unwind_protect_cleanump code if the
4362  // unwind_protect block runs without error.
4363  do_unwind_protect_cleanup_code (cleanup_code);
4364  }
4365 }
4366 
4367 void
4369 {
4370  int line = cmd.line ();
4371  if (line < 0)
4372  line = 1;
4373 
4374  if (m_echo_state)
4375  {
4376  echo_code (line);
4377  line++;
4378  }
4379 
4380  unwind_protect_var<bool> upv (m_in_loop_command, true);
4381 
4382  tree_expression *expr = cmd.condition ();
4383 
4384  if (! expr)
4385  panic_impossible ();
4386 
4387  for (;;)
4388  {
4389  if (m_echo_state)
4390  m_echo_file_pos = line;
4391 
4392  if (m_debug_mode)
4393  do_breakpoint (cmd.is_active_breakpoint (*this));
4394 
4395  if (is_logically_true (expr, "while"))
4396  {
4397  tree_statement_list *loop_body = cmd.body ();
4398 
4399  if (loop_body)
4400  loop_body->accept (*this);
4401 
4402  if (quit_loop_now ())
4403  break;
4404  }
4405  else
4406  break;
4407  }
4408 }
4409 
4410 void
4412 {
4413  int line = cmd.line ();
4414  if (line < 0)
4415  line = 1;
4416 
4417  if (m_echo_state)
4418  {
4419  echo_code (line);
4420  line++;
4421  }
4422 
4423  unwind_protect_var<bool> upv (m_in_loop_command, true);
4424 
4425  tree_expression *expr = cmd.condition ();
4426 
4427  if (! expr)
4428  panic_impossible ();
4429 
4430  for (;;)
4431  {
4432  if (m_echo_state)
4433  m_echo_file_pos = line;
4434 
4435  tree_statement_list *loop_body = cmd.body ();
4436 
4437  if (loop_body)
4438  loop_body->accept (*this);
4439 
4440  if (quit_loop_now ())
4441  break;
4442 
4443  if (m_debug_mode)
4444  do_breakpoint (cmd.is_active_breakpoint (*this));
4445 
4446  if (is_logically_true (expr, "do-until"))
4447  break;
4448  }
4449 }
4450 
4451 void
4453 {
4454  panic_impossible ();
4455 }
4456 
4457 void
4459 {
4460  panic_impossible ();
4461 }
4462 
4463 void
4464 tree_evaluator::bind_ans (const octave_value& val, bool print)
4465 {
4466  static std::string ans = "ans";
4467 
4468  if (val.is_defined ())
4469  {
4470  if (val.is_cs_list ())
4471  {
4472  octave_value_list lst = val.list_value ();
4473 
4474  for (octave_idx_type i = 0; i < lst.length (); i++)
4475  bind_ans (lst(i), print);
4476  }
4477  else
4478  {
4479  // FIXME: Maybe assign could also return the assigned value,
4480  // just for convenience?
4481 
4482  assign (ans, val);
4483 
4484  if (print)
4485  {
4486  // Use varval instead of displaying VAL directly so that
4487  // we get the right type and value for things like
4488  // magic_int values that may mutate when stored.
4489 
4490  octave_value_list args = ovl (varval (ans));
4491  args.stash_name_tags (string_vector (ans));
4492  m_interpreter.feval ("display", args);
4493  }
4494  }
4495  }
4496 }
4497 
4498 void
4499 tree_evaluator::do_breakpoint (tree_statement& stmt)
4500 {
4501  do_breakpoint (stmt.is_active_breakpoint (*this),
4502  stmt.is_end_of_fcn_or_script ());
4503 }
4504 
4505 void
4506 tree_evaluator::do_breakpoint (bool is_breakpoint,
4507  bool is_end_of_fcn_or_script)
4508 {
4509  bool break_on_this_statement = false;
4510 
4511  if (is_breakpoint)
4512  break_on_this_statement = true;
4513  else if (m_dbstep_flag > 0)
4514  {
4515  if (m_call_stack.current_frame () == m_debug_frame)
4516  {
4517  if (m_dbstep_flag == 1 || is_end_of_fcn_or_script)
4518  {
4519  // We get here if we are doing a "dbstep" or a "dbstep N" and
4520  // the count has reached 1 so that we must stop and return to
4521  // debug prompt. Alternatively, "dbstep N" has been used but
4522  // the end of the frame has been reached so we stop at the last
4523  // line and return to prompt.
4524 
4525  break_on_this_statement = true;
4526  }
4527  else
4528  {
4529  // Executing "dbstep N". Decrease N by one and continue.
4530 
4531  m_dbstep_flag--;
4532  }
4533 
4534  }
4535  else if (m_dbstep_flag == 1
4536  && m_call_stack.current_frame () < m_debug_frame)
4537  {
4538  // We stepped out from the end of a function.
4539 
4540  m_debug_frame = m_call_stack.current_frame ();
4541 
4542  break_on_this_statement = true;
4543  }
4544  }
4545  else if (m_dbstep_flag == -1)
4546  {
4547  // We get here if we are doing a "dbstep in".
4548 
4549  break_on_this_statement = true;
4550 
4551  m_debug_frame = m_call_stack.current_frame ();
4552  }
4553  else if (m_dbstep_flag == -2)
4554  {
4555  // We get here if we are doing a "dbstep out". Check for end of
4556  // function and whether the current frame is the same as the
4557  // cached value because we want to step out from the frame where
4558  // "dbstep out" was evaluated, not from any functions called from
4559  // that frame.
4560 
4561  if (is_end_of_fcn_or_script
4562  && m_call_stack.current_frame () == m_debug_frame)
4563  m_dbstep_flag = -1;
4564  }
4565 
4566  if (! break_on_this_statement)
4567  break_on_this_statement = m_break_on_next_stmt;
4568 
4569  m_break_on_next_stmt = false;
4570 
4571  if (break_on_this_statement)
4572  {
4573  m_dbstep_flag = 0;
4574 
4575  enter_debugger ();
4576  }
4577 }
4578 
4579 bool
4580 tree_evaluator::is_logically_true (tree_expression *expr,
4581  const char *warn_for)
4582 {
4583  bool expr_value = false;
4584 
4585  m_call_stack.set_location (expr->line (), expr->column ());
4586 
4587  octave_value t1 = expr->evaluate (*this);
4588 
4589  if (t1.is_defined ())
4590  return t1.is_true ();
4591  else
4592  error ("%s: undefined value used in conditional expression", warn_for);
4593 
4594  return expr_value;
4595 }
4596 
4599  int nargout)
4600 {
4601  return set_internal_variable (m_max_recursion_depth, args, nargout,
4602  "max_recursion_depth", 0);
4603 }
4604 
4606 tree_evaluator::glob_symbol_info (const std::string& pattern) const
4607 {
4608  return m_call_stack.glob_symbol_info (pattern);
4609 }
4610 
4612 tree_evaluator::regexp_symbol_info (const std::string& pattern) const
4613 {
4614  return m_call_stack.regexp_symbol_info (pattern);
4615 }
4616 
4619 {
4620  return m_call_stack.get_symbol_info ();
4621 }
4622 
4625 {
4626  return m_call_stack.top_scope_symbol_info ();
4627 }
4628 
4629 octave_map
4631 {
4632  Cell fcn_names (dim_vector (m_autoload_map.size (), 1));
4633  Cell file_names (dim_vector (m_autoload_map.size (), 1));
4634 
4635  octave_idx_type i = 0;
4636  for (const auto& fcn_fname : m_autoload_map)
4637  {
4638  fcn_names(i) = fcn_fname.first;
4639  file_names(i) = fcn_fname.second;
4640 
4641  i++;
4642  }
4643 
4644  octave_map m;
4645 
4646  m.assign ("function", fcn_names);
4647  m.assign ("file", file_names);
4648 
4649  return m;
4650 }
4651 
4652 std::string
4653 tree_evaluator::lookup_autoload (const std::string& nm) const
4654 {
4655  std::string retval;
4656 
4657  auto p = m_autoload_map.find (nm);
4658 
4659  if (p != m_autoload_map.end ())
4660  {
4661  load_path& lp = m_interpreter.get_load_path ();
4662 
4663  retval = lp.find_file (p->second);
4664  }
4665 
4666  return retval;
4667 }
4668 
4669 std::list<std::string>
4671 {
4672  std::list<std::string> names;
4673 
4674  for (const auto& fcn_fname : m_autoload_map)
4675  names.push_back (fcn_fname.first);
4676 
4677  return names;
4678 }
4679 
4680 std::list<std::string>
4681 tree_evaluator::reverse_lookup_autoload (const std::string& nm) const
4682 {
4683  std::list<std::string> names;
4684 
4685  for (const auto& fcn_fname : m_autoload_map)
4686  if (nm == fcn_fname.second)
4687  names.push_back (fcn_fname.first);
4688 
4689  return names;
4690 }
4691 
4692 void
4693 tree_evaluator::add_autoload (const std::string& fcn,
4694  const std::string& nm)
4695 {
4696  m_autoload_map[fcn] = check_autoload_file (nm);
4697 }
4698 
4699 void
4700 tree_evaluator::remove_autoload (const std::string& fcn,
4701  const std::string& nm)
4702 {
4703  check_autoload_file (nm);
4704 
4705  // Remove function from symbol table and autoload map.
4706  symbol_table& symtab = m_interpreter.get_symbol_table ();
4707 
4708  symtab.clear_dld_function (fcn);
4709 
4710  m_autoload_map.erase (fcn);
4711 }
4712 
4715 {
4716  return set_internal_variable (m_whos_line_format, args, nargout,
4717  "whos_line_format");
4718 }
4719 
4722 {
4723  return set_internal_variable (m_silent_functions, args, nargout,
4724  "silent_functions");
4725 }
4726 
4729 {
4730  return set_internal_variable (m_string_fill_char, args, nargout,
4731  "string_fill_char");
4732 }
4733 
4734 // Final step of processing an indexing error. Add the name of the
4735 // variable being indexed, if any, then issue an error. (Will this also
4736 // be needed by pt-lvalue, which calls subsref?)
4737 
4738 void
4740  const tree_expression *expr)
4741 {
4742  std::string extra_message;
4743 
4744  if (is_variable (expr))
4745  {
4746  std::string var = expr->name ();
4747 
4748  ie.set_var (var);
4749 
4750  symbol_table& symtab = m_interpreter.get_symbol_table ();
4751 
4752  octave_value fcn = symtab.find_function (var);
4753 
4754  if (fcn.is_function ())
4755  {
4756  octave_function *fp = fcn.function_value ();
4757 
4758  if (fp && fp->name () == var)
4759  extra_message
4760  = " (note: variable '" + var + "' shadows function)";
4761  }
4762  }
4763 
4764  std::string msg = ie.message () + extra_message;
4765 
4766  error_with_id (ie.err_id (), "%s", msg.c_str ());
4767 }
4768 
4770 tree_evaluator::do_who (int argc, const string_vector& argv,
4771  bool return_list, bool verbose)
4772 {
4773  return m_call_stack.do_who (argc, argv, return_list, verbose);
4774 }
4775 
4778  const string_vector& arg_nm)
4779 {
4780  octave_value_list retval;
4781 
4782  if (args)
4783  {
4785  upv (m_lvalue_list, nullptr);
4786 
4787  int len = args->length ();
4788 
4789  unwind_protect_var<int> upv2 (m_index_position);
4790  unwind_protect_var<int> upv3 (m_num_indices);
4791 
4792  m_num_indices = len;
4793 
4794  std::list<octave_value> arg_vals;
4795 
4796  int k = 0;
4797 
4798  for (auto elt : *args)
4799  {
4800  // FIXME: is it possible for elt to be invalid?
4801 
4802  if (! elt)
4803  break;
4804 
4805  m_index_position = k++;
4806 
4807  octave_value tmp = elt->evaluate (*this);
4808 
4809  if (tmp.is_cs_list ())
4810  {
4811  octave_value_list tmp_ovl = tmp.list_value ();
4812 
4813  for (octave_idx_type i = 0; i < tmp_ovl.length (); i++)
4814  arg_vals.push_back (tmp_ovl(i));
4815  }
4816  else if (tmp.is_defined ())
4817  arg_vals.push_back (tmp);
4818  }
4819 
4820  retval = octave_value_list (arg_vals);
4821  }
4822 
4823  octave_idx_type n = retval.length ();
4824 
4825  if (n > 0)
4826  retval.stash_name_tags (arg_nm);
4827 
4828  return retval;
4829 }
4830 
4831 std::list<octave_lvalue>
4833 {
4834  std::list<octave_lvalue> retval;
4835 
4836  for (tree_expression *elt : *lhs)
4837  retval.push_back (elt->lvalue (*this));
4838 
4839  return retval;
4840 }
4841 
4842 void
4843 tree_evaluator::push_echo_state (int type, const std::string& file_name,
4844  int pos)
4845 {
4846  unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame ();
4847 
4848  if (frame)
4849  {
4850  push_echo_state_cleanup (*frame);
4851 
4852  set_echo_state (type, file_name, pos);
4853  }
4854 }
4855 
4856 void
4857 tree_evaluator::set_echo_state (int type, const std::string& file_name,
4858  int pos)
4859 {
4860  m_echo_state = echo_this_file (file_name, type);
4861 
4862  m_echo_file_name = file_name;
4863  m_echo_file_pos = pos;
4864 }
4865 
4866 void
4867 tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name,
4868  int pos)
4869 {
4870  m_echo_state = state;
4871 
4872  m_echo_file_name = file_name;
4873  m_echo_file_pos = pos;
4874 }
4875 
4876 void
4877 tree_evaluator::maybe_set_echo_state ()
4878 {
4879  octave_function *caller = caller_function ();
4880 
4881  if (caller && caller->is_user_code ())
4882  {
4883  octave_user_code *fcn = dynamic_cast<octave_user_code *> (caller);
4884 
4885  int type = fcn->is_user_function () ? ECHO_FUNCTIONS : ECHO_SCRIPTS;
4886 
4887  std::string file_name = fcn->fcn_file_name ();
4888 
4889  // We want the line where "echo" was called, not the line number
4890  // stored in the stack frame that was created for the echo
4891  // function (that will always be -1).
4892 
4893  int pos = m_call_stack.current_user_code_line ();
4894 
4895  if (pos < 0)
4896  pos = 1;
4897 
4898  set_echo_state (type, file_name, pos);
4899  }
4900 }
4901 
4902 void
4903 tree_evaluator::push_echo_state_cleanup (unwind_protect& frame)
4904 {
4905  frame.add (&tree_evaluator::uwp_set_echo_state, this,
4906  m_echo_state, m_echo_file_name, m_echo_file_pos);
4907 }
4908 
4909 bool
4910 tree_evaluator::maybe_push_echo_state_cleanup ()
4911 {
4912  // This function is expected to be called from ECHO, which would be
4913  // the top of the call stack. If the caller of ECHO is a
4914  // user-defined function or script, then set up unwind-protect
4915  // elements to restore echo state.
4916 
4917  unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame ();
4918 
4919  if (frame)
4920  {
4921  push_echo_state_cleanup (*frame);
4922  return true;
4923  }
4924 
4925  return false;
4926 }
4927 
4928 
4931 {
4932  bool cleanup_pushed = maybe_push_echo_state_cleanup ();
4933 
4934  string_vector argv = args.make_argv ();
4935 
4936  switch (args.length ())
4937  {
4938  case 0:
4939  if ((m_echo & ECHO_SCRIPTS) || (m_echo & ECHO_FUNCTIONS))
4940  {
4941  m_echo = ECHO_OFF;
4942  m_echo_files.clear ();
4943  }
4944  else
4945  m_echo = ECHO_SCRIPTS;
4946  break;
4947 
4948  case 1:
4949  {
4950  std::string arg0 = argv[0];
4951 
4952  if (arg0 == "on")
4953  m_echo = ECHO_SCRIPTS;
4954  else if (arg0 == "off")
4955  m_echo = ECHO_OFF;
4956  else
4957  {
4958  std::string file = fcn_file_in_path (arg0);
4959  file = sys::env::make_absolute (file);
4960 
4961  if (file.empty ())
4962  error ("echo: no such file %s", arg0.c_str ());
4963 
4964  if (m_echo & ECHO_ALL)
4965  {
4966  // Echo is enabled for all functions, so turn it off
4967  // for this one.
4968 
4969  m_echo_files[file] = false;
4970  }
4971  else
4972  {
4973  // Echo may be enabled for specific functions.
4974 
4975  auto p = m_echo_files.find (file);
4976 
4977  if (p == m_echo_files.end ())
4978  {
4979  // Not this one, so enable it.
4980 
4981  m_echo |= ECHO_FUNCTIONS;
4982  m_echo_files[file] = true;
4983  }
4984  else
4985  {
4986  // This one is already in the list. Flip the
4987  // status for it.
4988 
4989  p->second = ! p->second;
4990  }
4991  }
4992  }
4993  }
4994  break;
4995 
4996  case 2:
4997  {
4998  std::string arg0 = argv[0];
4999  std::string arg1 = argv[1];
5000 
5001  if (arg1 == "on" || arg1 == "off")
5002  std::swap (arg0, arg1);
5003 
5004  if (arg0 == "on")
5005  {
5006  if (arg1 == "all")
5007  {
5008  m_echo = (ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_ALL);
5009  m_echo_files.clear ();
5010  }
5011  else
5012  {
5013  std::string file = fcn_file_in_path (arg1);
5014  file = sys::env::make_absolute (file);
5015 
5016  if (file.empty ())
5017  error ("echo: no such file %s", arg1.c_str ());
5018 
5019  m_echo |= ECHO_FUNCTIONS;
5020  m_echo_files[file] = true;
5021  }
5022  }
5023  else if (arg0 == "off")
5024  {
5025  if (arg1 == "all")
5026  {
5027  m_echo = ECHO_OFF;
5028  m_echo_files.clear ();
5029  }
5030  else
5031  {
5032  std::string file = fcn_file_in_path (arg1);
5033  file = sys::env::make_absolute (file);
5034 
5035  if (file.empty ())
5036  error ("echo: no such file %s", arg1.c_str ());
5037 
5038  m_echo_files[file] = false;
5039  }
5040  }
5041  else
5042  print_usage ();
5043  }
5044  break;
5045 
5046  default:
5047  print_usage ();
5048  break;
5049  }
5050 
5051  if (cleanup_pushed)
5052  maybe_set_echo_state ();
5053 
5054  return octave_value ();
5055 }
5056 
5057 bool
5059 {
5060  return (m_debugger_stack.empty ()
5061  ? false : m_debugger_stack.top()->in_debug_repl ());
5062 }
5063 
5064 void
5066 {
5067  if (! m_debugger_stack.empty ())
5068  m_debugger_stack.top()->dbcont ();
5069 }
5070 
5071 void
5073 {
5074  if (! m_debugger_stack.empty ())
5075  m_debugger_stack.top()->dbquit (all);
5076 }
5077 
5080 {
5081  int nargin = args.length ();
5082 
5083  if (nargin != 0 && nargin != 3)
5084  print_usage ();
5085 
5086  if (nargin == 3)
5087  {
5089  = args(1).xidx_type_value ("end: K must be integer value");
5090 
5091  if (index_position < 1)
5092  error ("end: K must be greater than zero");
5093 
5095  = args(2).xidx_type_value ("end: N must be integer value");
5096 
5097  if (num_indices < 1)
5098  error ("end: N must be greater than zero");
5099 
5100  return octave_value (args(0).end_index (index_position-1, num_indices));
5101  }
5102 
5103  // If m_indexed_object is undefined, then this use of 'end' is
5104  // either appearing in a function call argument list or in an
5105  // attempt to index an undefined symbol. There seems to be no
5106  // reasonable way to provide a better error message. So just fail
5107  // with an invalid use message. See bug #58830.
5108 
5109  if (m_indexed_object.is_undefined ())
5110  error ("invalid use of 'end': may only be used to index existing value");
5111 
5112  octave_value expr_result;
5113 
5114  if (m_index_list.empty ())
5115  expr_result = m_indexed_object;
5116  else
5117  {
5118  try
5119  {
5120  // When evaluating "end" with no arguments, we should have
5121  // been called from the built-in Fend function that appears
5122  // in the context of an argument list. Fend will be
5123  // evaluated in its own stack frame. But we need to
5124  // evaluate the partial expression that the special "end"
5125  // token applies to in the calling stack frame.
5126 
5127  unwind_action act ([=] (std::size_t frm)
5128  {
5129  m_call_stack.restore_frame (frm);
5130  }, m_call_stack.current_frame ());
5131 
5132  std::size_t n = m_call_stack.find_current_user_frame ();
5133  m_call_stack.goto_frame (n);
5134 
5135  // End is only valid inside argument lists used for
5136  // indexing. The dispatch class is set by the function that
5137  // evaluates the argument list.
5138 
5139  // Silently ignore extra output values.
5140 
5141  octave_value_list tmp
5142  = m_indexed_object.subsref (m_index_type, m_index_list, 1);
5143 
5144  expr_result = tmp.length () ? tmp(0) : octave_value ();
5145 
5146  if (expr_result.is_cs_list ())
5148  }
5149  catch (const index_exception&)
5150  {
5151  error ("error evaluating partial expression for END");
5152  }
5153  }
5154 
5155  if (expr_result.isobject ())
5156  {
5157  // FIXME: is there a better way to lookup and execute a method
5158  // that handles all the details like setting the dispatch class
5159  // appropriately?
5160 
5161  std::string dispatch_class = expr_result.class_name ();
5162 
5163  symbol_table& symtab = m_interpreter.get_symbol_table ();
5164 
5165  octave_value meth = symtab.find_method ("end", dispatch_class);
5166 
5167  if (meth.is_defined ())
5168  return m_interpreter.feval
5169  (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1);
5170  }
5171 
5172  return octave_value (expr_result.end_index (m_index_position, m_num_indices));
5173 }
5174 
5176 tree_evaluator::PS4 (const octave_value_list& args, int nargout)
5177 {
5178  return set_internal_variable (m_PS4, args, nargout, "PS4");
5179 }
5180 
5181 bool
5182 tree_evaluator::echo_this_file (const std::string& file, int type) const
5183 {
5184  if ((type & m_echo) == ECHO_SCRIPTS)
5185  {
5186  // Asking about scripts and echo is enabled for them.
5187  return true;
5188  }
5189 
5190  if ((type & m_echo) == ECHO_FUNCTIONS)
5191  {
5192  // Asking about functions and echo is enabled for functions.
5193  // Now, which ones?
5194 
5195  auto p = m_echo_files.find (file);
5196 
5197  if (m_echo & ECHO_ALL)
5198  {
5199  // Return true ulness echo was turned off for a specific
5200  // file.
5201 
5202  return (p == m_echo_files.end () || p->second);
5203  }
5204  else
5205  {
5206  // Return true if echo is specifically enabled for this file.
5207 
5208  return p != m_echo_files.end () && p->second;
5209  }
5210  }
5211 
5212  return false;
5213 }
5214 
5215 void
5216 tree_evaluator::echo_code (int line)
5217 {
5218  std::string prefix = command_editor::decode_prompt_string (m_PS4);
5219 
5220  octave_function *curr_fcn = m_call_stack.current_function ();
5221 
5222  if (curr_fcn && curr_fcn->is_user_code ())
5223  {
5224  octave_user_code *code = dynamic_cast<octave_user_code *> (curr_fcn);
5225 
5226  int num_lines = line - m_echo_file_pos + 1;
5227 
5228  std::deque<std::string> lines
5229  = code->get_code_lines (m_echo_file_pos, num_lines);
5230 
5231  for (auto& elt : lines)
5232  octave_stdout << prefix << elt << std::endl;
5233  }
5234 }
5235 
5236 // Decide if it's time to quit a for or while loop.
5237 bool
5238 tree_evaluator::quit_loop_now ()
5239 {
5240  octave_quit ();
5241 
5242  // Maybe handle 'continue N' someday...
5243 
5244  if (m_continuing)
5245  m_continuing--;
5246 
5247  bool quit = (m_returning || m_breaking || m_continuing);
5248 
5249  if (m_breaking)
5250  m_breaking--;
5251 
5252  return quit;
5253 }
5254 
5255 void
5256 tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names,
5257  const Matrix& ignored_outputs,
5258  int nargin, int nargout,
5259  bool takes_varargs,
5260  const octave_value_list& va_args)
5261 {
5263  set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs);
5267 
5268  if (takes_varargs)
5269  assign ("varargin", va_args.cell_value ());
5270 }
5271 
5272 std::string
5273 tree_evaluator::check_autoload_file (const std::string& nm) const
5274 {
5275  if (sys::env::absolute_pathname (nm))
5276  return nm;
5277 
5278  std::string full_name = nm;
5279 
5280  octave_user_code *fcn = m_call_stack.current_user_code ();
5281 
5282  bool found = false;
5283 
5284  if (fcn)
5285  {
5286  std::string fname = fcn->fcn_file_name ();
5287 
5288  if (! fname.empty ())
5289  {
5290  fname = sys::env::make_absolute (fname);
5291  fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1);
5292 
5293  sys::file_stat fs (fname + nm);
5294 
5295  if (fs.exists ())
5296  {
5297  full_name = fname + nm;
5298  found = true;
5299  }
5300  }
5301  }
5302 
5303  if (! found)
5304  warning_with_id ("Octave:autoload-relative-file-name",
5305  "autoload: '%s' is not an absolute filename",
5306  nm.c_str ());
5307 
5308  return full_name;
5309 }
5310 
5311 DEFMETHOD (max_recursion_depth, interp, args, nargout,
5312  doc: /* -*- texinfo -*-
5313 @deftypefn {} {@var{val} =} max_recursion_depth ()
5314 @deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val})
5315 @deftypefnx {} {@var{old_val} =} max_recursion_depth (@var{new_val}, "local")
5316 Query or set the internal limit on the number of times a function may
5317 be called recursively.
5318 
5319 If the limit is exceeded, an error message is printed and control returns to
5320 the top level.
5321 
5322 When called from inside a function with the @qcode{"local"} option, the
5323 variable is changed locally for the function and any subroutines it calls.
5324 The original variable value is restored when exiting the function.
5325 
5326 @seealso{max_stack_depth}
5327 @end deftypefn */)
5328 {
5329  tree_evaluator& tw = interp.get_evaluator ();
5330 
5331  return tw.max_recursion_depth (args, nargout);
5332 }
5333 
5334 /*
5335 %!test
5336 %! orig_val = max_recursion_depth ();
5337 %! old_val = max_recursion_depth (2*orig_val);
5338 %! assert (orig_val, old_val);
5339 %! assert (max_recursion_depth (), 2*orig_val);
5340 %! max_recursion_depth (orig_val);
5341 %! assert (max_recursion_depth (), orig_val);
5342 
5343 %!error max_recursion_depth (1, 2)
5344 */
5345 
5346 DEFMETHOD (whos_line_format, interp, args, nargout,
5347  doc: /* -*- texinfo -*-
5348 @deftypefn {} {@var{val} =} whos_line_format ()
5349 @deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val})
5350 @deftypefnx {} {@var{old_val} =} whos_line_format (@var{new_val}, "local")
5351 Query or set the format string used by the command @code{whos}.
5352 
5353 A full format string is:
5354 @c Set example in small font to prevent overfull line
5355 
5356 @smallexample
5357 %[modifier]<command>[:width[:left-min[:balance]]];
5358 @end smallexample
5359 
5360 The following command sequences are available:
5361 
5362 @table @code
5363 @item %a
5364 Prints attributes of variables (c=complex, s=sparse, f=formal parameter,
5365 g=global, p=persistent).
5366 
5367 @item %b
5368 Prints number of bytes occupied by variables.
5369 
5370 @item %c
5371 Prints class names of variables.
5372 
5373 @item %e
5374 Prints elements held by variables.
5375 
5376 @item %n
5377 Prints variable names.
5378 
5379 @item %s
5380 Prints dimensions of variables.
5381 
5382 @item %t
5383 Prints type names of variables.
5384 @end table
5385 
5386 Every command may also have an alignment modifier:
5387 
5388 @table @code
5389 @item l
5390 Left alignment.
5391 
5392 @item r
5393 Right alignment (default).
5394 
5395 @item c
5396 Column-aligned (only applicable to command %s).
5397 @end table
5398 
5399 The @code{width} parameter is a positive integer specifying the minimum
5400 number of columns used for printing. No maximum is needed as the field will
5401 auto-expand as required.
5402 
5403 The parameters @code{left-min} and @code{balance} are only available when
5404 the column-aligned modifier is used with the command @samp{%s}.
5405 @code{balance} specifies the column number within the field width which
5406 will be aligned between entries. Numbering starts from 0 which indicates
5407 the leftmost column. @code{left-min} specifies the minimum field width to
5408 the left of the specified balance column.
5409 
5410 The default format is:
5411 
5412 @example
5413 " %la:5; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;@backslashchar{}n"
5414 @end example
5415 
5416 When called from inside a function with the @qcode{"local"} option, the
5417 variable is changed locally for the function and any subroutines it calls.
5418 The original variable value is restored when exiting the function.
5419 @seealso{whos}
5420 @end deftypefn */)
5421 {
5422  tree_evaluator& tw = interp.get_evaluator ();
5423 
5424  return tw.whos_line_format (args, nargout);
5425 }
5426 
5427 DEFMETHOD (silent_functions, interp, args, nargout,
5428  doc: /* -*- texinfo -*-
5429 @deftypefn {} {@var{val} =} silent_functions ()
5430 @deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val})
5431 @deftypefnx {} {@var{old_val} =} silent_functions (@var{new_val}, "local")
5432 Query or set the internal variable that controls whether internal
5433 output from a function is suppressed.
5434 
5435 If this option is disabled, Octave will display the results produced by
5436 evaluating expressions within a function body that are not terminated with
5437 a semicolon.
5438 
5439 When called from inside a function with the @qcode{"local"} option, the
5440 variable is changed locally for the function and any subroutines it calls.
5441 The original variable value is restored when exiting the function.
5442 @end deftypefn */)
5443 {
5444  tree_evaluator& tw = interp.get_evaluator ();
5445 
5446  return tw.silent_functions (args, nargout);
5447 }
5448 
5449 /*
5450 %!test
5451 %! orig_val = silent_functions ();
5452 %! old_val = silent_functions (! orig_val);
5453 %! assert (orig_val, old_val);
5454 %! assert (silent_functions (), ! orig_val);
5455 %! silent_functions (orig_val);
5456 %! assert (silent_functions (), orig_val);
5457 
5458 %!error silent_functions (1, 2)
5459 */
5460 
5461 DEFMETHOD (string_fill_char, interp, args, nargout,
5462  doc: /* -*- texinfo -*-
5463 @deftypefn {} {@var{val} =} string_fill_char ()
5464 @deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val})
5465 @deftypefnx {} {@var{old_val} =} string_fill_char (@var{new_val}, "local")
5466 Query or set the internal variable used to pad all rows of a character
5467 matrix to the same length.
5468 
5469 The value must be a single character and the default is @qcode{" "} (a
5470 single space). For example:
5471 
5472 @example
5473 @group
5474 string_fill_char ("X");
5475 [ "these"; "are"; "strings" ]
5476  @result{} "theseXX"
5477  "areXXXX"
5478  "strings"
5479 @end group
5480 @end example
5481 
5482 When called from inside a function with the @qcode{"local"} option, the
5483 variable is changed locally for the function and any subroutines it calls.
5484 The original variable value is restored when exiting the function.
5485 @end deftypefn */)
5486 {
5487  tree_evaluator& tw = interp.get_evaluator ();
5488 
5489  return tw.string_fill_char (args, nargout);
5490 }
5491 
5492 /*
5493 ## string_fill_char() function call must be outside of %!test block
5494 ## due to the way a %!test block is wrapped inside a function
5495 %!shared orig_val, old_val
5496 %! orig_val = string_fill_char ();
5497 %! old_val = string_fill_char ("X");
5498 %!test
5499 %! assert (orig_val, old_val);
5500 %! assert (string_fill_char (), "X");
5501 %! assert (["these"; "are"; "strings"], ["theseXX"; "areXXXX"; "strings"]);
5502 %! string_fill_char (orig_val);
5503 %! assert (string_fill_char (), orig_val);
5504 
5505 %!assert ( [ [], {1} ], {1} )
5506 
5507 %!error string_fill_char (1, 2)
5508 */
5509 
5510 DEFMETHOD (PS4, interp, args, nargout,
5511  doc: /* -*- texinfo -*-
5512 @deftypefn {} {@var{val} =} PS4 ()
5513 @deftypefnx {} {@var{old_val} =} PS4 (@var{new_val})
5514 @deftypefnx {} {@var{old_val} =} PS4 (@var{new_val}, "local")
5515 Query or set the character string used to prefix output produced
5516 when echoing commands is enabled.
5517 
5518 The default value is @qcode{"+ "}.
5519 @xref{Diary and Echo Commands}, for a description of echoing commands.
5520 
5521 When called from inside a function with the @qcode{"local"} option, the
5522 variable is changed locally for the function and any subroutines it calls.
5523 The original variable value is restored when exiting the function.
5524 @seealso{echo, PS1, PS2}
5525 @end deftypefn */)
5526 {
5527  return interp.PS4 (args, nargout);
5528 }
5529 
5530 DEFMETHOD (echo, interp, args, nargout,
5531  doc: /* -*- texinfo -*-
5532 @deftypefn {} {} echo
5533 @deftypefnx {} {} echo on
5534 @deftypefnx {} {} echo off
5535 @deftypefnx {} {} echo on all
5536 @deftypefnx {} {} echo off all
5537 @deftypefnx {} {} echo @var{function} on
5538 @deftypefnx {} {} echo @var{function} off
5539 Control whether commands are displayed as they are executed.
5540 
5541 Valid options are:
5542 
5543 @table @code
5544 @item on
5545 Enable echoing of commands as they are executed in script files.
5546 
5547 @item off
5548 Disable echoing of commands as they are executed in script files.
5549 
5550 @item on all
5551 Enable echoing of commands as they are executed in script files and
5552 functions.
5553 
5554 @item off all
5555 Disable echoing of commands as they are executed in script files and
5556 functions.
5557 
5558 @item @var{function} on
5559 Enable echoing of commands as they are executed in the named function.
5560 
5561 @item @var{function} off
5562 Disable echoing of commands as they are executed in the named function.
5563 @end table
5564 
5565 @noindent
5566 With no arguments, @code{echo} toggles the current echo state.
5567 
5568 @seealso{PS4}
5569 @end deftypefn */)
5570 {
5571  tree_evaluator& tw = interp.get_evaluator ();
5572 
5573  return tw.echo (args, nargout);
5574 }
5575 
5576 /*
5577 %!error echo ([])
5578 %!error echo (0)
5579 %!error echo ("")
5580 %!error echo ("Octave")
5581 %!error echo ("off", "invalid")
5582 %!error echo ("on", "invalid")
5583 %!error echo ("on", "all", "all")
5584 */
5585 
5586 OCTAVE_END_NAMESPACE(octave)
octave_idx_type rows() const
Definition: Array.h:459
octave_idx_type columns() const
Definition: Array.h:471
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
Definition: Cell.h:43
Definition: dMatrix.h:42
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:158
void add(F &&fcn, Args &&... args)
void discard(std::size_t num)
void run(std::size_t num)
void protect_var(T &var)
void forced_interactive(bool arg)
Definition: octave.h:295
static bool forced_interactive()
Definition: octave.cc:329
static application * app()
Definition: octave.h:301
std::size_t length() const
Definition: base-list.h:53
iterator end()
Definition: base-list.h:68
elt_type & front()
Definition: base-list.h:79
iterator begin()
Definition: base-list.h:65
void statement_list(std::shared_ptr< tree_statement_list > &lst)
Definition: oct-parse.cc:6825
void disallow_command_syntax()
Definition: oct-parse.cc:9627
bool at_end_of_input() const
Definition: parse.h:170
void reset()
Definition: oct-parse.cc:6723
bool debug_on_err(const std::string &id)
Definition: bp-table.h:141
bool have_breakpoints()
Definition: bp-table.h:138
bool debug_on_caught(const std::string &id)
Definition: bp-table.h:147
void set_dispatch_class(const std::string &class_name)
Definition: call-stack.cc:305
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
Definition: call-stack.cc:983
octave_value get_top_level_value(const std::string &name) const
Definition: call-stack.cc:970
octave_value global_varval(const std::string &name) const
Definition: call-stack.cc:956
std::size_t find_current_user_frame() const
Definition: call-stack.cc:511
std::list< frame_info > backtrace_info(octave_idx_type &curr_user_frame, bool print_subfn=true) const
Definition: call-stack.cc:707
void set_column(int c)
Definition: call-stack.h:190
octave_map backtrace(octave_idx_type &curr_user_frame, bool print_subfn=true) const
Definition: call-stack.cc:738
octave_value & global_varref(const std::string &name)
Definition: call-stack.cc:964
void set_top_level_value(const std::string &name, const octave_value &value)
Definition: call-stack.cc:976
int current_line() const
Definition: call-stack.cc:93
void display() const
Definition: call-stack.cc:1191
void pop()
Definition: call-stack.cc:787
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
Definition: call-stack.cc:1225
std::list< std::string > variable_names() const
Definition: call-stack.cc:866
symbol_info_list regexp_symbol_info(const std::string &pattern) const
Definition: call-stack.cc:918
void make_global(const symbol_record &sym)
Definition: call-stack.cc:950
std::shared_ptr< stack_frame > current_user_frame() const
Definition: call-stack.cc:529
std::size_t size() const
Definition: call-stack.h:89
std::shared_ptr< stack_frame > pop_return()
Definition: call-stack.cc:810
void clear_global_variables()
Definition: call-stack.cc:905
symbol_info_list glob_symbol_info(const std::string &pattern) const
Definition: call-stack.cc:912
void restore_frame(std::size_t n)
Definition: call-stack.h:202
bool at_top_level() const
Definition: call-stack.h:108
bool is_class_method_executing(std::string &dispatch_class) const
Definition: call-stack.cc:311
bool goto_frame(std::size_t n=0, bool verbose=false)
Definition: call-stack.cc:489
int debug_user_code_column() const
Definition: call-stack.cc:268
std::size_t current_frame() const
Definition: call-stack.h:87
void set_auto_fcn_var(stack_frame::auto_var_type avt, const octave_value &val)
Definition: call-stack.cc:1206
symbol_info_list get_symbol_info()
Definition: call-stack.cc:924
symbol_info_list top_scope_symbol_info() const
Definition: call-stack.cc:930
std::list< std::string > global_variable_names() const
Definition: call-stack.cc:844
std::list< std::shared_ptr< stack_frame > > backtrace_frames(octave_idx_type &curr_user_frame) const
Definition: call-stack.cc:665
void set_location(int l, int c)
Definition: call-stack.h:169
bool is_class_constructor_executing(std::string &dispatch_class) const
Definition: call-stack.cc:326
void goto_caller_frame()
Definition: call-stack.cc:645
symbol_scope current_scope() const
Definition: call-stack.h:101
octave_map empty_backtrace() const
Definition: call-stack.cc:781
octave_function * current_function(bool skip_first=false) const
Definition: call-stack.cc:67
void clear_global_variable_pattern(const std::string &pattern)
Definition: call-stack.cc:881
unwind_protect * curr_fcn_unwind_protect_frame()
Definition: call-stack.cc:191
int debug_user_code_line() const
Definition: call-stack.cc:238
octave_user_code * debug_user_code() const
Definition: call-stack.cc:211
void set_line(int l)
Definition: call-stack.h:180
void push(const symbol_scope &scope)
Definition: call-stack.cc:394
std::shared_ptr< stack_frame > get_current_stack_frame() const
Definition: call-stack.h:91
std::list< std::string > top_level_variable_names() const
Definition: call-stack.cc:860
void set_nargin(int nargin)
Definition: call-stack.cc:1213
void clear_global_variable(const std::string &name)
Definition: call-stack.cc:872
octave_user_code * current_user_code() const
Definition: call-stack.cc:121
void goto_base_frame()
Definition: call-stack.cc:658
symbol_scope top_scope() const
Definition: call-stack.h:96
void set_nargout(int nargout)
Definition: call-stack.cc:1219
int current_user_code_line() const
Definition: call-stack.cc:141
std::size_t dbupdown(std::size_t start, int n, bool verbose)
Definition: call-stack.cc:541
int current_column() const
Definition: call-stack.cc:107
std::string get_dispatch_class() const
Definition: call-stack.cc:299
void clear_global_variable_regexp(const std::string &pattern)
Definition: call-stack.cc:893
void make_persistent(const symbol_record &sym)
Definition: call-stack.cc:944
octave_value max_stack_depth(const octave_value_list &args, int nargout)
Definition: call-stack.cc:936
cdef_method find_method(const std::string &nm, bool local=false)
Definition: cdef-class.h:457
std::string get_name() const
Definition: cdef-class.h:318
cdef_class find_class(const std::string &name, bool error_if_not_found=true, bool load_if_not_found=true)
bool is_static() const
Definition: cdef-method.h:184
octave_value get_function() const
Definition: cdef-method.h:191
cdef_class get_class() const
Definition: cdef-object.cc:183
bool ok() const
Definition: cdef-object.h:312
static void run_event_hooks()
Definition: cmd-edit.cc:1578
static void increment_current_command_number()
Definition: cmd-edit.cc:1294
static bool interrupt(bool=true)
Definition: cmd-edit.cc:1622
static bool erase_empty_line(bool flag)
Definition: cmd-edit.cc:1315
static std::string decode_prompt_string(const std::string &s)
Definition: cmd-edit.cc:1275
static bool ignoring_entries()
Definition: cmd-hist.cc:611
static bool add(const std::string &)
Definition: cmd-hist.cc:617
static void ignore_entries(bool=true)
Definition: cmd-hist.cc:604
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
dim_vector redim(int n) const
Force certain dimensionality, preserving numel ().
Definition: dim-vector.cc:226
octave_value last_error_id(const octave_value_list &args, int nargout)
Definition: error.cc:358
octave_map last_error_stack() const
Definition: error.h:250
octave_value debug_on_warning(const octave_value_list &args, int nargout)
Definition: error.cc:292
void set_debug_on_warning(bool flag)
Definition: error.h:86
octave_value debug_on_caught(const octave_value_list &args, int nargout)
Definition: error.cc:285
void save_exception(const execution_exception &ee)
Definition: error.cc:912
octave_value debug_on_error(const octave_value_list &args, int nargout)
Definition: error.cc:278
octave_value last_error_message(const octave_value_list &args, int nargout)
Definition: error.cc:336
void display_exception(const execution_exception &ee) const
Definition: error.cc:924
void set_debug_on_error(bool flag)
Definition: error.h:58
Provides threadsafe access to octave.
void append_history(const std::string &hist_entry)
void enter_debugger_event(const std::string &fcn_name, const std::string &fcn_file_name, int line)
void post_event(const fcn_callback &fcn)
void pre_input_event()
void pop_event_queue()
void execute_in_debugger_event(const std::string &file, int line)
void push_event_queue()
void set_workspace()
virtual const char * err_id() const =0
void set_var(const std::string &var_arg="")
octave_value gud_mode(const octave_value_list &args, int nargout)
cdef_manager & get_cdef_manager()
Definition: interpreter.h:318
event_manager & get_event_manager()
Definition: interpreter.h:328
symbol_table & get_symbol_table()
Definition: interpreter.h:298
void set_PS1(const std::string &s)
octave_value PS1(const octave_value_list &args, int nargout)
void parse_and_execute(const std::string &input, bool &incomplete_parse)
Definition: interpreter.cc:813
bool interactive() const
Definition: interpreter.h:165
load_path & get_load_path()
Definition: interpreter.h:283
error_system & get_error_system()
Definition: interpreter.h:251
octave_value_list feval(const char *name, const octave_value_list &args=octave_value_list(), int nargout=0)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
void recover_from_exception()
octave_value PS2(const octave_value_list &args, int nargout)
Definition: lex.h:760
line(const graphics_handle &mh, const graphics_handle &p)
Definition: graphics.h:7672
std::string find_file(const std::string &file) const
Definition: load-path.cc:575
virtual bool is_user_code() const
Definition: ov-base.h:537
virtual bool is_user_function() const
Definition: ov-base.h:535
virtual bool is_builtin_function() const
Definition: ov-base.h:539
meth method() const
Definition: ov-builtin.cc:59
octave_value_list(* fcn)(const octave_value_list &, int)
Definition: ov-builtin.h:63
octave_value_list(* meth)(octave::interpreter &, const octave_value_list &, int)
Definition: ov-builtin.h:60
fcn function() const
Definition: ov-builtin.cc:53
octave::cdef_object get_object() const
Definition: ov-classdef.h:73
std::string class_name() const
Definition: ov-classdef.h:152
octave_classdef * classdef_object_value(bool=false)
Definition: ov-classdef.h:71
virtual std::list< std::string > parent_fcn_names() const
Definition: ov-fcn.h:87
virtual bool is_nested_function() const
Definition: ov-fcn.h:102
virtual bool is_subfunction() const
Definition: ov-fcn.h:106
std::string dispatch_class() const
Definition: ov-fcn.h:148
bool islocked() const
Definition: ov-fcn.h:186
bool is_class_method(const std::string &cname="") const
Definition: ov-fcn.h:115
bool is_class_constructor(const std::string &cname="") const
Definition: ov-fcn.h:110
bool is_private_function() const
Definition: ov-fcn.h:161
virtual std::string parent_fcn_name() const
Definition: ov-fcn.h:82
void unlock()
Definition: ov-fcn.h:180
void stash_dir_name(const std::string &dir)
Definition: ov-fcn.h:172
virtual bool is_parent_function() const
Definition: ov-fcn.h:104
void lock()
Definition: ov-fcn.h:174
virtual octave_value_list call(octave::tree_evaluator &tw, int nargout=0, const octave_value_list &args=octave_value_list())
Definition: ov-fcn.cc:56
void stash_dispatch_class(const std::string &nm)
Definition: ov-fcn.h:146
virtual std::string fcn_file_name() const
Definition: ov-fcn.h:75
std::string name() const
Definition: ov-fcn.h:206
std::string dir_name() const
Definition: ov-fcn.h:170
bool is_undefined() const
Definition: oct-lvalue.cc:46
void assign(octave_value::assign_op, const octave_value &)
Definition: oct-lvalue.cc:58
void define(const octave_value &v)
Definition: oct-lvalue.cc:52
string_vector keys() const
Definition: oct-map.h:335
const Cell & contents(const_iterator p) const
Definition: oct-map.h:310
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:230
void stash_fcn_file_name(const std::string &nm)
Definition: ov-usr-fcn.h:94
std::string get_code_line(std::size_t line)
Definition: ov-usr-fcn.cc:100
std::string fcn_file_name() const
Definition: ov-usr-fcn.h:105
std::deque< std::string > get_code_lines(std::size_t line, std::size_t num_lines)
Definition: ov-usr-fcn.cc:109
virtual octave_value find_subfunction(const std::string &) const
Definition: ov-usr-fcn.h:111
octave::tree_statement_list * body()
Definition: ov-usr-fcn.h:118
bool takes_varargs() const
Definition: ov-usr-fcn.cc:375
bool is_special_expr() const
Definition: ov-usr-fcn.h:328
octave_value_list all_va_args(const octave_value_list &args)
Definition: ov-usr-fcn.cc:462
bool is_classdef_constructor(const std::string &cname="") const
Definition: ov-usr-fcn.h:349
octave::tree_parameter_list * parameter_list()
Definition: ov-usr-fcn.h:384
bool is_anonymous_function() const
Definition: ov-usr-fcn.h:313
void restore_warning_states()
Definition: ov-usr-fcn.cc:623
octave::tree_parameter_list * return_list()
Definition: ov-usr-fcn.h:386
void mark_as_anonymous_function()
Definition: ov-usr-fcn.h:311
void mark_as_nested_function()
Definition: ov-usr-fcn.h:333
octave_value & xelem(octave_idx_type i)
Definition: ovl.h:171
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
void stash_name_tags(const string_vector &nm)
Definition: ovl.h:165
bool has_magic_colon() const
Definition: ovl.cc:215
bool empty() const
Definition: ovl.h:115
Cell cell_value() const
Definition: ovl.h:105
string_vector name_tags() const
Definition: ovl.h:167
octave_value_list slice(octave_idx_type offset, octave_idx_type len, bool tags=false) const
Definition: ovl.h:131
void clear()
Definition: ovl.h:173
string_vector make_argv(const std::string &="") const
Definition: ovl.cc:227
octave_idx_type length() const
Definition: ovl.h:113
void make_storable_values()
Definition: ovl.cc:277
octave_value_list list_value() const
bool is_undefined() const
Definition: ov.h:595
Cell xcell_value(const char *fmt,...) const
std::string class_name() const
Definition: ov.h:1347
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov.h:476
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:504
bool is_true() const
Definition: ov.h:758
Cell cell_value() const
int ndims() const
Definition: ov.h:551
bool is_scalar_type() const
Definition: ov.h:744
octave::range< double > range_value() const
Definition: ov.h:985
bool is_string() const
Definition: ov.h:637
octave_idx_type end_index(octave_idx_type index_position, octave_idx_type num_indices) const
octave_user_code * user_code_value(bool silent=false) const
bool is_range() const
Definition: ov.h:646
bool is_defined() const
Definition: ov.h:592
bool is_function() const
Definition: ov.h:777
bool is_equal(const octave_value &) const
@ op_asn_eq
Definition: ov.h:135
octave_value storable_value() const
octave_function * function_value(bool silent=false) const
octave_value reshape(const dim_vector &dv) const
Definition: ov.h:571
bool iscell() const
Definition: ov.h:604
octave_map map_value() const
@ magic_colon_t
Definition: ov.h:170
bool is_matrix_type() const
Definition: ov.h:747
bool is_double_type() const
Definition: ov.h:695
bool is_cs_list() const
Definition: ov.h:670
bool is_user_code() const
Definition: ov.h:786
std::string xstring_value(const char *fmt,...) const
bool isstruct() const
Definition: ov.h:649
bool isobject() const
Definition: ov.h:664
dim_vector dims() const
Definition: ov.h:541
Definition: parse.h:822
int run()
Definition: oct-parse.cc:9748
std::map< std::string, octave_value > local_vars_map
Definition: stack-frame.h:112
@ SAVED_WARNING_STATES
Definition: stack-frame.h:136
octave_idx_type numel() const
Definition: str-vec.h:100
static symbol_scope invalid()
Definition: symscope.h:400
void set_parent(const symbol_scope &p)
Definition: symscope.h:624
void cache_fcn_file_name(const std::string &name)
Definition: symscope.h:636
void set_nesting_depth(std::size_t depth)
Definition: symscope.h:440
void set_primary_parent(const symbol_scope &p)
Definition: symscope.h:630
symbol_scope dup() const
Definition: symscope.h:472
void cache_dir_name(const std::string &name)
Definition: symscope.h:642
std::size_t nesting_depth() const
Definition: symscope.h:446
octave_value find_scoped_function(const std::string &name, const symbol_scope &search_scope)
Definition: symtab.cc:77
octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.cc:128
void clear_function(const std::string &name)
Definition: symtab.cc:446
void clear_function_pattern(const std::string &pat)
Definition: symtab.cc:452
void clear_functions(bool force=false)
Definition: symtab.cc:437
void install_cmdline_function(const std::string &name, const octave_value &fcn)
Definition: symtab.cc:339
octave_value find_function(const std::string &name, const symbol_scope &search_scope=symbol_scope::invalid())
Definition: symtab.cc:254
void clear_dld_function(const std::string &name)
Definition: symtab.cc:501
octave_value fcn_table_find(const std::string &name, const octave_value_list &args=ovl(), const symbol_scope &search_scope=symbol_scope::invalid())
Definition: symtab.cc:224
octave_value find_user_function(const std::string &name)
Definition: symtab.cc:293
void clear_function_regexp(const std::string &pat)
Definition: symtab.cc:468
symbol_scope scope() const
tree_parameter_list * parameter_list() const
tree_expression * expression() const
std::set< std::string > free_variables() const
tree_statement_list * body()
Definition: pt-loop.h:233
tree_argument_list * left_hand_side()
Definition: pt-loop.h:229
tree_expression * control_expr()
Definition: pt-loop.h:231
tree_decl_init_list * initializer_list()
Definition: pt-decl.h:189
bool is_global() const
Definition: pt-decl.h:79
tree_identifier * ident()
Definition: pt-decl.h:84
bool is_persistent() const
Definition: pt-decl.h:82
tree_expression * expression()
Definition: pt-decl.h:88
void accept(tree_walker &tw)
Definition: pt-decl.h:155
octave_value_list eval_string(const std::string &eval_str, bool silent, int &parse_status, int nargout)
Definition: pt-eval.cc:1022
bool switch_case_label_matches(tree_switch_case *expr, const octave_value &val)
Definition: pt-eval.cc:2434
octave_value_list execute_user_function(octave_user_function &user_function, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3567
void visit_break_command(tree_break_command &)
Definition: pt-eval.cc:1325
bool is_global(const std::string &name) const
Definition: pt-eval.cc:1927
void visit_octave_user_function(octave_user_function &)
Definition: pt-eval.cc:3743
void pop_stack_frame()
Definition: pt-eval.cc:2499
void visit_unwind_protect_command(tree_unwind_protect_command &)
Definition: pt-eval.cc:4313
bool mislocked(bool skip_first=false) const
Definition: pt-eval.cc:2754
void bind_ans(const octave_value &val, bool print)
Definition: pt-eval.cc:4464
void visit_return_command(tree_return_command &)
Definition: pt-eval.cc:3913
octave_value_list execute_builtin_function(octave_builtin &builtin_function, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3445
void clear_all(bool force=false)
Definition: pt-eval.cc:2871
int max_recursion_depth() const
Definition: pt-eval.h:590
void visit_statement_list(tree_statement_list &)
Definition: pt-eval.cc:4054
void reset_debug_state()
Definition: pt-eval.cc:1378
octave_value evaluate(tree_decl_elt *)
Definition: pt-eval.cc:1850
void visit_anon_fcn_handle(tree_anon_fcn_handle &)
Definition: pt-eval.cc:1259
octave_user_code * current_user_code() const
Definition: pt-eval.cc:2543
void dbcont()
Definition: pt-eval.cc:5065
void source_file(const std::string &file_name, const std::string &context="", bool verbose=false, bool require_file=true)
Definition: pt-eval.cc:2042
symbol_scope get_current_scope() const
Definition: pt-eval.cc:2714
void visit_cell(tree_cell &)
Definition: pt-eval.cc:3855
octave_value echo(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:4930
octave_value_list evaluate_end_expression(const octave_value_list &args)
Definition: pt-eval.cc:5079
void add_autoload(const std::string &fcn, const std::string &nm)
Definition: pt-eval.cc:4693
std::list< frame_info > backtrace_info() const
Definition: pt-eval.cc:2640
void visit_constant(tree_constant &)
Definition: pt-eval.cc:3883
void keyboard(const std::string &prompt="keyboard> ")
Definition: pt-eval.cc:1443
void display_call_stack() const
Definition: pt-eval.cc:2771
octave_map empty_backtrace() const
Definition: pt-eval.cc:2659
void visit_superclass_ref(tree_superclass_ref &)
Definition: pt-eval.cc:4452
void visit_simple_assignment(tree_simple_assignment &)
Definition: pt-eval.cc:3938
octave_value & global_varref(const std::string &name)
Definition: pt-eval.cc:1971
octave_map backtrace() const
Definition: pt-eval.cc:2653
void final_index_error(index_exception &ie, const tree_expression *expr)
Definition: pt-eval.cc:4739
void visit_args_block_validation_list(tree_args_block_validation_list &)
Definition: pt-eval.cc:1283
Matrix ignored_fcn_outputs() const
Definition: pt-eval.cc:1455
void debug_where(std::ostream &os) const
Definition: pt-eval.cc:2535
int current_line() const
Definition: pt-eval.cc:2511
void clear_global_variables()
Definition: pt-eval.cc:2865
void clear_global_variable(const std::string &name)
Definition: pt-eval.cc:2847
std::string get_dispatch_class() const
Definition: pt-eval.cc:2597
octave_value_list execute_mex_function(octave_mex_function &mex_function, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3495
void set_dispatch_class(const std::string &class_name)
Definition: pt-eval.cc:2603
void visit_boolean_expression(tree_boolean_expression &)
Definition: pt-eval.cc:1313
bool goto_frame(std::size_t n=0, bool verbose=false)
Definition: pt-eval.cc:2573
void visit_switch_case(tree_switch_case &)
Definition: pt-eval.cc:4104
void munlock(bool skip_first=false) const
Definition: pt-eval.cc:2737
void visit_arg_validation(tree_arg_validation &)
Definition: pt-eval.cc:1289
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
Definition: pt-eval.cc:2213
void remove_autoload(const std::string &fcn, const std::string &nm)
Definition: pt-eval.cc:4700
bool at_top_level() const
Definition: pt-eval.cc:538
void visit_octave_user_function_header(octave_user_function &)
Definition: pt-eval.cc:3750
void visit_arg_size_spec(tree_arg_size_spec &)
Definition: pt-eval.cc:1295
void visit_multi_assignment(tree_multi_assignment &)
Definition: pt-eval.cc:3861
void visit_continue_command(tree_continue_command &)
Definition: pt-eval.cc:1352
octave_value find(const std::string &name)
Definition: pt-eval.cc:2777
symbol_info_list top_scope_symbol_info() const
Definition: pt-eval.cc:4624
void visit_while_command(tree_while_command &)
Definition: pt-eval.cc:4368
void visit_do_until_command(tree_do_until_command &)
Definition: pt-eval.cc:4411
octave_map get_autoload_map() const
Definition: pt-eval.cc:4630
void visit_index_expression(tree_index_expression &)
Definition: pt-eval.cc:3843
void visit_postfix_expression(tree_postfix_expression &)
Definition: pt-eval.cc:3901
std::list< std::shared_ptr< stack_frame > > backtrace_frames() const
Definition: pt-eval.cc:2627
std::list< std::string > variable_names() const
Definition: pt-eval.cc:2932
void define_parameter_list_from_arg_vector(tree_parameter_list *param_list, const octave_value_list &args)
Definition: pt-eval.cc:2220
bool is_local_variable(const std::string &name) const
Definition: pt-eval.cc:1869
void visit_decl_command(tree_decl_command &)
Definition: pt-eval.cc:3048
bool in_debug_repl() const
Definition: pt-eval.cc:5058
void visit_arg_validation_fcns(tree_arg_validation_fcns &)
Definition: pt-eval.cc:1301
void visit_function_def(tree_function_def &)
Definition: pt-eval.cc:3762
symbol_scope get_top_scope() const
Definition: pt-eval.cc:2708
void visit_switch_command(tree_switch_command &)
Definition: pt-eval.cc:4116
int index_position() const
Definition: pt-eval.h:750
void clear_symbol_pattern(const std::string &pattern)
Definition: pt-eval.cc:2896
void clear_symbol(const std::string &name)
Definition: pt-eval.cc:2884
bool in_user_code() const
Definition: pt-eval.cc:3042
void visit_arguments_block(tree_arguments_block &)
Definition: pt-eval.cc:1271
void dbquit(bool all=false)
Definition: pt-eval.cc:5072
void restore_frame(std::size_t n)
Definition: pt-eval.cc:2591
void clear_objects()
Definition: pt-eval.cc:2802
void visit_if_command(tree_if_command &)
Definition: pt-eval.cc:3796
bool is_class_method_executing(std::string &dispatch_class) const
Definition: pt-eval.cc:2609
void visit_spmd_command(tree_spmd_command &)
Definition: pt-eval.cc:3340
octave_value_list convert_to_const_vector(tree_argument_list *arg_list)
Definition: pt-eval.cc:2328
unwind_protect * curr_fcn_unwind_protect_frame()
Definition: pt-eval.cc:2549
std::shared_ptr< stack_frame > pop_return_stack_frame()
Definition: pt-eval.cc:2505
void visit_try_catch_command(tree_try_catch_command &)
Definition: pt-eval.cc:4158
void visit_colon_expression(tree_colon_expression &)
Definition: pt-eval.cc:1346
int server_loop()
Definition: pt-eval.cc:880
int debug_user_code_line() const
Definition: pt-eval.cc:2523
int returning() const
Definition: pt-eval.h:784
void push_dummy_scope(const std::string &name)
Definition: pt-eval.cc:2694
int echo() const
Definition: pt-eval.h:823
void visit_simple_for_command(tree_simple_for_command &)
Definition: pt-eval.cc:3134
octave_value_list make_value_list(tree_argument_list *args, const string_vector &arg_nm)
Definition: pt-eval.cc:4777
std::string backtrace_message() const
Definition: pt-eval.cc:2665
void clear_variable(const std::string &name)
Definition: pt-eval.cc:2811
void visit_matrix(tree_matrix &)
Definition: pt-eval.cc:3849
bool is_variable(const std::string &name) const
Definition: pt-eval.cc:1860
bool is_class_constructor_executing(std::string &dispatch_class) const
Definition: pt-eval.cc:2615
void visit_octave_user_script(octave_user_script &)
Definition: pt-eval.cc:3560
std::string lookup_autoload(const std::string &nm) const
Definition: pt-eval.cc:4653
void visit_if_clause(tree_if_clause &)
Definition: pt-eval.cc:3790
std::list< std::string > reverse_lookup_autoload(const std::string &nm) const
Definition: pt-eval.cc:4681
std::size_t current_call_stack_frame_number() const
Definition: pt-eval.h:634
void visit_args_block_attribute_list(tree_args_block_attribute_list &)
Definition: pt-eval.cc:1277
std::size_t debug_frame() const
Definition: pt-eval.h:625
octave_function * caller_function() const
Definition: pt-eval.cc:2567
std::list< std::string > global_variable_names() const
Definition: pt-eval.cc:2920
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
Definition: pt-eval.cc:4770
std::shared_ptr< push_parser > get_parser()
Definition: pt-eval.h:150
void set_parser(const std::shared_ptr< push_parser > &parser)
Definition: pt-eval.h:155
symbol_info_list get_symbol_info()
Definition: pt-eval.cc:4618
symbol_info_list glob_symbol_info(const std::string &pattern) const
Definition: pt-eval.cc:4606
bool silent_functions() const
Definition: pt-eval.h:602
void clear_global_variable_pattern(const std::string &pattern)
Definition: pt-eval.cc:2853
void visit_argument_list(tree_argument_list &)
Definition: pt-eval.cc:1265
void pop_scope()
Definition: pt-eval.cc:2702
std::shared_ptr< stack_frame > current_user_frame() const
Definition: pt-eval.h:448
octave_value_list convert_return_list_to_const_vector(tree_parameter_list *ret_list, int nargout, const Cell &varargout)
Definition: pt-eval.cc:2358
void assign(const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:1997
void assignin(const std::string &context, const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:2006
void visit_statement(tree_statement &)
Definition: pt-eval.cc:3944
char string_fill_char() const
Definition: pt-eval.h:648
octave_value top_level_varval(const std::string &name) const
Definition: pt-eval.cc:1984
void dbupdown(int n, bool verbose=false)
Definition: pt-eval.cc:1449
octave_value evaluate_anon_fcn_handle(tree_anon_fcn_handle &afh)
Definition: pt-eval.cc:3351
void undefine_parameter_list(tree_parameter_list *param_list)
Definition: pt-eval.cc:2249
octave_value max_stack_depth(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:2765
void visit_identifier(tree_identifier &)
Definition: pt-eval.cc:3784
void clear_symbol_regexp(const std::string &pattern)
Definition: pt-eval.cc:2908
@ ECHO_FUNCTIONS
Definition: pt-eval.h:75
void get_line_and_eval()
Definition: pt-eval.cc:645
std::list< std::string > autoloaded_functions() const
Definition: pt-eval.cc:4670
void visit_octave_user_function_trailer(octave_user_function &)
Definition: pt-eval.cc:3756
int debug_user_code_column() const
Definition: pt-eval.cc:2529
void push_echo_state(int type, const std::string &file_name, int pos=1)
Definition: pt-eval.cc:4843
void visit_fcn_handle(tree_fcn_handle &)
Definition: pt-eval.cc:3889
octave_value_list execute_user_script(octave_user_script &user_script, int nargout, const octave_value_list &args)
Definition: pt-eval.cc:3517
void goto_base_frame()
Definition: pt-eval.cc:2585
void eval(std::shared_ptr< tree_statement_list > &stmt_list, bool interactive)
Definition: pt-eval.cc:989
bool server_mode() const
Definition: pt-eval.h:178
std::string whos_line_format() const
Definition: pt-eval.h:613
octave_value_list evalin(const std::string &context, const std::string &try_code, int nargout)
Definition: pt-eval.cc:1176
bool is_defined(const tree_expression *expr) const
Definition: pt-eval.cc:1895
octave_value global_varval(const std::string &name) const
Definition: pt-eval.cc:1965
int num_indices() const
Definition: pt-eval.h:752
void top_level_assign(const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:1990
void install_variable(const std::string &name, const octave_value &value, bool global)
Definition: pt-eval.cc:1954
void visit_binary_expression(tree_binary_expression &)
Definition: pt-eval.cc:1307
symbol_info_list regexp_symbol_info(const std::string &pattern) const
Definition: pt-eval.cc:4612
void set_auto_fcn_var(stack_frame::auto_var_type avt, const octave_value &val=octave_value())
Definition: pt-eval.cc:2194
octave_user_code * debug_user_code() const
Definition: pt-eval.cc:2555
bool eval_decl_elt(tree_decl_elt *elt)
Definition: pt-eval.cc:2412
bool quiet_breakpoint_flag() const
Definition: pt-eval.h:639
int breaking() const
Definition: pt-eval.h:766
void clear_global_variable_regexp(const std::string &pattern)
Definition: pt-eval.cc:2859
void visit_decl_elt(tree_decl_elt &)
Definition: pt-eval.cc:3072
void parse_and_execute(const std::string &input, bool &incomplete_parse)
Definition: pt-eval.cc:580
void visit_parameter_list(tree_parameter_list &)
Definition: pt-eval.cc:3895
std::list< std::string > top_level_variable_names() const
Definition: pt-eval.cc:2926
std::list< octave_lvalue > make_lvalue_list(tree_argument_list *)
Definition: pt-eval.cc:4832
int continuing() const
Definition: pt-eval.h:775
int current_column() const
Definition: pt-eval.cc:2517
void enter_debugger(const std::string &prompt="debug> ")
Definition: pt-eval.cc:1393
void visit_complex_for_command(tree_complex_for_command &)
Definition: pt-eval.cc:3264
octave_value whos_line_format(const octave_value_list &args, int nargout)
Definition: pt-eval.cc:4714
octave_user_code * get_user_code(const std::string &fname="")
Definition: pt-eval.cc:2942
void global_assign(const std::string &name, const octave_value &val=octave_value())
Definition: pt-eval.cc:1977
std::string PS4() const
Definition: pt-eval.h:700
octave_value make_fcn_handle(const std::string &nm)
Definition: pt-eval.cc:1603
void mlock(bool skip_first=false) const
Definition: pt-eval.cc:2720
void visit_metaclass_query(tree_metaclass_query &)
Definition: pt-eval.cc:4458
void visit_compound_binary_expression(tree_compound_binary_expression &)
Definition: pt-eval.cc:1319
void do_unwind_protect_cleanup_code(tree_statement_list *list)
Definition: pt-eval.cc:4230
octave_value varval(const symbol_record &sym) const
Definition: pt-eval.cc:1936
void visit_switch_case_list(tree_switch_case_list &)
Definition: pt-eval.cc:4110
int dbstep_flag() const
Definition: pt-eval.h:793
void push_stack_frame(const symbol_scope &scope)
Definition: pt-eval.cc:2466
std::string mfilename(const std::string &opt="") const
Definition: pt-eval.cc:544
void visit_prefix_expression(tree_prefix_expression &)
Definition: pt-eval.cc:3907
void clear_variable_regexp(const std::string &pattern)
Definition: pt-eval.cc:2829
void visit_no_op_command(tree_no_op_command &)
Definition: pt-eval.cc:3867
octave_function * current_function(bool skip_first=false) const
Definition: pt-eval.cc:2561
void goto_caller_frame()
Definition: pt-eval.cc:2579
bool statement_printing_enabled()
Definition: pt-eval.cc:1371
void set_nargin(int nargin)
Definition: pt-eval.cc:2201
void clear_variable_pattern(const std::string &pattern)
Definition: pt-eval.cc:2820
std::string current_function_name(bool skip_first=false) const
Definition: pt-eval.cc:3031
void clear_variables()
Definition: pt-eval.cc:2838
void set_nargout(int nargout)
Definition: pt-eval.cc:2207
void visit_if_command_list(tree_if_command_list &)
Definition: pt-eval.cc:3817
virtual octave_value evaluate(tree_evaluator &tw, int nargout=1)=0
virtual bool is_identifier() const
Definition: pt-exp.h:66
bool print_result() const
Definition: pt-exp.h:98
virtual tree_expression * dup(symbol_scope &scope) const =0
tree_expression * set_print_flag(bool print)
Definition: pt-exp.h:122
virtual std::string name() const
Definition: pt-exp.h:102
virtual bool is_assignment_expression() const
Definition: pt-exp.h:70
virtual octave_lvalue lvalue(tree_evaluator &)
Definition: pt-exp.cc:43
virtual octave_value_list evaluate_n(tree_evaluator &tw, int nargout=1)=0
octave_value function()
Definition: pt-cmd.h:107
virtual bool is_black_hole() const
Definition: pt-id.h:71
symbol_record symbol() const
Definition: pt-id.h:106
octave_lvalue lvalue(tree_evaluator &tw)
Definition: pt-id.cc:68
octave_value evaluate(tree_evaluator &tw, int nargout=1)
Definition: pt-id.h:92
void accept(tree_walker &tw)
Definition: pt-select.h:109
tree_if_command_list * cmd_list()
Definition: pt-select.h:133
bool is_end_of_fcn_or_script() const
Definition: pt-cmd.h:73
bool takes_varargs() const
Definition: pt-misc.h:81
tree_parameter_list * dup(symbol_scope &scope) const
Definition: pt-misc.cc:69
bool varargs_only()
Definition: pt-misc.h:83
tree_expression * left_hand_side()
Definition: pt-loop.h:165
tree_expression * control_expr()
Definition: pt-loop.h:167
tree_statement_list * body()
Definition: pt-loop.h:171
tree_statement_list * body()
Definition: pt-spmd.h:55
void accept(tree_walker &tw)
Definition: pt-stmt.h:191
bool is_active_breakpoint(tree_evaluator &tw) const
Definition: pt-stmt.cc:103
tree_command * command()
Definition: pt-stmt.h:95
int column() const
Definition: pt-stmt.cc:127
bool is_expression() const
Definition: pt-stmt.h:76
tree_expression * expression()
Definition: pt-stmt.h:97
void accept(tree_walker &tw)
Definition: pt-stmt.h:118
int line() const
Definition: pt-stmt.cc:119
bool is_end_of_fcn_or_script() const
Definition: pt-stmt.cc:152
tree_expression * case_label()
Definition: pt-select.h:181
tree_switch_case_list * case_list()
Definition: pt-select.h:250
tree_expression * switch_value()
Definition: pt-select.h:248
tree_statement_list * cleanup()
Definition: pt-except.h:70
tree_identifier * identifier()
Definition: pt-except.h:66
tree_statement_list * body()
Definition: pt-except.h:68
tree_statement_list * cleanup()
Definition: pt-except.h:132
tree_statement_list * body()
Definition: pt-except.h:130
tree_statement_list * body()
Definition: pt-loop.h:75
tree_expression * condition()
Definition: pt-loop.h:73
virtual int line() const
Definition: pt.h:56
bool is_active_breakpoint(tree_evaluator &tw) const
Definition: pt.h:92
virtual void accept(tree_walker &tw)=0
virtual int column() const
Definition: pt.h:58
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
void error_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1033
void warning(const char *fmt,...)
Definition: error.cc:1063
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1078
void() error(const char *fmt,...)
Definition: error.cc:988
void interpreter_try(octave::unwind_protect &)
#define panic_if(cond)
Definition: error.h:509
#define panic_impossible()
Definition: error.h:503
void err_indexed_cs_list()
Definition: errwarn.cc:65
std::string dir_sep_str()
std::string dir_sep_chars()
char dir_sep_char()
octave::sys::time Vlast_prompt_time
Definition: input.cc:83
bool octave_completion_matches_called
Definition: input.cc:86
bool iskeyword(const std::string &s)
Definition: lex.cc:1335
bool isinf(double x)
Definition: lo-mappers.h:203
F77_RET_T const F77_DBLE const F77_DBLE * f
octave_value_list call_mex(octave_mex_function &mex_fcn, const octave_value_list &args, int nargout_arg)
Definition: mex.cc:4469
T octave_idx_type m
Definition: mx-inlines.cc:781
octave_idx_type n
Definition: mx-inlines.cc:761
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:289
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:798
bool valid_identifier(const char *s)
Definition: utils.cc:79
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:583
int release_unreferenced_dynamic_libraries()
Definition: oct-shlib.cc:72
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219
#define octave_stdout
Definition: pager.h:309
octave_value parse_fcn_file(interpreter &interp, const std::string &full_file, const std::string &file, const std::string &dir_name, const std::string &dispatch_type, const std::string &package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup)
Definition: oct-parse.cc:9903
std::atomic< sig_atomic_t > octave_interrupt_state
Definition: quit.cc:39
std::string fcn_file_in_path(const std::string &)
void sleep(double seconds, bool do_graphics_events=false)
F77_RET_T len
Definition: xerbla.cc:61