# HG changeset patch # User John W. Eaton # Date 1348158039 14400 # Node ID 6823ad7a25b10768eadad3c63c9aaf325506cd36 # Parent a42d69d5a36dc86a46d139c76351414825b30baa 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. diff -r a42d69d5a36d -r 6823ad7a25b1 NEWS --- 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: --------------------------------------------------------- diff -r a42d69d5a36d -r 6823ad7a25b1 libinterp/interpfcn/error.cc --- 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; } diff -r a42d69d5a36d -r 6823ad7a25b1 libinterp/octave-value/ov-usr-fcn.cc --- 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 #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\ diff -r a42d69d5a36d -r 6823ad7a25b1 libinterp/octave-value/ov-usr-fcn.h --- 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 *lvalue_list); + void restore_warning_states (void); + // No copying! octave_user_function (const octave_user_function& fn);