diff libinterp/parse-tree/pt-eval.cc @ 21157:94fc5f13d51b

dbstop: conditional breakpoint, dbstop if caught error etc. (bug #46795) * debug.cc (parse_dbfunction_params): Accept "in", "at" and "if" tokens. Only breakpoints are returned; "dbstop if error" etc. are processed in the parser. * debug.cc (dbstop_process_map_ags, Fdbstop): set breakpoints etc. based on the output of A=dbstatus. The structure of A is not Matlab compatible. * debug.cc (do_add_breakpoint_1, do_get_breakpoint_list): Store file (not subfunction) names in bp_set, to avoid crash in "dbclear all". * debug.cc (dbclear_all_signals, condition_valid, stop_on_err_warn_status): New function * debug.cc (do_add_breakpoint): take "condition" parameter. * debug.cc (do_get_breakpoint_list): Make invariant copy of bp_set (bug #44195) * debug.cc (do_add_breakpoint, do_remove_breakpoint, do_remove_all_breakpoints_in_file): More informative error messages. * debug.cc (Fdbclear): clear break on signals (error, warning etc.) * debug.cc (Fdbstatus): Return all breakpoints when debugging, so that "s = dbstatus; ...; dbstop (s)" works. (Related to bug #41338, bug #41556) * debug.cc (Fdbstatus): Return structure with conditions, and "if error" etc. * debug.h (debug_on_err, debug_on_caught, debug_on_warn): New functions * debug.h: Rename "fname_line_map" to "fname_bp_map", as it has conditions * error.cc (verror): Allow dbstop on selected errors, or errors in try/catch * error.h New globals: Vdebug_on_caught, in_try_catch. * toplev.cc: Experimental code for Matlab's "dbstop if naninf". * symtab.cc (load_class_constructor): Add class constructors to list of methods so they can be breakpointed * pt-pb.{cc,h} (take_action): Add "condition" to set_breakpoint call, track bp_cond_list. * pt-eval.cc visit_.*_command: Ask if breakpoint condition is satisfied. * pt-eval.cc (visit_try_catch_command): Count the number of levels of try/catch we are in to allow "dbstop if caught error". * pt-stmt.cc (set_breakpoint): Pass condition * pt-stmt.cc (is_breakpoint): If new argument is true, only return true if the condition is set. * pt-stmt.cc (bp_cond, preakpoints_and_conds): new function * pt-stmt.h: new declarations * pt.{cc,h} (meets_bp_condition, bp_cond): New function * octave-link.h (update_breakpoint): Accept condition
author Lachlan Andrew <lachlanbis@gmail.com>
date Sun, 24 Jan 2016 11:02:30 +1100
parents f5b17eb2508b
children a223cce1daa4
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-eval.cc	Sat Jan 30 08:22:36 2016 -0800
+++ b/libinterp/parse-tree/pt-eval.cc	Sun Jan 24 11:02:30 2016 +1100
@@ -97,7 +97,7 @@
 tree_evaluator::visit_break_command (tree_break_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   if (statement_context == function || statement_context == script
       || in_loop_command)
@@ -114,7 +114,7 @@
 tree_evaluator::visit_continue_command (tree_continue_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   if (statement_context == function || statement_context == script
       || in_loop_command)
@@ -210,7 +210,7 @@
 tree_evaluator::visit_global_command (tree_global_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   do_decl_init_list (do_global_init, cmd.initializer_list ());
 }
@@ -219,7 +219,7 @@
 tree_evaluator::visit_persistent_command (tree_persistent_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   do_decl_init_list (do_static_init, cmd.initializer_list ());
 }
@@ -282,7 +282,7 @@
 tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   // FIXME: need to handle PARFOR loops here using cmd.in_parallel ()
   // and cmd.maxproc_expr ();
@@ -397,7 +397,7 @@
 tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   unwind_protect frame;
 
@@ -538,7 +538,7 @@
         octave_call_stack::set_location (tic->line (), tic->column ());
 
       if (debug_mode && ! tic->is_else_clause ())
-        do_breakpoint (tic->is_breakpoint ());
+        do_breakpoint (tic->is_breakpoint (true));
 
       if (tic->is_else_clause () || expr->is_logically_true ("if"))
         {
@@ -580,7 +580,7 @@
 tree_evaluator::visit_no_op_command (tree_no_op_command& cmd)
 {
   if (debug_mode && cmd.is_end_of_fcn_or_script ())
-    do_breakpoint (cmd.is_breakpoint (), true);
+    do_breakpoint (cmd.is_breakpoint (true), true);
 }
 
 void
@@ -623,7 +623,7 @@
 tree_evaluator::visit_return_command (tree_return_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   // Act like dbcont.
 
@@ -683,7 +683,7 @@
           else
             {
               if (debug_mode)
-                do_breakpoint (expr->is_breakpoint ());
+                do_breakpoint (expr->is_breakpoint (true));
 
               // FIXME: maybe all of this should be packaged in
               // one virtual function that returns a flag saying whether
@@ -795,7 +795,7 @@
 tree_evaluator::visit_switch_command (tree_switch_command& cmd)
 {
   if (debug_mode)
-    do_breakpoint (cmd.is_breakpoint ());
+    do_breakpoint (cmd.is_breakpoint (true));
 
   tree_expression *expr = cmd.switch_value ();
 
@@ -853,12 +853,15 @@
     {
       try
         {
+          in_try_catch++;
           try_code->accept (*this);
+          in_try_catch--;
         }
       catch (const octave_execution_exception&)
         {
           recover_from_exception ();
 
+          in_try_catch--;          // must be restored before "catch" block
           execution_error = true;
         }
     }
@@ -886,8 +889,10 @@
               err.assign ("stack", last_error_stack ());
 
               ult.assign (octave_value::op_asn_eq, err);
+
             }
 
+              // perform actual "catch" block
           if (catch_code)
             catch_code->accept (*this);
         }
@@ -1030,7 +1035,7 @@
   for (;;)
     {
       if (debug_mode)
-        do_breakpoint (cmd.is_breakpoint ());
+        do_breakpoint (cmd.is_breakpoint (true));
 
       if (expr->is_logically_true ("while"))
         {
@@ -1077,7 +1082,7 @@
         break;
 
       if (debug_mode)
-        do_breakpoint (cmd.is_breakpoint ());
+        do_breakpoint (cmd.is_breakpoint (true));
 
       if (expr->is_logically_true ("do-until"))
         break;
@@ -1087,7 +1092,7 @@
 void
 tree_evaluator::do_breakpoint (tree_statement& stmt) const
 {
-  do_breakpoint (stmt.is_breakpoint (), stmt.is_end_of_fcn_or_script ());
+  do_breakpoint (stmt.is_breakpoint (true), stmt.is_end_of_fcn_or_script ());
 }
 
 void