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