changeset 3877:55648fc616c8

[project @ 2002-03-07 23:00:09 by jwe]
author jwe
date Thu, 07 Mar 2002 23:00:10 +0000
parents a134e5cfdc01
children faeca8a063ae
files src/ChangeLog src/input.cc src/input.h src/parse.y src/pt-loop.cc src/pt-loop.h
diffstat 6 files changed, 231 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,26 @@
+2002-03-07  John W. Eaton  <jwe@bevo.che.wisc.edu>
+
+	* pt-loop.cc (evaluating_looping_command): New global.
+	(tree_while_command::eval): Protect evaluating_looping_command.
+	Set it to true while evaluating loop.
+	(tree_do_until_command::eval): Ditto.
+	(tree_simple_for_command::eval): Ditto.
+	(tree_complex_for_command::eval): Ditto.
+	* pt-loop.h (evaluating_looping_command): Provide decl.
+	* parse.y (parse_fcn_file): Protect get_input_from_eval_string.
+	Set get_input_from_eval_string to false before calling yyparse.
+	(make_break_command): Also check evaluating_looping_command.
+	(make_continue_command): Also check evaluating_looping_command.
+	(eval_string (const std::string&, bool, int&, int)): Loop over
+	yyparse to handle multi-line strings.
+	Move call to unwind_protect::run_frame to end of function.
+	Don't reset parser before calling yyparse.
+	Correctly handle return, break, and continue.
+
+	* input.cc (input_from_eval_string_pending): New global variable.
+	(get_usr_input): Use it.
+	* input.h (input_from_eval_string_pending): Provide decl.
+
 2002-03-06  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
 	* ov-usr-fcn.cc (octave_user_function::do_multi_index_op):
--- a/src/input.cc
+++ b/src/input.cc
@@ -98,6 +98,10 @@
 // TRUE means get input from current_eval_string.
 bool get_input_from_eval_string = false;
 
+// TRUE means we haven't been asked for the input from
+// current_eval_string yet.
+bool input_from_eval_string_pending = false;
+
 // TRUE means we're parsing a function file.
 bool reading_fcn_file = false;
 
@@ -249,12 +253,17 @@
 
   if (get_input_from_eval_string)
     {
-      retval = current_eval_string;
+      if (input_from_eval_string_pending)
+	{
+	  input_from_eval_string_pending = false;
+
+	  retval = current_eval_string;
 
-      size_t len = retval.length ();
+	  size_t len = retval.length ();
 
-      if (retval[len-1] != '\n')
-	retval.append ("\n");
+	  if (retval[len-1] != '\n')
+	    retval.append ("\n");
+	}
     }
   else
     retval = octave_gets ();
--- a/src/input.h
+++ b/src/input.h
@@ -45,6 +45,10 @@
 // TRUE means get input from current_eval_string.
 extern bool get_input_from_eval_string;
 
+// TRUE means we haven't been asked for the input from
+// current_eval_string yet.
+extern bool input_from_eval_string_pending;
+
 // TRUE means we're parsing a function file.
 extern bool reading_fcn_file;
 
--- a/src/parse.y
+++ b/src/parse.y
@@ -2204,7 +2204,8 @@
   int c = break_tok->column ();
 
   if (lexer_flags.looping || lexer_flags.defining_func
-      || reading_script_file || evaluating_function_body)
+      || reading_script_file || evaluating_function_body
+      || evaluating_looping_command)
     retval = new tree_break_command (l, c);
   else
     retval = new tree_no_op_command ("break", l, c);
@@ -2222,7 +2223,7 @@
   int l = continue_tok->line ();
   int c = continue_tok->column ();
 
-  if (lexer_flags.looping)
+  if (lexer_flags.looping || evaluating_looping_command)
     retval = new tree_continue_command (l, c);
   else
     retval = new tree_no_op_command ("continue", l, c);
@@ -3135,11 +3136,13 @@
 	  unwind_protect_bool (Vsaving_history);
 	  unwind_protect_bool (reading_fcn_file);
 	  unwind_protect_bool (input_from_command_line_file);
