changeset 15427:6823ad7a25b1

implement local option for warnings * error.cc (warning_query): New function. (Fwarning): Handle "local" option when setting warning states. Use warning_query to handle query option. * ov-usr-fcn.cc (octave_usr_function::restore_warning_states): New private function. (octave_usr_function::bind_automatic_vars): Create hidden auto variable .saved_warning_states. (octave_usr_function::do_multi_index_op): Insert pointer to restore_warning_states function in unwind_protect frame. * ov-usr-fcn.h (octave_usr_function::restore_warning_states): Provide decl. * NEWS: Note user visible change.
author John W. Eaton <jwe@octave.org>
date Thu, 20 Sep 2012 12:20:39 -0400
parents a42d69d5a36d
children 4db96357fec9 87c3704b5c7a
files NEWS libinterp/interpfcn/error.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov-usr-fcn.h
diffstat 4 files changed, 186 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Sep 20 10:14:03 2012 -0400
+++ b/NEWS	Thu Sep 20 12:20:39 2012 -0400
@@ -3,6 +3,17 @@
 
  ** A new GUI is now available with Octave.
 
+ ** Warning states may now be set temporarily, until the end of the
+    current function, using the syntax
+
+      warning STATE ID "local"
+
+    in which STATE may be "on", "off", or "error".  Changes to warning
+    states that are set locally affect the current function and all
+    functions called from the current scope.  The previous warning state
+    is restored on return from the current function.  The "local"
+    option is ignored if used in the top-level workspace.
+
 Summary of important user-visible changes for version 3.8:
 ---------------------------------------------------------
 
--- a/libinterp/interpfcn/error.cc	Thu Sep 20 10:14:03 2012 -0400
+++ b/libinterp/interpfcn/error.cc	Thu Sep 20 12:20:39 2012 -0400
@@ -1141,6 +1141,59 @@
   return retval;
 }
 
+static octave_scalar_map
+warning_query (const std::string& id_arg)
+{
+  octave_scalar_map retval;
+
+  std::string id = id_arg;
+
+  if (id == "last")
+    id = Vlast_warning_id;
+
+  Cell ident = warning_options.contents ("identifier");
+  Cell state = warning_options.contents ("state");
+
+  octave_idx_type nel = ident.numel ();
+
+  bool found = false;
+
+  std::string val;
+
+  for (octave_idx_type i = 0; i < nel; i++)
+    {
+      if (ident(i).string_value () == id)
+        {
+          val = state(i).string_value ();
+          found = true;
+          break;
+        }
+    }
+
+  if (! found)
+    {
+      for (octave_idx_type i = 0; i < nel; i++)
+        {
+          if (ident(i).string_value () == "all")
+            {
+              val = state(i).string_value ();
+              found = true;
+              break;
+            }
+        }
+    }
+
+  if (found)
+    {
+      retval.assign ("identifier", id);
+      retval.assign ("state", val);
+    }
+  else
+    error ("warning: unable to find default warning state!");
+
+  return retval;
+}
+
 DEFUN (warning, args, nargout,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} warning (@var{template}, @dots{})\n\
