changeset 29339:93530bb4bd6f

improve behavior of echo (bug #56068) When "echo on" appears in a script, attempt to correctly begin echoing at the line where the echo command appears. * pt-eval.h, pt-eval.cc (tree_evaluator::m_echo_file_pos): Now an int instead of size_t. Use int instead of size_t to store line number info. Convert invalid line numbers to 1. (tree_evaluator::maybe_set_echo_state): Store user code line.
author John W. Eaton <jwe@octave.org>
date Thu, 28 Jan 2021 00:23:00 -0500
parents e3fb1bd77d47
children 0e97c97044ee
files libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h
diffstat 2 files changed, 70 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-eval.cc	Wed Jan 27 09:44:59 2021 -0500
+++ b/libinterp/parse-tree/pt-eval.cc	Thu Jan 28 00:23:00 2021 -0500
@@ -1152,7 +1152,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -1177,7 +1179,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -2784,7 +2788,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -2835,7 +2841,7 @@
 
   template <typename T>
   void
-  tree_evaluator::execute_range_loop (const range<T>& rng, size_t line,
+  tree_evaluator::execute_range_loop (const range<T>& rng, int line,
                                       octave_lvalue& ult,
                                       tree_statement_list *loop_body)
   {
@@ -2866,7 +2872,9 @@
   void
   tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd)
   {
-    size_t line = cmd.line ();
+    int line = cmd.line ();
+    if (line < 0)
+      line = 1;
 
     if (m_echo_state)
       {
@@ -3051,7 +3059,9 @@
   void
   tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd)
   {
-    size_t line = cmd.line ();
+    int line = cmd.line ();
+    if (line < 0)
+      line = 1;
 
     if (m_echo_state)
       {
@@ -3400,7 +3410,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -3469,7 +3481,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -3513,7 +3527,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -3562,7 +3578,9 @@
               {
                 if (m_echo_state)
                   {
-                    size_t line = stmt.line ();
+                    int line = stmt.line ();
+                    if (line < 0)
+                      line = 1;
                     echo_code (line);
                     m_echo_file_pos = line + 1;
                   }
@@ -3712,7 +3730,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -3752,7 +3772,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -3905,7 +3927,9 @@
   {
     if (m_echo_state)
       {
-        size_t line = cmd.line ();
+        int line = cmd.line ();
+        if (line < 0)
+          line = 1;
         echo_code (line);
         m_echo_file_pos = line + 1;
       }
@@ -3956,7 +3980,9 @@
   void
   tree_evaluator::visit_while_command (tree_while_command& cmd)
   {
-    size_t line = cmd.line ();
+    int line = cmd.line ();
+    if (line < 0)
+      line = 1;
 
     if (m_echo_state)
       {
@@ -4002,7 +4028,9 @@
   void
   tree_evaluator::visit_do_until_command (tree_do_until_command& cmd)
   {
-    size_t line = cmd.line ();
+    int line = cmd.line ();
+    if (line < 0)
+      line = 1;
 
     if (m_echo_state)
       {
@@ -4433,7 +4461,7 @@
 
   void
   tree_evaluator::push_echo_state (int type, const std::string& file_name,
-                                   size_t pos)
+                                   int pos)
   {
     unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame ();
 
@@ -4447,7 +4475,7 @@
 
   void
   tree_evaluator::set_echo_state (int type, const std::string& file_name,
-                                  size_t pos)
+                                  int pos)
   {
     m_echo_state = echo_this_file (file_name, type);
     m_echo_file_name = file_name;
@@ -4456,7 +4484,7 @@
 
   void
   tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name,
-                                      size_t pos)
+                                      int pos)
   {
     m_echo_state = state;
     m_echo_file_name = file_name;
@@ -4476,7 +4504,14 @@
 
         std::string file_name = fcn->fcn_file_name ();
 
-        size_t pos = m_call_stack.current_line ();
+        // We want the line where "echo" was called, not the line number
+        // stored in the stack frame that was created for the echo
+        // function (that will always be -1).
+
+        int pos = m_call_stack.current_user_code_line ();
+
+        if (pos < 0)
+          pos = 1;
 
         set_echo_state (type, file_name, pos);
       }
@@ -4819,7 +4854,7 @@
     return false;
   }
 
-  void tree_evaluator::echo_code (size_t line)
+  void tree_evaluator::echo_code (int line)
   {
     std::string prefix = command_editor::decode_prompt_string (m_PS4);
 
@@ -4829,7 +4864,7 @@
       {
         octave_user_code *code = dynamic_cast<octave_user_code *> (curr_fcn);
 
-        size_t num_lines = line - m_echo_file_pos + 1;
+        int num_lines = line - m_echo_file_pos + 1;
 
         std::deque<std::string> lines
           = code->get_code_lines (m_echo_file_pos, num_lines);
--- a/libinterp/parse-tree/pt-eval.h	Wed Jan 27 09:44:59 2021 -0500
+++ b/libinterp/parse-tree/pt-eval.h	Thu Jan 28 00:23:00 2021 -0500
@@ -792,17 +792,16 @@
 
     std::list<octave_lvalue> make_lvalue_list (tree_argument_list *);
 
-    void push_echo_state (int type, const std::string& file_name,
-                          size_t pos = 1);
+    void push_echo_state (int type, const std::string& file_name, int pos = 1);
 
   private:
 
     template <typename T>
-    void execute_range_loop (const range<T>& rng, size_t line,
+    void execute_range_loop (const range<T>& rng, int line,
                              octave_lvalue& ult,
                              tree_statement_list *loop_body);
 
-    void set_echo_state (int type, const std::string& file_name, size_t pos);
+    void set_echo_state (int type, const std::string& file_name, int pos);
 
     void maybe_set_echo_state (void);
 
@@ -818,12 +817,11 @@
     bool is_logically_true (tree_expression *expr, const char *warn_for);
 
     // For unwind-protect.
-    void uwp_set_echo_state (bool state, const std::string& file_name,
-                             size_t pos);
+    void uwp_set_echo_state (bool state, const std::string& file_name, int pos);
 
     bool echo_this_file (const std::string& file, int type) const;
 
-    void echo_code (size_t line);
+    void echo_code (int line);
 
     bool quit_loop_now (void);
 
@@ -909,8 +907,15 @@
 
     std::string m_echo_file_name;
 
-    // Next line to echo, counting from 1.
-    size_t m_echo_file_pos;
+    // Next line to echo, counting from 1.  We use int here because the
+    // parser does.  It also initializes line and column numbers to the
+    // invalid value -1 and that can cause trouble if cast to an
+    // unsigned value.  When updating this value and echoing ranges of
+    // code, we also check to ensure that the line numbers stored in the
+    // parse tree are valid.  It would be better to ensure that the
+    // parser always stores valid position info, but that's more
+    // difficult to always do correctly.
+    int m_echo_file_pos;
 
     std::map<std::string, bool> m_echo_files;