Mercurial > octave
changeset 21754:34a582f2edd7
Allow dbstop in functions nested in subfunctions (bug #47918).
* debug.cc (find_fcn_by_line): New function.
Recursive code refactored out of bp_table::do_add_breakpoint
* debug.cc (bp_table:do_add_breakpoint):
Factor out the search for the function containing the specified line.
author | Lachlan Andrew <lachlanbis@gmail.com> |
---|---|
date | Wed, 18 May 2016 13:05:09 +1000 |
parents | be52b94354a3 |
children | 08e861873118 |
files | libinterp/corefcn/debug.cc |
diffstat | 1 files changed, 64 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/debug.cc Tue May 17 22:45:07 2016 +1000 +++ b/libinterp/corefcn/debug.cc Wed May 18 13:05:09 2016 +1000 @@ -644,10 +644,71 @@ return true; } +// Return the sub/nested/main function of MAIN_FCN that contains +// line number LINENO of the source file. +// If END_LINE != 0, *END_LINE is set to last line of the returned function. +static octave_user_code* +find_fcn_by_line (octave_user_code *main_fcn, int lineno, int *end_line = 0) +{ + octave_user_code *retval = 0; + octave_user_code *next_fcn = 0; // 1st function starting after lineno + + // Find innermost nested (or parent) function containing lineno. + int earliest_end = std::numeric_limits<int>::max (); + + std::map<std::string, octave_value> subfcns = main_fcn->subfunctions (); + for (std::map<std::string,octave_value>::const_iterator q = subfcns.begin (); + q != subfcns.end (); q++) + { + if (q->second.is_user_function ()) + { + octave_user_function *dbg_subfcn = q->second.user_function_value (); + + // Check if lineno is within dbg_subfcn. + // FIXME: we could break when beginning_line() > lineno, + // but that makes the code "fragile" + // if the order of walking subfcns changes, + // for a minor speed improvement in non-critical code. + if (dbg_subfcn->ending_line () < earliest_end + && dbg_subfcn->ending_line () >= lineno + && dbg_subfcn->beginning_line () <= lineno) + { + earliest_end = dbg_subfcn->ending_line (); + retval = find_fcn_by_line (dbg_subfcn, lineno, &earliest_end); + } + + // Find the first fcn starting after lineno. + // This is used if line is not inside any function. + if (dbg_subfcn->beginning_line () >= lineno && ! next_fcn) + next_fcn = dbg_subfcn; + } + } + + // The breakpoint is either in the subfunction found above, + // or in the main function, which we check now. + if (main_fcn->is_user_function ()) + { + int e = dynamic_cast<octave_user_function*> (main_fcn)->ending_line (); + if (e >= lineno && e < earliest_end) + retval = main_fcn; + + if (! retval) + retval = next_fcn; + } + else // main_fcn is a script. + { + if (! retval) + retval = main_fcn; + } + + if (end_line != 0 && earliest_end < *end_line) + *end_line = earliest_end; + + return retval; +} + // Given file name fname, find the subfunction at line and create // a breakpoint there. Put the system into debug_mode. -// (FIXME: If line is multiple lines, what happens if they are in different -// functions?) bp_table::intmap bp_table::do_add_breakpoint (const std::string& fname, const bp_table::intmap& line, @@ -662,9 +723,6 @@ intmap retval; - const std::list<std::string> subfcn_names = main_fcn->subfunction_names (); - std::map<std::string, octave_value> subfcns = main_fcn->subfunctions (); - octave_idx_type len = line.size (); for (int i = 0; i < len; i++) @@ -675,56 +733,7 @@ { int lineno = m->second; - octave_user_code *dbg_fcn = 0; - octave_user_code *next_fcn = 0; // 1st function starting after line - - // Find innermost nested (or parent) function containing line. - int earliest_end = std::numeric_limits<int>::max (); - - for (std::list<std::string>::const_iterator p - = subfcn_names.begin (); - p != subfcn_names.end (); p++) - { - std::map<std::string, octave_value>::const_iterator - q = subfcns.find (*p); - - if (q != subfcns.end () && q->second.is_user_function ()) - { - octave_user_function *dbg_subfcn - = q->second.user_function_value (); - - if (dbg_subfcn->ending_line () < earliest_end - && dbg_subfcn->ending_line () >= lineno - && dbg_subfcn->beginning_line () <= lineno) - { - earliest_end = dbg_subfcn->ending_line (); - dbg_fcn = dbg_subfcn; - } - - // First fcn starting after line. - // This is used if line is not inside any function. - if (dbg_subfcn->beginning_line () >= lineno && ! next_fcn) - next_fcn = dbg_subfcn; - } - } - - // The breakpoint is either in the subfunction found above, - // or in the main function, which we check now. - if (main_fcn->is_user_function ()) - { - int e = dynamic_cast<octave_user_function*> (main_fcn) - ->ending_line (); - if (e >= lineno && e < earliest_end) - dbg_fcn = main_fcn; - - if (! dbg_fcn) - dbg_fcn = next_fcn; - } - else - { - if (! dbg_fcn) - dbg_fcn = main_fcn; - } + octave_user_code *dbg_fcn = find_fcn_by_line (main_fcn, lineno); // We've found the right (sub)function. Now insert the breakpoint. // We insert all breakpoints.