26 #if defined (HAVE_CONFIG_H)
54 static const char *bt_fieldnames[] =
55 {
"file",
"name",
"line",
"column",
nullptr };
60 : m_evaluator (evaluator), m_cs (), m_curr_frame (0),
61 m_max_stack_depth (1024), m_global_values ()
70 error (
"current_function: call stack is empty");
74 std::size_t idx = m_curr_frame;
76 if (idx > 0 && skip_first)
81 fcn = m_cs[idx]->function ();
99 const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame];
100 retval = elt->line ();
113 const std::shared_ptr<stack_frame> elt = m_cs[m_curr_frame];
114 retval = elt->column ();
129 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
133 if (
f &&
f->is_user_code ())
149 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
153 if (
f &&
f->is_user_code ())
174 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
178 if (
f &&
f->is_user_code ())
180 int column = elt->column ();
199 const std::shared_ptr<stack_frame> elt = m_cs[xframe];
203 if (
f &&
f->is_user_code ())
204 return elt->unwind_protect_frame ();
216 if (m_curr_frame == 0)
219 std::size_t i = m_curr_frame;
223 const std::shared_ptr<stack_frame> elt = m_cs[i--];
227 if (
f &&
f->is_user_code ())
243 if (m_curr_frame == 0)
246 std::size_t i = m_curr_frame;
250 const std::shared_ptr<stack_frame> elt = m_cs[i--];
254 if (
f &&
f->is_user_code ())
258 retval = elt->line ();
273 if (m_curr_frame == 0)
277 std::size_t i = m_curr_frame;
281 const std::shared_ptr<stack_frame> elt = m_cs[i--];
285 if (
f &&
f->is_user_code ())
289 retval = elt->column ();
301 return m_cs[m_curr_frame]->get_dispatch_class ();
307 m_cs[m_curr_frame]->set_dispatch_class (class_name);
317 bool retval = (
f &&
f->is_class_method ());
320 dispatch_class =
f->dispatch_class ();
332 bool retval = (
f &&
f->is_class_constructor ());
335 dispatch_class =
f->dispatch_class ();
345 auto p = m_cs.cend ();
347 while (p != m_cs.cbegin ())
349 const std::shared_ptr<stack_frame> elt = *(--p);
353 if (
f && !
f->is_user_script ())
363 void call_stack::get_new_frame_index_and_links
364 (std::size_t& new_frame_idx, std::shared_ptr<stack_frame>& parent_link,
365 std::shared_ptr<stack_frame>& static_link)
const
369 std::size_t prev_frame_idx = m_curr_frame;
371 new_frame_idx = m_cs.size ();
374 if (new_frame_idx >
static_cast<std::size_t
> (m_max_stack_depth))
375 error (
"max_stack_depth exceeded");
380 if (new_frame_idx == 0)
383 parent_link = m_cs[prev_frame_idx];
389 ? parent_link : parent_link->static_link ())
396 std::size_t new_frame_idx;
397 std::shared_ptr<stack_frame> parent_link;
398 std::shared_ptr<stack_frame> static_link;
400 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
402 std::shared_ptr<stack_frame>
404 parent_link, static_link));
406 m_cs.push_back (new_frame);
408 m_curr_frame = new_frame_idx;
413 const std::shared_ptr<stack_frame>& closure_frames)
415 std::size_t new_frame_idx;
416 std::shared_ptr<stack_frame> parent_link;
417 std::shared_ptr<stack_frame> static_link;
419 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
421 std::shared_ptr<stack_frame>
423 parent_link, static_link,
426 m_cs.push_back (new_frame);
428 m_curr_frame = new_frame_idx;
434 const std::shared_ptr<stack_frame>& closure_frames)
436 std::size_t new_frame_idx;
437 std::shared_ptr<stack_frame> parent_link;
438 std::shared_ptr<stack_frame> static_link;
440 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
442 std::shared_ptr<stack_frame>
444 parent_link, static_link, local_vars,
447 m_cs.push_back (new_frame);
449 m_curr_frame = new_frame_idx;
455 std::size_t new_frame_idx;
456 std::shared_ptr<stack_frame> parent_link;
457 std::shared_ptr<stack_frame> static_link;
459 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
461 std::shared_ptr<stack_frame>
463 parent_link, static_link));
465 m_cs.push_back (new_frame);
467 m_curr_frame = new_frame_idx;
473 std::size_t new_frame_idx;
474 std::shared_ptr<stack_frame> parent_link;
475 std::shared_ptr<stack_frame> static_link;
477 get_new_frame_index_and_links (new_frame_idx, parent_link, static_link);
479 std::shared_ptr<stack_frame>
481 parent_link, static_link));
483 m_cs.push_back (new_frame);
485 m_curr_frame = new_frame_idx;
493 if (
n < m_cs.size ())
501 const std::shared_ptr<stack_frame> elt = m_cs[
n];
513 std::size_t user_frame = m_curr_frame;
515 std::shared_ptr<stack_frame> frm = m_cs[user_frame];
517 if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
518 || frm->is_scope_frame ()))
520 frm = frm->static_link ();
522 user_frame = frm->index ();
528 std::shared_ptr<stack_frame>
543 if (start >= m_cs.size ())
544 error (
"invalid stack frame");
548 if (start == 0 &&
n < 0)
556 std::shared_ptr<stack_frame> frm = m_cs[start];
558 if (! (frm && (frm->is_user_fcn_frame ()
559 || frm->is_user_script_frame ()
560 || frm->is_scope_frame ())))
561 error (
"call_stack::dbupdown: invalid initial frame in call stack!");
569 std::size_t xframe = frm->index ();
589 std::size_t last_good_frame = 0;
595 if (frm->is_user_fcn_frame () || frm->is_user_script_frame ()
596 || frm->is_scope_frame ())
598 last_good_frame = xframe;
614 if (xframe == m_cs.size ())
619 m_cs[last_good_frame]->display_stopped_in_message (
octave_stdout);
621 return last_good_frame;
649 std::shared_ptr<stack_frame> caller_frame = m_cs[start]->static_link ();
654 m_curr_frame = caller_frame ? caller_frame->index () : 0;
660 if (m_curr_frame > 0)
664 std::list<std::shared_ptr<stack_frame>>
667 std::list<std::shared_ptr<stack_frame>> frames;
678 for (std::size_t
n = m_cs.size () - 1;
n > 0;
n--)
680 std::shared_ptr<stack_frame> frm = m_cs[
n];
682 if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
683 || frm->is_scope_frame ())
685 if (frm->index () == curr_frame)
686 curr_user_frame = frames.size ();
688 frames.push_back (frm);
698 std::list<std::shared_ptr<stack_frame>>
706 std::list<frame_info>
708 bool print_subfn)
const
710 std::list<std::shared_ptr<stack_frame>> frames
713 std::list<frame_info> retval;
715 for (
const auto& frm : frames)
717 if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
718 || frm->is_scope_frame ())
720 retval.push_back (frame_info (frm->fcn_file_name (),
721 frm->fcn_name (print_subfn),
722 frm->line (), frm->column ()));
729 std::list<frame_info>
739 bool print_subfn)
const
741 std::list<std::shared_ptr<stack_frame>> frames
744 std::size_t nframes = frames.size ();
755 for (
const auto& frm : frames)
757 if (frm->is_user_script_frame () || frm->is_user_fcn_frame ()
758 || frm->is_scope_frame ())
760 file(k) = frm->fcn_file_name ();
761 name(k) = frm->fcn_name (print_subfn);
763 column(k) = frm->
column ();
777 return backtrace (curr_user_frame,
true);
792 if (m_cs.size () > 1)
794 std::shared_ptr<stack_frame> elt = m_cs.back ();
796 std::shared_ptr<stack_frame> caller = elt->parent_link ();
798 m_curr_frame = caller->index ();
800 if (elt->is_closure_context ())
801 elt->break_closure_cycles (elt);
803 elt->clear_parent_static_link ();
809 std::shared_ptr<stack_frame>
814 std::shared_ptr<stack_frame> elt = std::move (m_cs.back ());
817 m_curr_frame = elt->parent_frame_index ();
819 if (elt->is_closure_context ())
820 elt->break_closure_cycles (elt);
822 elt->clear_parent_static_link ();
833 while (! m_cs.empty ())
840 return m_cs[m_curr_frame]->all_variables ();
843 std::list<std::string>
846 std::list<std::string> retval;
848 for (
const auto& nm_ov : m_global_values)
850 if (nm_ov.second.is_defined ())
851 retval.push_back (nm_ov.first);
859 std::list<std::string>
862 return m_cs[0]->variable_names ();
865 std::list<std::string>
868 return m_cs[m_curr_frame]->variable_names ();
874 auto p = m_global_values.find (name);
876 if (p != m_global_values.end ())
885 for (
auto& nm_ov : m_global_values)
887 if (pat.
match (nm_ov.first))
897 for (
auto& nm_ov : m_global_values)
907 for (
auto& nm_ov : m_global_values)
914 return m_cs[m_curr_frame]->glob_symbol_info (pattern);
920 return m_cs[m_curr_frame]->regexp_symbol_info (pattern);
926 return m_cs[m_curr_frame]->get_symbol_info ();
932 return m_cs[0]->get_symbol_info ();
940 "max_stack_depth", 0);
946 m_cs[m_curr_frame]->make_persistent (sym);
952 m_cs[m_curr_frame]->make_global (sym);
958 auto p = m_global_values.find (name);
960 return p == m_global_values.end () ?
octave_value () : p->second;
966 return m_global_values[name];
972 return m_cs[0]->varval (name);
979 m_cs[0]->assign (name, value);
984 bool return_list,
bool verbose)
988 std::string my_name = argv[0];
990 std::string file_name;
992 bool from_file =
false;
993 bool global_only =
false;
994 bool have_regexp =
false;
999 if (argv[i] ==
"-file")
1002 error (
"%s: -file option may only be specified once",
1008 error (
"%s: -file argument must be followed by a filename",
1011 file_name = argv[++i];
1013 else if (argv[i] ==
"-regexp")
1017 else if (argv[i] ==
"global")
1019 else if (argv[i][0] ==
'-')
1020 warning (
"%s: unrecognized option '%s'", my_name.c_str (),
1028 int npatterns = argc - i;
1032 patterns.
resize (npatterns);
1033 for (
int j = 0; j < npatterns; j++)
1034 patterns[j] = argv[i+j];
1063 std::string newmsg =
"Variables in the file " + file_name +
":\n";
1069 return do_who_two (patterns, have_regexp, return_list, verbose,
1078 return do_who_two (patterns, have_regexp, return_list, verbose);
1084 bool have_regexp,
bool return_list,
1085 bool verbose,
const std::string& msg)
1087 return m_cs[m_curr_frame]->who (patterns, have_regexp, return_list,
1095 bool return_list,
bool verbose,
1096 const std::string& msg)
1099 std::list<std::string> symbol_names;
1105 std::string pattern = patterns[j];
1107 std::list<std::string> tmp;
1113 for (
auto& nm_ov : m_global_values)
1116 tmp.push_back (nm_ov.first);
1123 for (
auto& nm_ov : m_global_values)
1125 if (pat.
match (nm_ov.first))
1126 tmp.push_back (nm_ov.first);
1130 for (
const auto& nm : tmp)
1138 bool is_formal =
false;
1139 bool is_global =
true;
1140 bool is_persistent =
false;
1142 symbol_info syminf (nm, value, is_formal, is_global,
1145 symbol_stats.
append (syminf);
1148 symbol_names.push_back (nm);
1157 std::string caller_fcn_name;
1160 caller_fcn_name = caller_fcn->
name ();
1162 return symbol_stats.
map_value (caller_fcn_name, 1);
1167 else if (! (symbol_stats.
empty () && symbol_names.empty ()))
1195 std::size_t nframes =
size ();
1197 for (std::size_t i = 0; i < nframes; i++)
1199 m_cs[i]->display (
false);
1200 if (i < nframes - 1)
1209 m_cs[m_curr_frame]->set_auto_fcn_var (avt, val);
1215 m_cs[m_curr_frame]->set_nargin (nargin);
1221 m_cs[m_curr_frame]->set_nargout (nargout);
1227 return m_cs[m_curr_frame]->get_auto_fcn_var (avt);
1230 DEFMETHOD (max_stack_depth, interp, args, nargout,
1300 int argc = args.length () + 1;
1306 return tw.
do_who (argc, argv, nargout == 1);
1388 int argc = args.length () + 1;
1394 return tw.
do_who (argc, argv, nargout == 1,
true);
1397 OCTAVE_END_NAMESPACE(
octave)
octave_value_list Fload(octave::interpreter &, const octave_value_list &=octave_value_list(), int=0)
Cell column(octave_idx_type i) const
void append(const elt_type &s)
void set_dispatch_class(const std::string &class_name)
octave_function * caller_function() const
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
octave_value get_top_level_value(const std::string &name) const
octave_value global_varval(const std::string &name) const
std::size_t find_current_user_frame() const
std::list< std::shared_ptr< stack_frame > > backtrace_frames() const
octave_value & global_varref(const std::string &name)
octave_value do_who_two(const string_vector &patterns, bool have_regexp, bool return_list, bool verbose, const std::string &msg="")
void set_top_level_value(const std::string &name, const octave_value &value)
int current_user_code_column() const
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
std::list< std::string > variable_names() const
symbol_info_list regexp_symbol_info(const std::string &pattern) const
void make_global(const symbol_record &sym)
std::shared_ptr< stack_frame > current_user_frame() const
std::shared_ptr< stack_frame > pop_return()
void clear_global_variables()
symbol_info_list glob_symbol_info(const std::string &pattern) const
bool is_class_method_executing(std::string &dispatch_class) const
bool goto_frame(std::size_t n=0, bool verbose=false)
int debug_user_code_column() const
void set_auto_fcn_var(stack_frame::auto_var_type avt, const octave_value &val)
symbol_info_list get_symbol_info()
symbol_info_list top_scope_symbol_info() const
std::list< std::string > global_variable_names() const
bool is_class_constructor_executing(std::string &dispatch_class) const
octave_map empty_backtrace() const
octave_function * current_function(bool skip_first=false) const
octave_value do_global_who_two(const string_vector &patterns, bool have_regexp, bool return_list, bool verbose, const std::string &msg="")
void clear_global_variable_pattern(const std::string &pattern)
unwind_protect * curr_fcn_unwind_protect_frame()
octave_map backtrace() const
int debug_user_code_line() const
octave_user_code * debug_user_code() const
call_stack(tree_evaluator &evaluator)
symbol_info_list all_variables()
void push(const symbol_scope &scope)
std::list< std::string > top_level_variable_names() const
void set_nargin(int nargin)
void clear_global_variable(const std::string &name)
octave_user_code * current_user_code() const
std::list< frame_info > backtrace_info() const
void set_nargout(int nargout)
int current_user_code_line() const
std::size_t dbupdown(std::size_t start, int n, bool verbose)
int current_column() const
std::string get_dispatch_class() const
void clear_global_variable_regexp(const std::string &pattern)
void make_persistent(const symbol_record &sym)
octave_value max_stack_depth(const octave_value_list &args, int nargout)
Vector representing the dimensions (size) of an Array.
line(const graphics_handle &mh, const graphics_handle &p)
virtual bool is_user_code() const
const Cell & contents(const_iterator p) const
bool is_match(const std::string &buffer) const
static stack_frame * create(tree_evaluator &tw, octave_function *fcn, std::size_t index, const std::shared_ptr< stack_frame > &parent_link, const std::shared_ptr< stack_frame > &static_link)
std::map< std::string, octave_value > local_vars_map
void resize(octave_idx_type n, const std::string &rfv="")
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix="") const
octave_idx_type numel() const
void display(std::ostream &os, const std::string &format) const
octave_map map_value(const std::string &caller_function_name, int nesting_level) const
bool match(const std::string &sym)
interpreter & get_interpreter()
octave_value do_who(int argc, const string_vector &argv, bool return_list, bool verbose=false)
octave_value max_stack_depth(const octave_value_list &args, int nargout)
octave_value whos_line_format(const octave_value_list &args, int nargout)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
void warning(const char *fmt,...)
void() error(const char *fmt,...)
F77_RET_T const F77_DBLE const F77_DBLE * f
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
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.