+	  unwind_protect_bool (get_input_from_eval_string);
 
 	  Vecho_executing_commands = ECHO_OFF;
 	  Vsaving_history = false;
 	  reading_fcn_file = true;
 	  input_from_command_line_file = false;
+	  get_input_from_eval_string = false;
 
 	  YY_BUFFER_STATE old_buf = current_buffer ();
 	  YY_BUFFER_STATE new_buf = create_buffer (ffile);
@@ -3390,17 +3393,22 @@
 octave_value_list
 eval_string (const std::string& s, bool silent, int& parse_status, int nargout)
 {
+  octave_value_list retval;
+
   unwind_protect::begin_frame ("eval_string");
 
   unwind_protect_bool (get_input_from_eval_string);
+  unwind_protect_bool (input_from_eval_string_pending);
   unwind_protect_bool (input_from_command_line_file);
-  unwind_protect_ptr (global_command);
   unwind_protect_str (current_eval_string);
 
   get_input_from_eval_string = true;
+  input_from_eval_string_pending = true;
   input_from_command_line_file = false;
   current_eval_string = s;
 
+  unwind_protect_ptr (global_command);
+
   YY_BUFFER_STATE old_buf = current_buffer ();
   YY_BUFFER_STATE new_buf = create_buffer (0);
 
@@ -3411,26 +3419,33 @@
 
   unwind_protect_ptr (curr_sym_tab);
 
-  reset_parser ();
-
-  parse_status = yyparse ();
-
-  // Important to reset the idea of where input is coming from before
-  // trying to eval the command we just parsed -- it might contain the
-  // name of an function file that still needs to be parsed!
-
-  tree_statement_list *command = global_command;
+  do
+    {
+      parse_status = yyparse ();
+
+      tree_statement_list *command = global_command;
+
+      if (parse_status == 0 && command)
+        {
+	  retval = command->eval (silent, nargout);
+
+	  delete command;
+
+	  command = 0;
+
+	  if (error_state
+	      || tree_return_command::returning
+	      || tree_break_command::breaking
+	      || tree_continue_command::continuing)
+	    break;
+	}
+      else
+	break;
+    }
+  while (parse_status == 0);
 
   unwind_protect::run_frame ("eval_string");
 
-  octave_value_list retval;
-
-  if (parse_status == 0 && command)
-    {
-      retval = command->eval (silent, nargout);
-      delete command;
-    }
-
   return retval;
 }
 
--- a/src/pt-loop.cc
+++ b/src/pt-loop.cc
@@ -41,6 +41,10 @@
 #include "pt-loop.h"
 #include "pt-stmt.h"
 #include "pt-walk.h"
+#include "unwind-prot.h"
+
+// TRUE means we are evaluating some kind of looping construct.
+bool evaluating_looping_command = false;
 
 // Decide if it's time to quit a for or while loop.
 static inline bool
@@ -78,6 +82,12 @@
   if (error_state)
     return;
 
+  unwind_protect::begin_frame ("while_command::eval");
+
+  unwind_protect_bool (evaluating_looping_command);
+
+  evaluating_looping_command = true;
+
   if (! expr)
     panic_impossible ();
 
@@ -92,7 +102,7 @@
 	      if (error_state)
 		{
 		  eval_error ();
-		  return;
+		  goto cleanup;
 		}
 	    }
 
@@ -102,6 +112,9 @@
       else
 	break;
     }
+
+ cleanup:
+  unwind_protect::run_frame ("while_command::eval");
 }
 
 void
@@ -126,6 +139,12 @@
   if (error_state)
     return;
 
+  unwind_protect::begin_frame ("do_until_command::eval");
+
+  unwind_protect_bool (evaluating_looping_command);
+
+  evaluating_looping_command = true;
+
   if (! expr)
     panic_impossible ();
 
@@ -140,13 +159,16 @@
 	  if (error_state)
 	    {
 	      eval_error ();
-	      return;
+	      goto cleanup;
 	    }
 	}
 
       if (quit_loop_now () || expr->is_logically_true ("do-until"))
 	break;
     }
+
+ cleanup:
+  unwind_protect::run_frame ("do_until_command::eval");
 }
 
 void
