26 #if defined (HAVE_CONFIG_H)
66 : m_ok (false), m_file (file), m_dir (), m_fcn (), m_class_name ()
68 std::string abs_file = sys::env::make_absolute (file);
72 std::size_t
len = fcn.length ();
73 if (
len >= 2 && fcn[
len-2] ==
'.' && fcn[
len-1] ==
'm')
74 fcn = fcn.substr (0,
len-2);
78 if (pos != std::string::npos && pos < dir.length () - 1)
80 if (dir[pos+1] ==
'@')
82 m_class_name = dir.substr (pos+1);
86 dir = dir.substr (0, pos);
101 std::string file ()
const {
return m_file; }
102 std::string dir ()
const {
return m_fcn; }
103 std::string fcn ()
const {
return m_fcn; }
104 std::string class_name ()
const {
return m_class_name; }
106 bool ok ()
const {
return m_ok; }
114 std::string m_class_name;
126 bp_table::m_errors_that_stop.clear ();
129 bp_table::m_caught_that_stop.clear ();
132 bp_table::m_warnings_that_stop.clear ();
151 fail = (U.
numel () > 1);
157 else if (! W(0).iscell ())
161 Cell V = W(0).cell_value ();
162 for (
int i = 0; i <
V.numel (); i++)
164 m_errors_that_stop.insert (
V(i).string_value ());
171 error (
"dbstop: invalid 'errs' field");
178 fail = (U.
numel () > 1);
184 else if (! W(0).iscell ())
188 Cell V = W(0).cell_value ();
189 for (
int i = 0; i <
V.numel (); i++)
191 m_caught_that_stop.insert (
V(i).string_value ());
198 error (
"dbstop: invalid 'caught' field");
205 fail = (U.
numel () > 1);
211 else if (! W(0).iscell ())
215 Cell V = W(0).cell_value ();
216 for (
int i = 0; i <
V.numel (); i++)
218 m_warnings_that_stop.insert (
V(i).string_value ());
225 error (
"dbstop: invalid 'warn' field");
238 const std::string& fcn_ident,
240 const std::string& condition,
257 for (
auto& lineno : retval)
265 const char *s = strchr (fcn_ident.c_str (),
'>');
267 m_bp_set.insert (fcn_ident.substr (0, s - fcn_ident.c_str ()));
269 m_bp_set.insert (fcn_ident);
288 if (cond.length () > 0)
295 error (
"dbstop: Cannot parse condition '%s'", cond.c_str ());
300 std::shared_ptr<tree_statement_list> stmt_list
305 "condition is not empty, but has nothing to evaluate");
308 if (stmt_list->length () == 1
309 && (stmt = stmt_list->front ())
314 error (
"dbstop: condition cannot be an assignment. "
315 "Did you mean '=='?");
318 error (
"dbstop: condition must be an expression");
349 std::string& fcn_name,
350 std::string& class_name,
354 int nargin = args.
length ();
359 if (nargin == 0 || ! args(0).is_string ())
363 bool seen_in =
false;
364 bool seen_at =
false;
365 bool seen_if =
false;
371 if (args(pos).is_string ())
373 std::string arg = args(pos).string_value ();
379 else if (arg ==
"at")
384 else if (arg ==
"if")
389 else if (atoi (args(pos).string_value ().c_str ()) > 0)
398 error (
"%s: '%s' missing argument", who,
400 ?
"in" : (tok ==
dbstop_at ?
"at" :
"if")));
406 fcn_name = args(pos).string_value ();
408 error (
"%s: Too many function names specified -- %s",
409 who, fcn_name.c_str ());
410 else if (seen_at || seen_if)
411 error (
"%s: function name must come before line number and 'if'",
419 error (
"%s: Only one 'at' clause is allowed -- %s",
420 who, args(pos).string_value ().c_str ());
422 error (
"%s: line number must come before 'if' clause\n", who);
426 error (
"%s: line number must come before 'if' clause\n", who);
429 std::string arg = args(pos).string_value ();
434 if (atoi (arg.c_str ()) == 0)
438 class_name = fcn_name;
451 error (
"%s: function name must come before line number "
457 for ( ; pos < nargin; pos++)
459 if (args(pos).is_string ())
461 int line = atoi (args(pos).string_value ().c_str ());
468 else if (args(pos).isnumeric ())
473 lines.
insert (
static_cast<int> (arg.
elem (j)));
476 error (
"%s: Invalid argument type %s",
477 who, args(pos).type_name ().c_str ());
485 for (; pos < nargin; pos++)
487 if (args(pos).is_string ())
488 cond +=
' ' + args(pos).string_value ();
490 error (
"%s: arguments to 'if' must all be strings", who);
493 cond = cond.substr (1);
497 std::string condition = args(pos).string_value ();
498 bool on_off = !
strcmp (who,
"dbstop");
503 if (condition ==
"error")
504 process_id_list (who, condition, args, nargin, pos, on_off,
506 else if (condition ==
"warning")
507 process_id_list (who, condition, args, nargin, pos, on_off,
508 m_warnings_that_stop);
509 else if (condition ==
"caught" && nargin > pos+1
510 && args(pos+1).string_value () ==
"error")
513 process_id_list (who, condition, args, nargin, pos, on_off,
516 else if (condition ==
"interrupt")
520 else if (condition ==
"naninf")
522 #if defined (DBSTOP_NANINF)
523 Vdebug_on_naninf = on_off;
526 warning (
"%s: condition '%s' not yet supported",
527 who, condition.c_str ());
531 error (
"%s: invalid condition %s",
532 who, condition.c_str ());
571 bp_table::set_stop_flag (
const char *who,
const std::string& condition,
577 if (condition ==
"error")
579 else if (condition ==
"warning")
581 else if (condition ==
"caught")
584 error (
"%s: internal error in set_stop_flag", who);
588 bp_table::process_id_list (
const char *who,
589 const std::string& condition,
591 int nargin,
int& pos,
bool on_off,
592 std::set<std::string>& id_list)
598 if (! args(pos).is_string () || nargin > pos+1)
599 error (
"%s: ID must be a single string", who);
602 id_list.insert (args(pos).string_value ());
603 set_stop_flag (who, condition,
true);
607 id_list.erase (args(pos).string_value ());
608 if (id_list.empty ())
609 set_stop_flag (who, condition,
false);
615 set_stop_flag (who, condition, on_off);
617 if (condition ==
"error")
632 int *end_line =
nullptr)
640 std::map<std::string, octave_value> subfcns = main_fcn->
subfunctions ();
641 for (
const auto& str_val_p : subfcns)
643 if (str_val_p.second.is_user_function ())
645 auto *dbg_subfcn = str_val_p.second.user_function_value ();
652 if (dbg_subfcn->ending_line () < earliest_end
653 && dbg_subfcn->ending_line () >= lineno
654 && dbg_subfcn->beginning_line () <= lineno)
656 earliest_end = dbg_subfcn->ending_line ();
657 retval = find_fcn_by_line (dbg_subfcn, lineno, &earliest_end);
662 if (dbg_subfcn->beginning_line () >= lineno && ! next_fcn)
663 next_fcn = dbg_subfcn;
672 if (e >= lineno && e < earliest_end)
684 if (end_line && earliest_end < *end_line)
685 *end_line = earliest_end;
695 const std::string& condition)
698 line_info.insert (
line);
703 return result.empty () ? 0 : *(result.begin ());
710 class user_code_provider
713 user_code_provider (
const std::string& who,
const std::string& fcn_ident,
715 : m_fcn (nullptr), m_is_valid (false)
718 if (m_fcn && ! (m_fcn->is_classdef_method ()
719 || m_fcn->is_classdef_constructor ()))
730 std::string class_name = fcn_ident;
731 const char *s = strchr (fcn_ident.c_str (),
'/');
732 if (s && fcn_ident[0] ==
'@')
733 class_name = fcn_ident.substr (1, s - fcn_ident.c_str () - 1);
736 m_is_valid = m_cls.ok () && (m_cls.get_name () == class_name);
738 populate_function_cache ();
740 error (
"%s: unable to find function '%s'\n", who.c_str (),
751 return find_fcn_by_line (m_fcn,
line);
753 return m_cls.get_method (
line).user_code_value (
true);
756 bool is_function ()
const {
return m_fcn; }
758 bool is_valid ()
const {
return m_is_valid; }
760 size_t number_of_functions ()
const
768 return m_methods_cache.size ();
779 if (i < m_methods_cache.size ())
780 return m_methods_cache[i];
786 void populate_function_cache ()
788 if (m_methods_cache.empty ())
791 const std::map<std::string, cdef_method>& map
792 = m_cls.get_method_map (
false,
true);
793 for (
auto iter = map.cbegin (); iter != map.cend (); ++iter)
798 m_methods_cache.push_back (fcn);
804 std::vector<octave_user_code *> m_methods_cache;
815 const std::string& condition)
817 user_code_provider user_code (
"add_breakpoints_in_function", fcn_ident,
824 for (
const auto& lineno : lines)
830 line_info.insert (lineno);
834 std::string ident = fcn_ident;
835 if (! user_code.is_function () && fcn_ident[0] !=
'@' && dbg_fcn)
838 ident =
"@" + fcn_ident +
"/" + dbg_fcn->
name ();
841 if (dbg_fcn && add_breakpoint_1 (dbg_fcn, ident, line_info,
844 if (! ret_one.empty ())
846 int line = *(ret_one.begin ());
849 retval.insert (
line);
862 const std::string& condition)
867 bp_file_info info (m_evaluator, file);
872 std::string fcn_ident;
873 if (info.class_name ().empty ())
874 fcn_ident = info.fcn ();
876 fcn_ident =
"@" + info.class_name () +
"/" + info.fcn ();
884 const std::string& condition)
889 bp_file_info info (m_evaluator, file);
894 std::string fcn_ident;
895 if (info.class_name ().empty ())
896 fcn_ident = info.fcn ();
898 fcn_ident =
"@" + info.class_name () +
"/" + info.fcn ();
905 const std::string& fcn_ident,
920 if (results.
length () > 0)
926 for (
const auto& lineno : lines)
936 auto it = m_bp_set.find (fcn_ident);
937 if (results.
empty () && it != m_bp_set.end ())
941 retval = results.
length ();
952 line_info.insert (
line);
966 retval = results.size ();
971 user_code_provider user_code (
"remove_breakpoints_from_function",
975 for (
const auto line : lines)
985 if (results.
length () > 0)
999 if (dbg_fcn !=
nullptr)
1002 const std::list<std::string> subfcn_names
1005 std::map<std::string, octave_value> subfcns
1008 for (
const auto& subf_nm : subfcn_names)
1010 const auto q = subfcns.find (subf_nm);
1012 if (q != subfcns.end ())
1017 retval += remove_breakpoint_1 (dbg_subfcn, fcn_ident, lines);
1023 const bool no_breakpoints
1025 auto iter = m_bp_set.find (fcn_ident);
1026 if (no_breakpoints && iter != m_bp_set.end ())
1027 m_bp_set.erase (iter);
1044 user_code_provider user_code (
"remove_all_breakpoints_from_function",
1045 fcn_ident, fcn, silent);
1047 if (user_code.is_valid ())
1049 for (
size_t i = 0; i != user_code.number_of_functions (); ++i)
1066 auto it = m_bp_set.find (fcn_ident);
1067 if (it != m_bp_set.end ())
1068 m_bp_set.erase (it);
1082 bp_file_info info (m_evaluator, file);
1097 bp_file_info info (m_evaluator, file);
1112 bp_file_info info (m_evaluator, file);
1125 for (
auto it = m_bp_set.cbegin (), it_next = it;
1126 it != m_bp_set.cend ();
1141 for (
int i = 0; i < slist.
length (); i++)
1143 if (slist(i).string_value () == match)
1145 retval = slist(i).string_value ();
1159 std::set<std::string> tmp_bp_set = m_bp_set;
1161 for (
auto& bp_fname : tmp_bp_set)
1163 if (fname_list.
empty ()
1167 user_code_provider user_code (
"get_breakpoint_list", bp_fname,
1170 std::list<bp_type> all_bkpts;
1171 std::list<bp_type>::iterator it (all_bkpts.begin ());
1172 for (
size_t i = 0; i != user_code.number_of_functions (); ++i)
1182 const std::list<bp_type>& bp
1185 it = all_bkpts.insert (it, bp.cbegin (),
1191 if (! all_bkpts.empty ())
1192 retval[bp_fname] = all_bkpts;
1196 if (dbg_fcn !=
nullptr)
1198 const std::list<std::string> subf_nm
1201 std::map<std::string, octave_value> subfcns
1204 for (
const auto& subfcn_nm : subf_nm)
1206 const auto q = subfcns.find (subfcn_nm);
1208 if (q != subfcns.end ())
1216 std::list<bp_type> bkpts
1219 if (! bkpts.empty ())
1222 = bp_fname +
'>' + dbg_subfcn->
name ();
1224 retval[key] = bkpts;
1255 if (m_errors_that_stop.empty ())
1264 Cell errs (
dim_vector (bp_table::m_errors_that_stop.size (), 1));
1267 for (
const auto& e : m_errors_that_stop)
1282 if (m_caught_that_stop.empty ())
1294 for (
const auto& e : m_caught_that_stop)
1309 if (m_warnings_that_stop.empty ())
1321 for (
const auto&
w : m_warnings_that_stop)
1345 OCTAVE_END_NAMESPACE(
octave)
ComplexNDArray concat(NDArray &ra, ComplexNDArray &rb, const Array< octave_idx_type > &ra_idx)
cdef_class lookup_class(const std::string &name, bool error_if_not_found, bool load_if_not_found)
charNDArray max(char d, const charNDArray &m)
T & elem(octave_idx_type n)
Size of the specified dimension.
Array< T, Alloc > & insert(const Array< T, Alloc > &a, const Array< octave_idx_type > &idx)
Insert an array into another at a specified position.
bool isempty() const
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Cell index(const octave_value_list &idx, bool resize_ok=false) const
void statement_list(std::shared_ptr< tree_statement_list > &lst)
bool condition_valid(const std::string &cond)
int remove_breakpoint_from_function(const std::string &fcn_ident="", int line=1)
int remove_breakpoint_from_file(const std::string &file="", int line=1)
void remove_all_breakpoints()
bp_lines remove_all_breakpoints_from_function(const std::string &fcn_ident, bool silent=false)
fname_bp_map get_breakpoint_list(const octave_value_list &fname_list)
int remove_breakpoints_from_file(const std::string &file="", const bp_lines &lines=bp_lines())
int remove_breakpoints_from_function(const std::string &fcn_ident="", const bp_lines &lines=bp_lines())
int add_breakpoint_in_function(const std::string &fcn_ident="", int line=1, const std::string &condition="")
bp_lines add_breakpoints_in_function(const std::string &fcn_ident="", const bp_lines &lines=bp_lines(), const std::string &condition="")
void dbstop_process_map_args(const octave_map &mv)
int add_breakpoint_in_file(const std::string &file="", int line=1, const std::string &condition="")
std::map< std::string, std::list< bp_type > > fname_bp_map
bp_lines add_breakpoints_in_file(const std::string &file="", const bp_lines &lines=bp_lines(), const std::string &condition="")
bp_lines remove_all_breakpoints_from_file(const std::string &file, bool silent=false)
void dbclear_all_signals()
octave_map stop_on_err_warn_status(bool to_screen)
void parse_dbfunction_params(const char *who, const octave_value_list &args, std::string &fcn_name, std::string &class_name, bp_table::bp_lines &lines, std::string &cond)
Vector representing the dimensions (size) of an Array.
octave_value debug_on_warning(const octave_value_list &args, int nargout)
octave_value debug_on_caught(const octave_value_list &args, int nargout)
octave_value debug_on_error(const octave_value_list &args, int nargout)
Provides threadsafe access to octave.
void update_breakpoint(bool insert, const std::string &file, int line, const std::string &cond="")
event_manager & get_event_manager()
load_path & get_load_path()
error_system & get_error_system()
bool contains_file_in_dir(const std::string &file_name, const std::string &dir_name)
virtual bool is_user_function() const
virtual octave_user_code * user_code_value(bool silent=false)
virtual std::string profiler_name() const
virtual std::list< std::string > subfunction_names() const
bool isfield(const std::string &name) const
void assign(const std::string &k, const Cell &val)
const Cell & contents(const_iterator p) const
std::string fcn_file_name() const
virtual std::map< std::string, octave_value > subfunctions() const
octave::tree_statement_list * body()
Array< octave_value > array_value() const
octave_idx_type length() const
bool in_debug_repl() const
interpreter & get_interpreter()
octave_user_code * get_user_code(const std::string &fname="")
virtual bool is_assignment_expression() const
octave_value_list list_breakpoints()
std::list< bp_type > breakpoints_and_conds()
void delete_breakpoint(int line)
bp_table::bp_lines remove_all_breakpoints(event_manager &evmgr, const std::string &file)
bp_table::bp_lines add_breakpoint(event_manager &evmgr, const std::string &file, const bp_table::bp_lines &lines, const std::string &condition)
bool is_expression() const
tree_expression * expression()
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void warning(const char *fmt,...)
void() error(const char *fmt,...)
std::string dir_sep_chars()
std::string dirname(const std::string &path)
std::string tail(const std::string &path)
F77_RET_T const F77_INT const F77_INT const F77_INT const F77_DBLE const F77_DBLE F77_INT F77_DBLE * V
std::complex< double > w(std::complex< double > z, double relerr=0)
std::string find_bkpt_list(octave_value_list slist, std::string match)
bool strcmp(const T &str_a, const T &str_b)
Octave string utility functions.