@@ -1149,6 +1202,7 @@
 @deftypefnx {Built-in Function} {} warning (\"off\", @var{id})\n\
 @deftypefnx {Built-in Function} {} warning (\"query\", @var{id})\n\
 @deftypefnx {Built-in Function} {} warning (\"error\", @var{id})\n\
+@deftypefnx {Built-in Function} {} warning (@var{state}, @var{id}, \"local\")\n\
 Format the optional arguments under the control of the template string\n\
 @var{template} using the same rules as the @code{printf} family of\n\
 functions (@pxref{Formatted Output}) and print the resulting message\n\
@@ -1176,6 +1230,15 @@
 @end group\n\
 @end example\n\
 \n\
+If the state is @samp{\"on\"}, @samp{\"off\"}, or @samp{\"error\"}\n\
+and the third argument is @samp{\"local\"}, then the warning state\n\
+will be set temporarily, until the end of the current function.\n\
+Changes to warning states that are set locally affect the current\n\
+function and all functions called from the current scope.  The\n\
+previous warning state is restored on return from the current\n\
+function.  The \"local\" option is ignored if used in the top-level\n\
+workspace.\n\
+\n\
 Implementation Note: For compatibility with @sc{matlab}, escape\n\
 sequences (e.g., \"\\n\" => newline) are processed in @var{template}\n\
 regardless of whether @var{template} has been defined within single quotes\n\
@@ -1201,13 +1264,93 @@
           std::string arg1 = argv(1);
           std::string arg2 = "all";
 
-          if (argc == 3)
+          if (argc >= 3)
             arg2 = argv(2);
 
           if (arg1 == "on" || arg1 == "off" || arg1 == "error")
             {
               octave_map old_warning_options = warning_options;
 
+              if (argc == 4 && argv(3) == "local"
+                  && ! symbol_table::at_top_level ())
+                {
+                  symbol_table::scope_id scope
+                    = octave_call_stack::current_scope ();
+
+                  symbol_table::context_id context
+                    = octave_call_stack::current_context ();
+
+                  octave_scalar_map val = warning_query (arg2);
+
+                  octave_value curr_state = val.contents ("state");
+
+                  // FIXME -- this might be better with a dictionary
+                  // object.
+
+                  octave_value curr_warning_states
+                    = symbol_table::varval (".saved_warning_states.",
+                                            scope, context);
+
+                  octave_map m;
+
+                  if (curr_warning_states.is_defined ())
+                    m = curr_warning_states.map_value ();
+                  else
+                    {
+                      string_vector fields (2);
+
+                      fields(0) = "identifier";
+                      fields(1) = "state";
+
+                      m = octave_map (dim_vector (0, 1), fields);
+                    }
+
+                  if (error_state)
+                    panic_impossible ();
+
+                  Cell ids = m.contents ("identifier");
+                  Cell states = m.contents ("state");
+
+                  octave_idx_type nel = states.numel ();
+                  bool found = false;
+                  octave_idx_type i;
+                  for (i = 0; i < nel; i++)
+                    {
+                      std::string id = ids(i).string_value ();
+
+                      if (error_state)
+                        panic_impossible ();
+
+                      if (id == arg2)
+                        {
+                          states(i) = curr_state;
+                          found = true;
+                          break;
+                        }
+                    }
+
+                  if (! found)
+                    {
+                      m.resize (dim_vector (nel+1, 1));
+
+                      ids.resize (dim_vector (nel+1, 1));
+                      states.resize (dim_vector (nel+1, 1));
+
+                      ids(nel) = arg2;
+                      states(nel) = curr_state;
+                    }
+
+                  m.contents ("identifier") = ids;
+                  m.contents ("state") = states;
+
+                  symbol_table::varref
+                    (".saved_warning_states.", scope, context) = m;
+
+                  // Now ignore the "local" argument and continue to
+                  // handle the current setting.
+                  argc--;
+                }
+                  
               if (arg2 == "all")
                 {
                   octave_map tmp;
@@ -1369,54 +1512,7 @@
                   retval = tmp;
                 }
               else
-                {
-                  if (arg2 == "last")
-                    arg2 = Vlast_warning_id;
-
-                  Cell ident = warning_options.contents ("identifier");
-                  Cell state = warning_options.contents ("state");
-
-                  octave_idx_type nel = ident.numel ();
-
-                  bool found = false;
-
-                  std::string val;
-
-                  for (octave_idx_type i = 0; i < nel; i++)
-                    {
-                      if (ident(i).string_value () == arg2)
-                        {
-                          val = state(i).string_value ();
-                          found = true;
-                          break;
-                        }
-                    }
-
-                  if (! found)
-                    {
-                      for (octave_idx_type i = 0; i < nel; i++)
-                        {
-                          if (ident(i).string_value () == "all")
-                            {
-                              val = state(i).string_value ();
-                              found = true;
-                              break;
-                            }
-                        }
-                    }
-
-                  if (found)
-                    {
-                      octave_scalar_map tmp;
-
-                      tmp.assign ("identifier", arg2);
-                      tmp.assign ("state", val);
-
-                      retval = tmp;
-                    }
-                  else
-                    error ("warning: unable to find default warning state!");
-                }
+                retval = warning_query (arg2);
 
               done = true;
             }
--- a/libinterp/octave-value/ov-usr-fcn.cc	Thu Sep 20 10:14:03 2012 -0400
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Thu Sep 20 12:20:39 2012 -0400
@@ -30,6 +30,7 @@
 
 #include <defaults.h>
 #include "Cell.h"
+#include "builtins.h"
 #include "defun.h"
 #include "error.h"
 #include "gripes.h"
@@ -455,6 +456,8 @@
   bind_automatic_vars (arg_names, nargin, nargout, all_va_args (args),
                        lvalue_list);
 
+  frame.add_method (this, &octave_user_function::restore_warning_states);
+
   bool echo_commands = (Vecho_executing_commands & ECHO_FUNCTIONS);
 
   if (echo_commands)
@@ -614,6 +617,11 @@
   symbol_table::mark_automatic (".nargin.");
   symbol_table::mark_automatic (".nargout.");
 
+  symbol_table::varref (".saved_warning_states.") = octave_value ();
+
+  symbol_table::mark_automatic (".saved_warning_states.");
+  symbol_table::mark_automatic (".saved_warning_states.");
+
   if (takes_varargs ())
     symbol_table::varref ("varargin") = va_args.cell_value ();
 
@@ -648,6 +656,26 @@
   symbol_table::mark_automatic (".ignored.");
 }
 
+void
+octave_user_function::restore_warning_states (void)
+{
+  octave_value val = symbol_table::varval (".saved_warning_states.");
+
+  if (val.is_defined ())
+    {
+      octave_map m = val.map_value ();
+
+      if (error_state)
+        panic_impossible ();
+
+      Cell ids = m.contents ("identifier");
+      Cell states = m.contents ("state");
+
+      for (octave_idx_type i = 0; i < m.numel (); i++)
+        Fwarning (ovl (states(i), ids(i)));
+    }
+}
+
 DEFUN (nargin, args, ,
   "-*- texinfo -*-\n\
 @deftypefn  {Built-in Function} {} nargin ()\n\
--- a/libinterp/octave-value/ov-usr-fcn.h	Thu Sep 20 10:14:03 2012 -0400
+++ b/libinterp/octave-value/ov-usr-fcn.h	Thu Sep 20 12:20:39 2012 -0400
@@ -476,6 +476,8 @@
                             int nargout, const octave_value_list& va_args,
                             const std::list<octave_lvalue> *lvalue_list);
 
+  void restore_warning_states (void);
+
   // No copying!
 
   octave_user_function (const octave_user_function& fn);