@@ -223,144 +245,155 @@
   if (error_state)
     return;
 
+  unwind_protect::begin_frame ("simple_for_command::eval");
+
+  unwind_protect_bool (evaluating_looping_command);
+
+  evaluating_looping_command = true;
+
   octave_value rhs = expr->rvalue ();
 
   if (error_state || rhs.is_undefined ())
     {
       eval_error ();
-      return;
-    }
-
-  octave_lvalue ult = lhs->lvalue ();
-
-  if (error_state)
-    {
-      eval_error ();
-      return;
+      goto cleanup;
     }
 
-  if (rhs.is_range ())
-    {
-      Range rng = rhs.range_value ();
+  {
+    octave_lvalue ult = lhs->lvalue ();
 
-      int steps = rng.nelem ();
-      double b = rng.base ();
-      double increment = rng.inc ();
+    if (error_state)
+      {
+	eval_error ();
+	goto cleanup;
+      }
+
+    if (rhs.is_range ())
+      {
+	Range rng = rhs.range_value ();
 
-      for (int i = 0; i < steps; i++)
-	{
-	  MAYBE_DO_BREAKPOINT;
+	int steps = rng.nelem ();
+	double b = rng.base ();
+	double increment = rng.inc ();
 
-	  double tmp_val = b + i * increment;
+	for (int i = 0; i < steps; i++)
+	  {
+	    MAYBE_DO_BREAKPOINT;
 
-	  octave_value val (tmp_val);
+	    double tmp_val = b + i * increment;
+
+	    octave_value val (tmp_val);
 
-	  bool quit = false;
+	    bool quit = false;
 
-	  do_for_loop_once (ult, val, quit);
+	    do_for_loop_once (ult, val, quit);
 
-	  if (quit)
-	    break;
-	}
-    }
-  else if (rhs.is_scalar_type ())
-    {
-      bool quit = false;
-      
-      MAYBE_DO_BREAKPOINT;
+	    if (quit)
+	      break;
+	  }
+      }
+    else if (rhs.is_scalar_type ())
+      {
+	bool quit = false;
+
+	MAYBE_DO_BREAKPOINT;
 
-      do_for_loop_once (ult, rhs, quit);
-    }
-  else if (rhs.is_string ())
-    {
-      charMatrix chm_tmp = rhs.char_matrix_value ();
-      int nr = chm_tmp.rows ();
-      int steps = chm_tmp.columns ();
+	do_for_loop_once (ult, rhs, quit);
+      }
+    else if (rhs.is_string ())
+      {
+	charMatrix chm_tmp = rhs.char_matrix_value ();
+	int nr = chm_tmp.rows ();
+	int steps = chm_tmp.columns ();
 
-      if (error_state)
-	return;
+	if (error_state)
+	  goto cleanup;
 
-      if (nr == 1)
-	DO_LOOP (chm_tmp (0, i));
-      else
-	{
-	  for (int i = 0; i < steps; i++)
-	    {
-	      MAYBE_DO_BREAKPOINT;
+	if (nr == 1)
+	  DO_LOOP (chm_tmp (0, i));
+	else
+	  {
+	    for (int i = 0; i < steps; i++)
+	      {
+		MAYBE_DO_BREAKPOINT;
 
-	      octave_value val (chm_tmp.extract (0, i, nr-1, i), true);
+		octave_value val (chm_tmp.extract (0, i, nr-1, i), true);
 
-	      bool quit = false;
+		bool quit = false;
 
-	      do_for_loop_once (ult, val, quit);
+		do_for_loop_once (ult, val, quit);
 
-	      if (quit)
-		break;
-	    }
-	}
-    }
-  else if (rhs.is_matrix_type ())
-    {
-      Matrix m_tmp;
-      ComplexMatrix cm_tmp;
+		if (quit)
+		  break;
+	      }
+	  }
+      }
+    else if (rhs.is_matrix_type ())
+      {
+	Matrix m_tmp;
+	ComplexMatrix cm_tmp;
 
-      int nr;
-      int steps;
+	int nr;
+	int steps;
 
-      if (rhs.is_real_matrix ())
-	{
-	  m_tmp = rhs.matrix_value ();
-	  nr = m_tmp.rows ();
-	  steps = m_tmp.columns ();
-	}
-      else
-	{
-	  cm_tmp = rhs.complex_matrix_value ();
-	  nr = cm_tmp.rows ();
-	  steps = cm_tmp.columns ();
-	}
+	if (rhs.is_real_matrix ())
+	  {
+	    m_tmp = rhs.matrix_value ();
+	    nr = m_tmp.rows ();
+	    steps = m_tmp.columns ();
+	  }
+	else
+	  {
+	    cm_tmp = rhs.complex_matrix_value ();
+	    nr = cm_tmp.rows ();
+	    steps = cm_tmp.columns ();
+	  }
 
-      if (error_state)
-	return;
+	if (error_state)
+	  goto cleanup;
 
-      if (rhs.is_real_matrix ())
-	{
-	  if (nr == 1)
-	    DO_LOOP (m_tmp (0, i));
-	  else
-	    DO_LOOP (m_tmp.extract (0, i, nr-1, i));
-	}
-      else
-	{
-	  if (nr == 1)
-	    DO_LOOP (cm_tmp (0, i));
-	  else
-	    DO_LOOP (cm_tmp.extract (0, i, nr-1, i));
-	}
-    }
-  else if (rhs.is_map ())
-    {
-      Octave_map tmp_val (rhs.map_value ());
+	if (rhs.is_real_matrix ())
+	  {
+	    if (nr == 1)
+	      DO_LOOP (m_tmp (0, i));
+	    else
+	      DO_LOOP (m_tmp.extract (0, i, nr-1, i));
+	  }
+	else
+	  {
+	    if (nr == 1)
+	      DO_LOOP (cm_tmp (0, i));
+	    else
+	      DO_LOOP (cm_tmp.extract (0, i, nr-1, i));
+	  }
+      }
+    else if (rhs.is_map ())
+      {
+	Octave_map tmp_val (rhs.map_value ());
 
-      for (Pix p = tmp_val.first (); p != 0; tmp_val.next (p))
-	{
-	  MAYBE_DO_BREAKPOINT;
+	for (Pix p = tmp_val.first (); p != 0; tmp_val.next (p))
+	  {
+	    MAYBE_DO_BREAKPOINT;
 
-	  octave_value val = tmp_val.contents (p);
+	    octave_value val = tmp_val.contents (p);
 
-	  bool quit = false;
+	    bool quit = false;
 
-	  do_for_loop_once (ult, val, quit);
+	    do_for_loop_once (ult, val, quit);
 
-	  if (quit)
-	    break;
-	}
-    }
-  else
-    {
-      ::error ("invalid type in for loop expression near line %d, column %d",
-	       line (), column ());
-    }
+	    if (quit)
+	      break;
+	  }
+      }
+    else
+      {
+	::error ("invalid type in for loop expression near line %d, column %d",
+		 line (), column ());
+      }
+  }
+
+ cleanup:
+  unwind_protect::run_frame ("simple_for_command::eval");
 }
 
 void
@@ -419,12 +452,18 @@
   if (error_state)
     return;
 
+  unwind_protect::begin_frame ("complex_for_command::eval");
+
+  unwind_protect_bool (evaluating_looping_command);
+
+  evaluating_looping_command = true;
+
   octave_value rhs = expr->rvalue ();
 
   if (error_state || rhs.is_undefined ())
     {
       eval_error ();
-      return;
+      goto cleanup;
     }
 
   if (rhs.is_map ())
@@ -460,6 +499,9 @@
     }
   else
     error ("in statement `for [X, Y] = VAL', VAL must be a structure");
+
+ cleanup:
+  unwind_protect::run_frame ("complex_for_command::eval");
 }
 
 void
--- a/src/pt-loop.h
+++ b/src/pt-loop.h
@@ -39,6 +39,9 @@
 #include "comment-list.h"
 #include "pt-cmd.h"
 
+// TRUE means we are evaluating some kind of looping construct.
+extern bool evaluating_looping_command;
+
 // While.
 
 class