error.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1993-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <cstdarg>
00028 #include <cstring>
00029 
00030 #include <iostream>
00031 #include <sstream>
00032 #include <string>
00033 
00034 #include "defun.h"
00035 #include "error.h"
00036 #include "input.h"
00037 #include "pager.h"
00038 #include "oct-obj.h"
00039 #include "oct-map.h"
00040 #include "utils.h"
00041 #include "ov.h"
00042 #include "ov-usr-fcn.h"
00043 #include "pt-pr-code.h"
00044 #include "pt-stmt.h"
00045 #include "toplev.h"
00046 #include "unwind-prot.h"
00047 #include "variables.h"
00048 
00049 // TRUE means that Octave will try to beep obnoxiously before printing
00050 // error messages.
00051 static bool Vbeep_on_error = false;
00052 
00053 // TRUE means that Octave will try to enter the debugger when an error
00054 // is encountered.  This will also inhibit printing of the normal
00055 // traceback message (you will only see the top-level error message).
00056 bool Vdebug_on_error = false;
00057 
00058 // TRUE means that Octave will try to enter the debugger when a warning
00059 // is encountered.
00060 bool Vdebug_on_warning = false;
00061 
00062 // TRUE means that Octave will try to display a stack trace when a
00063 // warning is encountered.
00064 static bool Vbacktrace_on_warning = false;
00065 
00066 // TRUE means that Octave will print a verbose warning.  Currently unused.
00067 static bool Vverbose_warning;
00068 
00069 // TRUE means that Octave will print no warnings, but lastwarn will be
00070 //updated
00071 static bool Vquiet_warning = false;
00072 
00073 // A structure containing (most of) the current state of warnings.
00074 static octave_map warning_options;
00075 
00076 // The text of the last error message.
00077 static std::string Vlast_error_message;
00078 
00079 // The text of the last warning message.
00080 static std::string Vlast_warning_message;
00081 
00082 // The last warning message id.
00083 static std::string Vlast_warning_id;
00084 
00085 // The last error message id.
00086 static std::string Vlast_error_id;
00087 
00088 // The last file in which an error occured
00089 static octave_map Vlast_error_stack;
00090 
00091 // Current error state.
00092 //
00093 // Valid values:
00094 //
00095 //   -2: an error has occurred, but don't print any messages.
00096 //   -1: an error has occurred, we are printing a traceback
00097 //    0: no error
00098 //    1: an error has occurred
00099 //
00100 int error_state = 0;
00101 
00102 // Current warning state.
00103 //
00104 //  Valid values:
00105 //
00106 //    0: no warning
00107 //    1: a warning has occurred
00108 //
00109 int warning_state = 0;
00110 
00111 // Tell the error handler whether to print messages, or just store
00112 // them for later.  Used for handling errors in eval() and
00113 // the 'unwind_protect' statement.
00114 int buffer_error_messages = 0;
00115 
00116 // TRUE means error messages are turned off.
00117 bool discard_error_messages = false;
00118 
00119 // TRUE means warning messages are turned off.
00120 bool discard_warning_messages = false;
00121 
00122 void
00123 reset_error_handler (void)
00124 {
00125   error_state = 0;
00126   warning_state = 0;
00127   buffer_error_messages = 0;
00128   discard_error_messages = false;
00129 }
00130 
00131 static void
00132 initialize_warning_options (const std::string& state)
00133 {
00134   octave_scalar_map initw;
00135 
00136   initw.setfield ("identifier", "all");
00137   initw.setfield ("state", state);
00138 
00139   warning_options = initw;
00140 }
00141 
00142 static octave_map
00143 initialize_last_error_stack (void)
00144 {
00145   return octave_call_stack::empty_backtrace ();
00146 }
00147 
00148 // Warning messages are never buffered.
00149 
00150 static void
00151 vwarning (const char *name, const char *id, const char *fmt, va_list args)
00152 {
00153   if (discard_warning_messages)
00154     return;
00155 
00156   flush_octave_stdout ();
00157 
00158   std::ostringstream output_buf;
00159 
00160   if (name)
00161     output_buf << name << ": ";
00162 
00163   octave_vformat (output_buf, fmt, args);
00164 
00165   output_buf << std::endl;
00166 
00167   // FIXME -- we really want to capture the message before it
00168   // has all the formatting goop attached to it.  We probably also
00169   // want just the message, not the traceback information.
00170 
00171   std::string msg_string = output_buf.str ();
00172 
00173   if (! warning_state)
00174     {
00175       // This is the first warning in a possible series.
00176 
00177       Vlast_warning_id = id;
00178       Vlast_warning_message = msg_string;
00179     }
00180 
00181   if (! Vquiet_warning)
00182     {
00183       octave_diary << msg_string;
00184 
00185       std::cerr << msg_string;
00186     }
00187 }
00188 
00189 static void
00190 verror (bool save_last_error, std::ostream& os,
00191         const char *name, const char *id, const char *fmt, va_list args,
00192         bool with_cfn = false)
00193 {
00194   if (discard_error_messages)
00195     return;
00196 
00197   if (! buffer_error_messages)
00198     flush_octave_stdout ();
00199 
00200   // FIXME -- we really want to capture the message before it
00201   // has all the formatting goop attached to it.  We probably also
00202   // want just the message, not the traceback information.
00203 
00204   std::ostringstream output_buf;
00205 
00206   octave_vformat (output_buf, fmt, args);
00207 
00208   std::string base_msg = output_buf.str ();
00209 
00210   bool to_beep_or_not_to_beep_p = Vbeep_on_error && ! error_state;
00211 
00212   std::string msg_string;
00213 
00214   if (to_beep_or_not_to_beep_p)
00215     msg_string = "\a";
00216 
00217   if (name)
00218     msg_string += std::string (name) + ": ";
00219 
00220   // If with_fcn is specified, we'll attempt to prefix the message with the name
00221   // of the current executing function. But we'll do so only if:
00222   // 1. the name is not empty (anonymous function)
00223   // 2. it is not already there (including the following colon)
00224   if (with_cfn)
00225     {
00226       octave_function *curfcn = octave_call_stack::current ();
00227       if (curfcn)
00228         {
00229           std::string cfn = curfcn->name ();
00230           if (! cfn.empty ())
00231             {
00232               cfn += ':';
00233               if (cfn.length () > base_msg.length ()
00234                  || base_msg.compare (0, cfn.length (), cfn) != 0)
00235                 {
00236                   msg_string += cfn + ' ';
00237                 }
00238             }
00239         }
00240     }
00241 
00242   msg_string += base_msg + "\n";
00243 
00244   if (! error_state && save_last_error)
00245     {
00246       // This is the first error in a possible series.
00247 
00248       Vlast_error_id = id;
00249       Vlast_error_message = base_msg;
00250 
00251       octave_user_code *fcn = octave_call_stack::caller_user_code ();
00252 
00253       if (fcn)
00254         {
00255           octave_idx_type curr_frame = -1;
00256 
00257           Vlast_error_stack = octave_call_stack::backtrace (0, curr_frame);
00258         }
00259       else
00260         Vlast_error_stack = initialize_last_error_stack ();
00261     }
00262 
00263   if (! buffer_error_messages)
00264     {
00265       octave_diary << msg_string;
00266       os << msg_string;
00267     }
00268 }
00269 
00270 // Note that we don't actually print any message if the error string
00271 // is just "" or "\n".  This allows error ("") and error ("\n") to
00272 // just set the error state.
00273 
00274 static void
00275 error_1 (std::ostream& os, const char *name, const char *id,
00276          const char *fmt, va_list args, bool with_cfn = false)
00277 {
00278   if (error_state != -2)
00279     {
00280       if (fmt)
00281         {
00282           if (*fmt)
00283             {
00284               size_t len = strlen (fmt);
00285 
00286               if (len > 0)
00287                 {
00288                   if (fmt[len - 1] == '\n')
00289                     {
00290                       if (len > 1)
00291                         {
00292                           char *tmp_fmt = strsave (fmt);
00293                           tmp_fmt[len - 1] = '\0';
00294                           verror (true, os, name, id, tmp_fmt, args, with_cfn);
00295                           delete [] tmp_fmt;
00296                         }
00297 
00298                       error_state = -2;
00299                     }
00300                   else
00301                     {
00302                       verror (true, os, name, id, fmt, args, with_cfn);
00303 
00304                       if (! error_state)
00305                         error_state = 1;
00306                     }
00307                 }
00308             }
00309         }
00310       else
00311         panic ("error_1: invalid format");
00312     }
00313 }
00314 
00315 void
00316 vmessage (const char *name, const char *fmt, va_list args)
00317 {
00318   verror (false, std::cerr, name, "", fmt, args);
00319 }
00320 
00321 void
00322 message (const char *name, const char *fmt, ...)
00323 {
00324   va_list args;
00325   va_start (args, fmt);
00326   vmessage (name, fmt, args);
00327   va_end (args);
00328 }
00329 
00330 void
00331 vmessage_with_id (const char *name, const char *id, const char *fmt,
00332                   va_list args)
00333 {
00334   verror (false, std::cerr, name, id, fmt, args);
00335 }
00336 
00337 void
00338 message_with_id (const char *name, const char *id, const char *fmt, ...)
00339 {
00340   va_list args;
00341   va_start (args, fmt);
00342   vmessage_with_id (name, id, fmt, args);
00343   va_end (args);
00344 }
00345 
00346 void
00347 usage_1 (const char *id, const char *fmt, va_list args)
00348 {
00349   verror (true, std::cerr, "usage", id, fmt, args);
00350   error_state = -1;
00351 }
00352 
00353 void
00354 vusage (const char *fmt, va_list args)
00355 {
00356   usage_1 ("", fmt, args);
00357 }
00358 
00359 void
00360 usage (const char *fmt, ...)
00361 {
00362   va_list args;
00363   va_start (args, fmt);
00364   vusage (fmt, args);
00365   va_end (args);
00366 }
00367 
00368 void
00369 vusage_with_id (const char *id, const char *fmt, va_list args)
00370 {
00371   usage_1 (id, fmt, args);
00372 }
00373 
00374 void
00375 usage_with_id (const char *id, const char *fmt, ...)
00376 {
00377   va_list args;
00378   va_start (args, fmt);
00379   vusage_with_id (id, fmt, args);
00380   va_end (args);
00381 }
00382 
00383 static void
00384 pr_where_2 (const char *fmt, va_list args)
00385 {
00386   if (fmt)
00387     {
00388       if (*fmt)
00389         {
00390           size_t len = strlen (fmt);
00391 
00392           if (len > 0)
00393             {
00394               if (fmt[len - 1] == '\n')
00395                 {
00396                   if (len > 1)
00397                     {
00398                       char *tmp_fmt = strsave (fmt);
00399                       tmp_fmt[len - 1] = '\0';
00400                       verror (false, std::cerr, 0, "", tmp_fmt, args);
00401                       delete [] tmp_fmt;
00402                     }
00403                 }
00404               else
00405                 verror (false, std::cerr, 0, "", fmt, args);
00406             }
00407         }
00408     }
00409   else
00410     panic ("pr_where_2: invalid format");
00411 }
00412 
00413 static void
00414 pr_where_1 (const char *fmt, ...)
00415 {
00416   va_list args;
00417   va_start (args, fmt);
00418   pr_where_2 (fmt, args);
00419   va_end (args);
00420 }
00421 
00422 static void
00423 pr_where (const char *who)
00424 {
00425   octave_idx_type curr_frame = -1;
00426 
00427   octave_map stk = octave_call_stack::backtrace (0, curr_frame);
00428 
00429   octave_idx_type nframes_to_display = stk.numel ();
00430 
00431   if (nframes_to_display > 0)
00432     {
00433       pr_where_1 ("%s: called from\n", who);
00434 
00435       Cell names = stk.contents ("name");
00436       Cell lines = stk.contents ("line");
00437       Cell columns = stk.contents ("column");
00438 
00439       for (octave_idx_type i = 0; i < nframes_to_display; i++)
00440         {
00441           octave_value name = names(i);
00442           octave_value line = lines(i);
00443           octave_value column = columns(i);
00444 
00445           std::string nm = name.string_value ();
00446 
00447           pr_where_1 ("    %s at line %d column %d\n", nm.c_str (),
00448                       line.int_value (), column.int_value ());
00449         }
00450     }
00451 }
00452 
00453 static void
00454 error_2 (const char *id, const char *fmt, va_list args, bool with_cfn = false)
00455 {
00456   int init_state = error_state;
00457 
00458   error_1 (std::cerr, "error", id, fmt, args, with_cfn);
00459 
00460   if ((interactive || forced_interactive)
00461       && Vdebug_on_error && init_state == 0
00462       && octave_call_stack::caller_user_code ())
00463     {
00464       unwind_protect frame;
00465       frame.protect_var (Vdebug_on_error);
00466       Vdebug_on_error = false;
00467 
00468       error_state = 0;
00469 
00470       pr_where ("error");
00471 
00472       do_keyboard (octave_value_list ());
00473     }
00474 }
00475 
00476 void
00477 verror (const char *fmt, va_list args)
00478 {
00479   error_2 ("", fmt, args);
00480 }
00481 
00482 void
00483 error (const char *fmt, ...)
00484 {
00485   va_list args;
00486   va_start (args, fmt);
00487   verror (fmt, args);
00488   va_end (args);
00489 }
00490 
00491 void
00492 verror_with_cfn (const char *fmt, va_list args)
00493 {
00494   error_2 ("", fmt, args, true);
00495 }
00496 
00497 void
00498 error_with_cfn (const char *fmt, ...)
00499 {
00500   va_list args;
00501   va_start (args, fmt);
00502   verror_with_cfn (fmt, args);
00503   va_end (args);
00504 }
00505 
00506 void
00507 verror_with_id (const char *id, const char *fmt, va_list args)
00508 {
00509   error_2 (id, fmt, args);
00510 }
00511 
00512 void
00513 error_with_id (const char *id, const char *fmt, ...)
00514 {
00515   va_list args;
00516   va_start (args, fmt);
00517   verror_with_id (id, fmt, args);
00518   va_end (args);
00519 }
00520 
00521 void
00522 verror_with_id_cfn (const char *id, const char *fmt, va_list args)
00523 {
00524   error_2 (id, fmt, args, true);
00525 }
00526 
00527 void
00528 error_with_id_cfn (const char *id, const char *fmt, ...)
00529 {
00530   va_list args;
00531   va_start (args, fmt);
00532   verror_with_id_cfn (id, fmt, args);
00533   va_end (args);
00534 }
00535 
00536 static int
00537 check_state (const std::string& state)
00538 {
00539   // -1: not found
00540   //  0: found, "off"
00541   //  1: found, "on"
00542   //  2: found, "error"
00543 
00544   if (state == "off")
00545     return 0;
00546   else if (state == "on")
00547     return 1;
00548   else if (state == "error")
00549     return 2;
00550   else
00551     return -1;
00552 }
00553 
00554 // For given warning ID, return 0 if warnings are disabled, 1 if
00555 // enabled, and 2 if the given ID should be an error instead of a
00556 // warning.
00557 
00558 int
00559 warning_enabled (const std::string& id)
00560 {
00561   int retval = 0;
00562 
00563   int all_state = -1;
00564   int id_state = -1;
00565 
00566   octave_idx_type nel = warning_options.numel ();
00567 
00568   if (nel > 0)
00569     {
00570       Cell identifier = warning_options.contents ("identifier");
00571       Cell state = warning_options.contents ("state");
00572 
00573       bool all_found = false;
00574       bool id_found = false;
00575 
00576       for (octave_idx_type i = 0; i < nel; i++)
00577         {
00578           octave_value ov = identifier(i);
00579           std::string ovs = ov.string_value ();
00580 
00581           if (! all_found && ovs == "all")
00582             {
00583               all_state = check_state (state(i).string_value ());
00584 
00585               if (all_state >= 0)
00586                 all_found = true;
00587             }
00588 
00589           if (! id_found && ovs == id)
00590             {
00591               id_state = check_state (state(i).string_value ());
00592 
00593               if (id_state >= 0)
00594                 id_found = true;
00595             }
00596 
00597           if (all_found && id_found)
00598             break;
00599         }
00600     }
00601 
00602   // If "all" is not present, assume warnings are enabled.
00603   if (all_state == -1)
00604     all_state = 1;
00605 
00606   if (all_state == 0)
00607     {
00608       if (id_state >= 0)
00609         retval = id_state;
00610     }
00611   else if (all_state == 1)
00612     {
00613       if (id_state == 0 || id_state == 2)
00614         retval = id_state;
00615       else
00616         retval = all_state;
00617     }
00618   else if (all_state == 2)
00619     {
00620       if (id_state == 0)
00621         retval= id_state;
00622       else
00623         retval = all_state;
00624     }
00625 
00626   return retval;
00627 }
00628 
00629 static void
00630 warning_1 (const char *id, const char *fmt, va_list args)
00631 {
00632   int warn_opt = warning_enabled (id);
00633 
00634   if (warn_opt == 2)
00635     {
00636       // Handle this warning as an error.
00637 
00638       error_2 (id, fmt, args);
00639     }
00640   else if (warn_opt == 1)
00641     {
00642       vwarning ("warning", id, fmt, args);
00643 
00644       if (! symbol_table::at_top_level ()
00645           && Vbacktrace_on_warning
00646           && ! warning_state
00647           && ! discard_warning_messages)
00648         pr_where ("warning");
00649 
00650       warning_state = 1;
00651 
00652       if ((interactive || forced_interactive)
00653           && Vdebug_on_warning
00654           && octave_call_stack::caller_user_code ())
00655         {
00656           unwind_protect frame;
00657           frame.protect_var (Vdebug_on_warning);
00658           Vdebug_on_warning = false;
00659 
00660           do_keyboard (octave_value_list ());
00661         }
00662     }
00663 }
00664 
00665 void
00666 vwarning (const char *fmt, va_list args)
00667 {
00668   warning_1 ("", fmt, args);
00669 }
00670 
00671 void
00672 warning (const char *fmt, ...)
00673 {
00674   va_list args;
00675   va_start (args, fmt);
00676   vwarning (fmt, args);
00677   va_end (args);
00678 }
00679 
00680 void
00681 vwarning_with_id (const char *id, const char *fmt, va_list args)
00682 {
00683   warning_1 (id, fmt, args);
00684 }
00685 
00686 void
00687 warning_with_id (const char *id, const char *fmt, ...)
00688 {
00689   va_list args;
00690   va_start (args, fmt);
00691   vwarning_with_id (id, fmt, args);
00692   va_end (args);
00693 }
00694 
00695 void
00696 vparse_error (const char *fmt, va_list args)
00697 {
00698   error_1 (std::cerr, 0, "", fmt, args);
00699 }
00700 
00701 void
00702 parse_error (const char *fmt, ...)
00703 {
00704   va_list args;
00705   va_start (args, fmt);
00706   vparse_error (fmt, args);
00707   va_end (args);
00708 }
00709 
00710 void
00711 vparse_error_with_id (const char *id, const char *fmt, va_list args)
00712 {
00713   error_1 (std::cerr, 0, id, fmt, args);
00714 }
00715 
00716 void
00717 parse_error_with_id (const char *id, const char *fmt, ...)
00718 {
00719   va_list args;
00720   va_start (args, fmt);
00721   vparse_error_with_id (id, fmt, args);
00722   va_end (args);
00723 }
00724 
00725 void
00726 rethrow_error (const char *id, const char *fmt, ...)
00727 {
00728   va_list args;
00729   va_start (args, fmt);
00730   error_1 (std::cerr, 0, id, fmt, args);
00731   va_end (args);
00732 }
00733 
00734 void
00735 panic (const char *fmt, ...)
00736 {
00737   va_list args;
00738   va_start (args, fmt);
00739   buffer_error_messages = 0;
00740   discard_error_messages = false;
00741   verror (false, std::cerr, "panic", "", fmt, args);
00742   va_end (args);
00743   abort ();
00744 }
00745 
00746 static void
00747 defun_usage_message_1 (const char *fmt, ...)
00748 {
00749   va_list args;
00750   va_start (args, fmt);
00751   error_1 (octave_stdout, 0, "", fmt, args);
00752   va_end (args);
00753 }
00754 
00755 void
00756 defun_usage_message (const std::string& msg)
00757 {
00758   defun_usage_message_1 ("%s", msg.c_str ());
00759 }
00760 
00761 typedef void (*error_fun)(const char *, const char *, ...);
00762 
00763 extern octave_value_list Fsprintf (const octave_value_list&, int);
00764 
00765 static std::string
00766 handle_message (error_fun f, const char *id, const char *msg,
00767                 const octave_value_list& args)
00768 {
00769   std::string retval;
00770 
00771   std::string tstr;
00772 
00773   int nargin = args.length ();
00774 
00775   if (nargin > 0)
00776     {
00777       octave_value arg;
00778 
00779       if (nargin > 1)
00780         {
00781           octave_value_list tmp = Fsprintf (args, 1);
00782           arg = tmp(0);
00783         }
00784       else
00785         arg = args(0);
00786 
00787       if (arg.is_defined ())
00788         {
00789           if (arg.is_string ())
00790             {
00791               tstr = arg.string_value ();
00792               msg = tstr.c_str ();
00793 
00794               if (! msg)
00795                 return retval;
00796             }
00797           else if (arg.is_empty ())
00798             return retval;
00799         }
00800     }
00801 
00802 // Ugh.
00803 
00804   size_t len = strlen (msg);
00805 
00806   if (len > 0)
00807     {
00808       if (msg[len - 1] == '\n')
00809         {
00810           if (len > 1)
00811             {
00812               char *tmp_msg = strsave (msg);
00813               tmp_msg[len - 1] = '\0';
00814               f (id, "%s\n", tmp_msg);
00815               retval = tmp_msg;
00816               delete [] tmp_msg;
00817             }
00818         }
00819       else
00820         {
00821           f (id, "%s", msg);
00822           retval = msg;
00823         }
00824     }
00825 
00826   return retval;
00827 }
00828 
00829 DEFUN (rethrow, args, ,
00830   "-*- texinfo -*-\n\
00831 @deftypefn {Built-in Function} {} rethrow (@var{err})\n\
00832 Reissue a previous error as defined by @var{err}.  @var{err} is a structure\n\
00833 that must contain at least the 'message' and 'identifier' fields.  @var{err}\n\
00834 can also contain a field 'stack' that gives information on the assumed\n\
00835 location of the error.  Typically @var{err} is returned from\n\
00836 @code{lasterror}.\n\
00837 @seealso{lasterror, lasterr, error}\n\
00838 @end deftypefn")
00839 {
00840   octave_value retval;
00841   int nargin = args.length();
00842 
00843   if (nargin != 1)
00844     print_usage ();
00845   else
00846     {
00847       const octave_scalar_map err = args(0).scalar_map_value ();
00848 
00849       if (! error_state)
00850         {
00851           if (err.contains ("message") && err.contains ("identifier"))
00852             {
00853               std::string msg = err.contents("message").string_value ();
00854               std::string id = err.contents("identifier").string_value ();
00855               int len = msg.length();
00856 
00857               std::string file;
00858               std::string nm;
00859               int l = -1;
00860               int c = -1;
00861 
00862               octave_map err_stack = initialize_last_error_stack ();
00863 
00864               if (err.contains ("stack"))
00865                 {
00866                   err_stack = err.contents("stack").map_value ();
00867 
00868                   if (err_stack.numel () > 0)
00869                     {
00870                       if (err_stack.contains ("file"))
00871                         file = err_stack.contents("file")(0).string_value ();
00872 
00873                       if (err_stack.contains ("name"))
00874                         nm = err_stack.contents("name")(0).string_value ();
00875 
00876                       if (err_stack.contains ("line"))
00877                         l = err_stack.contents("line")(0).nint_value ();
00878 
00879                       if (err_stack.contains ("column"))
00880                         c = err_stack.contents("column")(0).nint_value ();
00881                     }
00882                 }
00883 
00884               // Ugh.
00885               char *tmp_msg = strsave (msg.c_str ());
00886               if (tmp_msg[len-1] == '\n')
00887                 {
00888                   if (len > 1)
00889                     {
00890                       tmp_msg[len - 1] = '\0';
00891                       rethrow_error (id.c_str (), "%s\n", tmp_msg);
00892                     }
00893                 }
00894               else
00895                 rethrow_error (id.c_str (), "%s", tmp_msg);
00896               delete [] tmp_msg;
00897 
00898               // FIXME -- is this the right thing to do for
00899               // Vlast_error_stack?  Should it be saved and restored
00900               // with unwind_protect?
00901 
00902               Vlast_error_stack = err_stack;
00903 
00904               if (err.contains ("stack"))
00905                 {
00906                   if (file.empty ())
00907                     {
00908                       if (nm.empty ())
00909                         {
00910                           if (l > 0)
00911                             {
00912                               if (c > 0)
00913                                 pr_where_1 ("error: near line %d, column %d",
00914                                             l, c);
00915                               else
00916                                 pr_where_1 ("error: near line %d", l);
00917                             }
00918                         }
00919                       else
00920                         {
00921                           if (l > 0)
00922                             {
00923                               if (c > 0)
00924                                 pr_where_1 ("error: called from '%s' near line %d, column %d",
00925                                             nm.c_str (), l, c);
00926                               else
00927                                 pr_where_1 ("error: called from '%d' near line %d", nm.c_str (), l);
00928                             }
00929                         }
00930                     }
00931                   else
00932                     {
00933                       if (nm.empty ())
00934                         {
00935                           if (l > 0)
00936                             {
00937                               if (c > 0)
00938                                 pr_where_1 ("error: in file %s near line %d, column %d",
00939                                             file.c_str (), l, c);
00940                               else
00941                                 pr_where_1 ("error: in file %s near line %d", file.c_str (), l);
00942                             }
00943                         }
00944                       else
00945                         {
00946                           if (l > 0)
00947                             {
00948                               if (c > 0)
00949                                 pr_where_1 ("error: called from '%s' in file %s near line %d, column %d",
00950                                             nm.c_str (), file.c_str (), l, c);
00951                               else
00952                                 pr_where_1 ("error: called from '%d' in file %s near line %d", nm.c_str (), file.c_str (), l);
00953                             }
00954                         }
00955                     }
00956                 }
00957             }
00958           else
00959             error ("rethrow: ERR structure must contain the fields 'message and 'identifier'");
00960         }
00961     }
00962   return retval;
00963 }
00964 
00965 DEFUN (error, args, ,
00966   "-*- texinfo -*-\n\
00967 @deftypefn  {Built-in Function} {} error (@var{template}, @dots{})\n\
00968 @deftypefnx {Built-in Function} {} error (@var{id}, @var{template}, @dots{})\n\
00969 Format the optional arguments under the control of the template string\n\
00970 @var{template} using the same rules as the @code{printf} family of\n\
00971 functions (@pxref{Formatted Output}) and print the resulting message\n\
00972 on the @code{stderr} stream.  The message is prefixed by the character\n\
00973 string @samp{error: }.\n\
00974 \n\
00975 Calling @code{error} also sets Octave's internal error state such that\n\
00976 control will return to the top level without evaluating any more\n\
00977 commands.  This is useful for aborting from functions or scripts.\n\
00978 \n\
00979 If the error message does not end with a new line character, Octave will\n\
00980 print a traceback of all the function calls leading to the error.  For\n\
00981 example, given the following function definitions:\n\
00982 \n\
00983 @example\n\
00984 @group\n\
00985 function f () g (); end\n\
00986 function g () h (); end\n\
00987 function h () nargin == 1 || error (\"nargin != 1\"); end\n\
00988 @end group\n\
00989 @end example\n\
00990 \n\
00991 @noindent\n\
00992 calling the function @code{f} will result in a list of messages that\n\
00993 can help you to quickly locate the exact location of the error:\n\
00994 \n\
00995 @example\n\
00996 @group\n\
00997 f ()\n\
00998 error: nargin != 1\n\
00999 error: called from:\n\
01000 error:   error at line -1, column -1\n\
01001 error:   h at line 1, column 27\n\
01002 error:   g at line 1, column 15\n\
01003 error:   f at line 1, column 15\n\
01004 @end group\n\
01005 @end example\n\
01006 \n\
01007 If the error message ends in a new line character, Octave will print the\n\
01008 message but will not display any traceback messages as it returns\n\
01009 control to the top level.  For example, modifying the error message\n\
01010 in the previous example to end in a new line causes Octave to only print\n\
01011 a single message:\n\
01012 \n\
01013 @example\n\
01014 @group\n\
01015 function h () nargin == 1 || error (\"nargin != 1\\n\"); end\n\
01016 f ()\n\
01017 error: nargin != 1\n\
01018 @end group\n\
01019 @end example\n\
01020 @end deftypefn")
01021 {
01022   octave_value retval;
01023 
01024   int nargin = args.length ();
01025 
01026   octave_value_list nargs = args;
01027 
01028   std::string id;
01029 
01030   if (nargin == 0)
01031     print_usage ();
01032   else
01033     {
01034       if (nargin > 1)
01035         {
01036           std::string arg1 = args(0).string_value ();
01037 
01038           if (! error_state)
01039             {
01040               if (arg1.find ('%') == std::string::npos)
01041                 {
01042                   id = arg1;
01043 
01044                   nargs.resize (nargin-1);
01045 
01046                   for (int i = 1; i < nargin; i++)
01047                     nargs(i-1) = args(i);
01048                 }
01049             }
01050           else
01051             return retval;
01052         }
01053       else if (nargin == 1 && args(0).is_map ())
01054         {
01055           // empty struct is not an error.  return and resume calling function.
01056           if (args(0).is_empty ())
01057             return retval;
01058 
01059           octave_value_list tmp;
01060 
01061           octave_scalar_map m = args(0).scalar_map_value ();
01062 
01063           // empty struct is not an error.  return and resume calling function.
01064           if (m.nfields () == 0)
01065             return retval;
01066 
01067           if (m.contains ("message"))
01068             {
01069               octave_value c = m.getfield ("message");
01070 
01071               if (c.is_string ())
01072                  nargs(0) = c.string_value ();
01073             }
01074 
01075           if (m.contains ("identifier"))
01076             {
01077               octave_value c = m.getfield ("identifier");
01078 
01079               if (c.is_string ())
01080                  id = c.string_value ();
01081             }
01082 
01083           // FIXME -- also need to handle "stack" field in error
01084           // structure, but that will require some more significant
01085           // surgery on handle_message, error_with_id, etc.
01086         }
01087 
01088       handle_message (error_with_id, id.c_str (), "unspecified error", nargs);
01089     }
01090 
01091   return retval;
01092 }
01093 
01094 DEFUN (warning, args, nargout,
01095   "-*- texinfo -*-\n\
01096 @deftypefn  {Built-in Function} {} warning (@var{template}, @dots{})\n\
01097 @deftypefnx {Built-in Function} {} warning (@var{id}, @var{template}, @dots{})\n\
01098 @deftypefnx {Built-in Function} {} warning (\"on\", @var{id})\n\
01099 @deftypefnx {Built-in Function} {} warning (\"off\", @var{id})\n\
01100 @deftypefnx {Built-in Function} {} warning (\"query\", @var{id})\n\
01101 @deftypefnx {Built-in Function} {} warning (\"error\", @var{id})\n\
01102 Format the optional arguments under the control of the template string\n\
01103 @var{template} using the same rules as the @code{printf} family of\n\
01104 functions (@pxref{Formatted Output}) and print the resulting message\n\
01105 on the @code{stderr} stream.  The message is prefixed by the character\n\
01106 string @samp{warning: }.\n\
01107 You should use this function when you want to notify the user\n\
01108 of an unusual condition, but only when it makes sense for your program\n\
01109 to go on.\n\
01110 \n\
01111 The optional message identifier allows users to enable or disable\n\
01112 warnings tagged by @var{id}.  A message identifier is of the form\n\
01113 \"NAMESPACE:WARNING-NAME\".  Octave's own warnings use the \"Octave\"\n\
01114 namespace (@pxref{doc-warning_ids}).  The special identifier @samp{\"all\"}\n\
01115 may be used to set the state of all warnings.\n\
01116 \n\
01117 If the first argument is @samp{\"on\"} or @samp{\"off\"}, set the state\n\
01118 of a particular warning using the identifier @var{id}.  If the first\n\
01119 argument is @samp{\"query\"}, query the state of this warning instead.\n\
01120 If the identifier is omitted, a value of @samp{\"all\"} is assumed.  If\n\
01121 you set the state of a warning to @samp{\"error\"}, the warning named by\n\
01122 @var{id} is handled as if it were an error instead.  So, for example, the\n\
01123 following handles all warnings as errors:\n\
01124 \n\
01125 @example\n\
01126 @group\n\
01127 warning (\"error\");\n\
01128 @end group\n\
01129 @end example\n\
01130 @seealso{warning_ids}\n\
01131 @end deftypefn")
01132 {
01133   octave_value retval;
01134 
01135   int nargin = args.length ();
01136   int argc = nargin + 1;
01137 
01138   bool done = false;
01139 
01140   if (argc > 1 && args.all_strings_p ())
01141     {
01142       string_vector argv = args.make_argv ("warning");
01143 
01144       if (! error_state)
01145         {
01146           std::string arg1 = argv(1);
01147           std::string arg2 = "all";
01148 
01149           if (argc == 3)
01150             arg2 = argv(2);
01151 
01152           if (arg1 == "on" || arg1 == "off" || arg1 == "error")
01153             {
01154               octave_map old_warning_options = warning_options;
01155 
01156               if (arg2 == "all")
01157                 {
01158                   octave_map tmp;
01159 
01160                   Cell id (1, 1);
01161                   Cell st (1, 1);
01162 
01163                   id(0) = arg2;
01164                   st(0) = arg1;
01165 
01166                   // Since internal Octave functions are not
01167                   // compatible, turning all warnings into errors
01168                   // should leave the state of
01169                   // Octave:matlab-incompatible alone.
01170 
01171                   if (arg1 == "error"
01172                       && warning_options.contains ("identifier"))
01173                     {
01174                       octave_idx_type n = 1;
01175 
01176                       Cell tid = warning_options.contents ("identifier");
01177                       Cell tst = warning_options.contents ("state");
01178 
01179                       for (octave_idx_type i = 0; i < tid.numel (); i++)
01180                         {
01181                           octave_value vid = tid(i);
01182 
01183                           if (vid.is_string ())
01184                             {
01185                               std::string key = vid.string_value ();
01186 
01187                               if (key == "Octave:matlab-incompatible"
01188                                   || key == "Octave:single-quote-string")
01189                                 {
01190                                   id.resize (dim_vector (1, n+1));
01191                                   st.resize (dim_vector (1, n+1));
01192 
01193                                   id(n) = tid(i);
01194                                   st(n) = tst(i);
01195 
01196                                   n++;
01197                                 }
01198                             }
01199                         }
01200                     }
01201 
01202                   tmp.assign ("identifier", id);
01203                   tmp.assign ("state", st);
01204 
01205                   warning_options = tmp;
01206 
01207                   done = true;
01208                 }
01209               else if (arg2 == "backtrace")
01210                 {
01211                   if (arg1 != "error")
01212                     {
01213                       Vbacktrace_on_warning = (arg1 == "on");
01214                       done = true;
01215                     }
01216                 }
01217               else if (arg2 == "debug")
01218                 {
01219                   if (arg1 != "error")
01220                     {
01221                       Vdebug_on_warning = (arg1 == "on");
01222                       done = true;
01223                     }
01224                 }
01225               else if (arg2 == "verbose")
01226                 {
01227                   if (arg1 != "error")
01228                     {
01229                       Vverbose_warning = (arg1 == "on");
01230                       done = true;
01231                     }
01232                 }
01233               else if (arg2 == "quiet")
01234                 {
01235                   if (arg1 != "error")
01236                     {
01237                       Vquiet_warning = (arg1 == "on");
01238                       done = true;
01239                     }
01240                 }
01241               else
01242                 {
01243                   if (arg2 == "last")
01244                     arg2 = Vlast_warning_id;
01245 
01246                   if (arg2 == "all")
01247                     initialize_warning_options (arg1);
01248                   else
01249                     {
01250                       Cell ident = warning_options.contents ("identifier");
01251                       Cell state = warning_options.contents ("state");
01252 
01253                       octave_idx_type nel = ident.numel ();
01254 
01255                       bool found = false;
01256 
01257                       for (octave_idx_type i = 0; i < nel; i++)
01258                         {
01259                           if (ident(i).string_value () == arg2)
01260                             {
01261                               // FIXME -- if state for "all" is
01262                               // same as arg1, we can simply remove the
01263                               // item from the list.
01264 
01265                               state(i) = arg1;
01266                               warning_options.assign ("state", state);
01267                               found = true;
01268                               break;
01269                             }
01270                         }
01271 
01272                       if (! found)
01273                         {
01274                           // FIXME -- if state for "all" is
01275                           // same as arg1, we don't need to do anything.
01276 
01277                           ident.resize (dim_vector (1, nel+1));
01278                           state.resize (dim_vector (1, nel+1));
01279 
01280                           ident(nel) = arg2;
01281                           state(nel) = arg1;
01282 
01283                           warning_options.clear ();
01284 
01285                           warning_options.assign ("identifier", ident);
01286                           warning_options.assign ("state", state);
01287                         }
01288                     }
01289 
01290                   done = true;
01291                 }
01292 
01293               if (done && nargout > 0)
01294                 retval = old_warning_options;
01295             }
01296           else if (arg1 == "query")
01297             {
01298               if (arg2 == "all")
01299                 retval = warning_options;
01300               else if (arg2 == "backtrace" || arg2 == "debug"
01301                        || arg2 == "verbose" || arg2 == "quiet")
01302                 {
01303                   octave_scalar_map tmp;
01304                   tmp.assign ("identifier", arg2);
01305                   if (arg2 == "backtrace")
01306                     tmp.assign ("state", Vbacktrace_on_warning ? "on" : "off");
01307                   else if (arg2 == "debug")
01308                     tmp.assign ("state", Vdebug_on_warning ? "on" : "off");
01309                   else if (arg2 == "verbose")
01310                     tmp.assign ("state", Vverbose_warning ? "on" : "off");
01311                   else
01312                     tmp.assign ("state", Vquiet_warning ? "on" : "off");
01313 
01314                   retval = tmp;
01315                 }
01316               else
01317                 {
01318                   if (arg2 == "last")
01319                     arg2 = Vlast_warning_id;
01320 
01321                   Cell ident = warning_options.contents ("identifier");
01322                   Cell state = warning_options.contents ("state");
01323 
01324                   octave_idx_type nel = ident.numel ();
01325 
01326                   bool found = false;
01327 
01328                   std::string val;
01329 
01330                   for (octave_idx_type i = 0; i < nel; i++)
01331                     {
01332                       if (ident(i).string_value () == arg2)
01333                         {
01334                           val = state(i).string_value ();
01335                           found = true;
01336                           break;
01337                         }
01338                     }
01339 
01340                   if (! found)
01341                     {
01342                       for (octave_idx_type i = 0; i < nel; i++)
01343                         {
01344                           if (ident(i).string_value () == "all")
01345                             {
01346                               val = state(i).string_value ();
01347                               found = true;
01348                               break;
01349                             }
01350                         }
01351                     }
01352 
01353                   if (found)
01354                     {
01355                       octave_scalar_map tmp;
01356 
01357                       tmp.assign ("identifier", arg2);
01358                       tmp.assign ("state", val);
01359 
01360                       retval = tmp;
01361                     }
01362                   else
01363                     error ("warning: unable to find default warning state!");
01364                 }
01365 
01366               done = true;
01367             }
01368         }
01369     }
01370   else if (argc == 1)
01371     {
01372       retval = warning_options;
01373 
01374       done = true;
01375     }
01376   else if (argc == 2)
01377     {
01378       octave_value arg = args(0);
01379 
01380       octave_map old_warning_options = warning_options;
01381 
01382       if (arg.is_map ())
01383         {
01384           octave_map m = arg.map_value ();
01385 
01386           if (m.contains ("identifier") && m.contains ("state"))
01387             warning_options = m;
01388           else
01389             error ("warning: expecting structure with fields 'identifier' and 'state'");
01390 
01391           done = true;
01392 
01393           if (nargout > 0)
01394             retval = old_warning_options;
01395         }
01396     }
01397 
01398   if (! (error_state || done))
01399     {
01400       octave_value_list nargs = args;
01401 
01402       std::string id;
01403 
01404       if (nargin > 1)
01405         {
01406           std::string arg1 = args(0).string_value ();
01407 
01408           if (! error_state)
01409             {
01410               if (arg1.find ('%') == std::string::npos)
01411                 {
01412                   id = arg1;
01413 
01414                   nargs.resize (nargin-1);
01415 
01416                   for (int i = 1; i < nargin; i++)
01417                     nargs(i-1) = args(i);
01418                 }
01419             }
01420           else
01421             return retval;
01422         }
01423 
01424       std::string prev_msg = Vlast_warning_message;
01425 
01426       std::string curr_msg = handle_message (warning_with_id, id.c_str (),
01427                                              "unspecified warning", nargs);
01428 
01429       if (nargout > 0)
01430         retval = prev_msg;
01431     }
01432 
01433   return retval;
01434 }
01435 
01436 octave_value_list
01437 set_warning_state (const std::string& id, const std::string& state)
01438 {
01439   octave_value_list args;
01440 
01441   args(1) = id;
01442   args(0) = state;
01443 
01444   return Fwarning (args, 1);
01445 }
01446 
01447 octave_value_list
01448 set_warning_state (const octave_value_list& args)
01449 {
01450   return Fwarning (args, 1);
01451 }
01452 
01453 void
01454 disable_warning (const std::string& id)
01455 {
01456   set_warning_state (id, "off");
01457 }
01458 
01459 void
01460 initialize_default_warning_state (void)
01461 {
01462   initialize_warning_options ("on");
01463 
01464   // Most people will want to have the following disabled.
01465 
01466   disable_warning ("Octave:array-to-scalar");
01467   disable_warning ("Octave:array-to-vector");
01468   disable_warning ("Octave:imag-to-real");
01469   disable_warning ("Octave:matlab-incompatible");
01470   disable_warning ("Octave:missing-semicolon");
01471   disable_warning ("Octave:neg-dim-as-zero");
01472   disable_warning ("Octave:resize-on-range-error");
01473   disable_warning ("Octave:separator-insert");
01474   disable_warning ("Octave:single-quote-string");
01475   disable_warning ("Octave:str-to-num");
01476   disable_warning ("Octave:mixed-string-concat");
01477   disable_warning ("Octave:variable-switch-label");
01478 
01479   // This should be an error unless we are in maximum braindamage mode.
01480   // FIXME: Not quite right.  This sets the error state even for braindamage
01481   // mode.  Also, this error is not triggered in normal mode because another
01482   // error handler catches it first and gives:
01483   // error: subscript indices must be either positive integers or logicals
01484   set_warning_state ("Octave:noninteger-range-as-index", "error");
01485 
01486 }
01487 
01488 DEFUN (lasterror, args, ,
01489   "-*- texinfo -*-\n\
01490 @deftypefn  {Built-in Function} {@var{lasterr} =} lasterror ()\n\
01491 @deftypefnx {Built-in Function} {} lasterror (@var{err})\n\
01492 @deftypefnx {Built-in Function} {} lasterror ('reset')\n\
01493 Query or set the last error message structure.  When called without\n\
01494 arguments, return a structure containing the last error message and other\n\
01495 information related to this error.  The elements of the structure are:\n\
01496 \n\
01497 @table @asis\n\
01498 @item 'message'\n\
01499 The text of the last error message\n\
01500 \n\
01501 @item 'identifier'\n\
01502 The message identifier of this error message\n\
01503 \n\
01504 @item 'stack'\n\
01505 A structure containing information on where the message occurred.  This may\n\
01506 be an empty structure if the information cannot\n\
01507 be obtained.  The fields of the structure are:\n\
01508 \n\
01509 @table @asis\n\
01510 @item 'file'\n\
01511 The name of the file where the error occurred\n\
01512 \n\
01513 @item 'name'\n\
01514 The name of function in which the error occurred\n\
01515 \n\
01516 @item 'line'\n\
01517 The line number at which the error occurred\n\
01518 \n\
01519 @item 'column'\n\
01520 An optional field with the column number at which the error occurred\n\
01521 @end table\n\
01522 @end table\n\
01523 \n\
01524 The last error structure may be set by passing a scalar structure, @var{err},\n\
01525 as input.  Any fields of @var{err} that match those above are set while any\n\
01526 unspecified fields are initialized with default values.\n\
01527 \n\
01528 If @code{lasterror} is called with the argument 'reset', all fields are\n\
01529 set to their default values.\n\
01530 @seealso{lasterr}\n\
01531 @end deftypefn")
01532 {
01533   octave_value retval;
01534   int nargin = args.length();
01535 
01536   unwind_protect frame;
01537 
01538   frame.protect_var (error_state);
01539   error_state = 0;
01540 
01541   if (nargin < 2)
01542     {
01543       octave_scalar_map err;
01544 
01545       err.assign ("message", Vlast_error_message);
01546       err.assign ("identifier", Vlast_error_id);
01547 
01548       err.assign ("stack", octave_value (Vlast_error_stack));
01549 
01550       if (nargin == 1)
01551         {
01552           if (args(0).is_string())
01553             {
01554               if (args(0).string_value () == "reset")
01555                 {
01556                   Vlast_error_message = std::string();
01557                   Vlast_error_id = std::string();
01558 
01559                   Vlast_error_stack = initialize_last_error_stack ();
01560                 }
01561               else
01562                 error("lasterror: unrecognized string argument");
01563             }
01564           else if (args(0).is_map ())
01565             {
01566               octave_scalar_map new_err = args(0).scalar_map_value ();
01567               std::string new_error_message;
01568               std::string new_error_id;
01569               std::string new_error_file;
01570               std::string new_error_name;
01571               int new_error_line = -1;
01572               int new_error_column = -1;
01573 
01574               if (! error_state && new_err.contains ("message"))
01575                 {
01576                   const std::string tmp =
01577                     new_err.getfield("message").string_value ();
01578                   new_error_message = tmp;
01579                 }
01580 
01581               if (! error_state && new_err.contains ("identifier"))
01582                 {
01583                   const std::string tmp =
01584                     new_err.getfield("identifier").string_value ();
01585                   new_error_id = tmp;
01586                 }
01587 
01588               if (! error_state && new_err.contains ("stack"))
01589                 {
01590                   octave_scalar_map new_err_stack =
01591                     new_err.getfield("stack").scalar_map_value ();
01592 
01593                   if (! error_state && new_err_stack.contains ("file"))
01594                     {
01595                       const std::string tmp =
01596                         new_err_stack.getfield("file").string_value ();
01597                       new_error_file = tmp;
01598                     }
01599 
01600                   if (! error_state && new_err_stack.contains ("name"))
01601                     {
01602                       const std::string tmp =
01603                         new_err_stack.getfield("name").string_value ();
01604                       new_error_name = tmp;
01605                     }
01606 
01607                   if (! error_state && new_err_stack.contains ("line"))
01608                     {
01609                       const int tmp =
01610                         new_err_stack.getfield("line").nint_value ();
01611                       new_error_line = tmp;
01612                     }
01613 
01614                   if (! error_state && new_err_stack.contains ("column"))
01615                     {
01616                       const int tmp =
01617                         new_err_stack.getfield("column").nint_value ();
01618                       new_error_column = tmp;
01619                     }
01620                 }
01621 
01622               if (! error_state)
01623                 {
01624                   Vlast_error_message = new_error_message;
01625                   Vlast_error_id = new_error_id;
01626 
01627                   octave_idx_type curr_frame = -1;
01628 
01629                   Vlast_error_stack
01630                     = octave_call_stack::backtrace (0, curr_frame);
01631                 }
01632             }
01633           else
01634             error ("lasterror: argument must be a structure or a string");
01635         }
01636 
01637       if (! error_state)
01638         retval = err;
01639     }
01640   else
01641     print_usage ();
01642 
01643   return retval;
01644 }
01645 
01646 DEFUN (lasterr, args, nargout,
01647   "-*- texinfo -*-\n\
01648 @deftypefn  {Built-in Function} {[@var{msg}, @var{msgid}] =} lasterr ()\n\
01649 @deftypefnx {Built-in Function} {} lasterr (@var{msg})\n\
01650 @deftypefnx {Built-in Function} {} lasterr (@var{msg}, @var{msgid})\n\
01651 Query or set the last error message.  When called without input arguments,\n\
01652 return the last error message and message identifier.  With one\n\
01653 argument, set the last error message to @var{msg}.  With two arguments,\n\
01654 also set the last message identifier.\n\
01655 @seealso{lasterror}\n\
01656 @end deftypefn")
01657 {
01658   octave_value_list retval;
01659 
01660   unwind_protect frame;
01661 
01662   frame.protect_var (error_state);
01663   error_state = 0;
01664 
01665   int argc = args.length () + 1;
01666 
01667   if (argc < 4)
01668     {
01669       string_vector argv = args.make_argv ("lasterr");
01670 
01671       if (! error_state)
01672         {
01673           std::string prev_error_id = Vlast_error_id;
01674           std::string prev_error_message = Vlast_error_message;
01675 
01676           if (argc > 2)
01677             Vlast_error_id = argv(2);
01678 
01679           if (argc > 1)
01680             Vlast_error_message = argv(1);
01681 
01682           if (argc == 1 || nargout > 0)
01683             {
01684               retval(1) = prev_error_id;
01685               retval(0) = prev_error_message;
01686             }
01687         }
01688       else
01689         error ("lasterr: expecting arguments to be character strings");
01690     }
01691   else
01692     print_usage ();
01693 
01694   return retval;
01695 }
01696 
01697 DEFUN (lastwarn, args, nargout,
01698   "-*- texinfo -*-\n\
01699 @deftypefn {Built-in Function} {[@var{msg}, @var{msgid}] =} lastwarn (@var{msg}, @var{msgid})\n\
01700 Without any arguments, return the last warning message.  With one\n\
01701 argument, set the last warning message to @var{msg}.  With two arguments,\n\
01702 also set the last message identifier.\n\
01703 @end deftypefn")
01704 {
01705   octave_value_list retval;
01706 
01707   int argc = args.length () + 1;
01708 
01709   if (argc < 4)
01710     {
01711       string_vector argv = args.make_argv ("lastwarn");
01712 
01713       if (! error_state)
01714         {
01715           std::string prev_warning_id = Vlast_warning_id;
01716           std::string prev_warning_message = Vlast_warning_message;
01717 
01718           if (argc > 2)
01719             Vlast_warning_id = argv(2);
01720 
01721           if (argc > 1)
01722             Vlast_warning_message = argv(1);
01723 
01724           if (argc == 1 || nargout > 0)
01725             {
01726               warning_state = 0;
01727               retval(1) = prev_warning_id;
01728               retval(0) = prev_warning_message;
01729             }
01730         }
01731       else
01732         error ("lastwarn: expecting arguments to be character strings");
01733     }
01734   else
01735     print_usage ();
01736 
01737   return retval;
01738 }
01739 
01740 DEFUN (usage, args, ,
01741   "-*- texinfo -*-\n\
01742 @deftypefn {Built-in Function} {} usage (@var{msg})\n\
01743 Print the message @var{msg}, prefixed by the string @samp{usage: }, and\n\
01744 set Octave's internal error state such that control will return to the\n\
01745 top level without evaluating any more commands.  This is useful for\n\
01746 aborting from functions.\n\
01747 \n\
01748 After @code{usage} is evaluated, Octave will print a traceback of all\n\
01749 the function calls leading to the usage message.\n\
01750 \n\
01751 You should use this function for reporting problems errors that result\n\
01752 from an improper call to a function, such as calling a function with an\n\
01753 incorrect number of arguments, or with arguments of the wrong type.  For\n\
01754 example, most functions distributed with Octave begin with code like\n\
01755 this\n\
01756 \n\
01757 @example\n\
01758 @group\n\
01759 if (nargin != 2)\n\
01760   usage (\"foo (a, b)\");\n\
01761 endif\n\
01762 @end group\n\
01763 @end example\n\
01764 \n\
01765 @noindent\n\
01766 to check for the proper number of arguments.\n\
01767 @end deftypefn")
01768 {
01769   octave_value_list retval;
01770   handle_message (usage_with_id, "", "unknown", args);
01771   return retval;
01772 }
01773 
01774 DEFUN (beep_on_error, args, nargout,
01775   "-*- texinfo -*-\n\
01776 @deftypefn  {Built-in Function} {@var{val} =} beep_on_error ()\n\
01777 @deftypefnx {Built-in Function} {@var{old_val} =} beep_on_error (@var{new_val})\n\
01778 @deftypefnx {Built-in Function} {} beep_on_error (@var{new_val}, \"local\")\n\
01779 Query or set the internal variable that controls whether Octave will try\n\
01780 to ring the terminal bell before printing an error message.\n\
01781 \n\
01782 When called from inside a function with the \"local\" option, the variable is\n\
01783 changed locally for the function and any subroutines it calls.  The original\n\
01784 variable value is restored when exiting the function.\n\
01785 @end deftypefn")
01786 {
01787   return SET_INTERNAL_VARIABLE (beep_on_error);
01788 }
01789 
01790 DEFUN (debug_on_error, args, nargout,
01791     "-*- texinfo -*-\n\
01792 @deftypefn  {Built-in Function} {@var{val} =} debug_on_error ()\n\
01793 @deftypefnx {Built-in Function} {@var{old_val} =} debug_on_error (@var{new_val})\n\
01794 @deftypefnx {Built-in Function} {} debug_on_error (@var{new_val}, \"local\")\n\
01795 Query or set the internal variable that controls whether Octave will try\n\
01796 to enter the debugger when an error is encountered.  This will also\n\
01797 inhibit printing of the normal traceback message (you will only see\n\
01798 the top-level error message).\n\
01799 \n\
01800 When called from inside a function with the \"local\" option, the variable is\n\
01801 changed locally for the function and any subroutines it calls.  The original\n\
01802 variable value is restored when exiting the function.\n\
01803 @seealso{debug_on_warning, debug_on_interrupt}\n\
01804 @end deftypefn")
01805 {
01806   return SET_INTERNAL_VARIABLE (debug_on_error);
01807 }
01808 
01809 DEFUN (debug_on_warning, args, nargout,
01810     "-*- texinfo -*-\n\
01811 @deftypefn  {Built-in Function} {@var{val} =} debug_on_warning ()\n\
01812 @deftypefnx {Built-in Function} {@var{old_val} =} debug_on_warning (@var{new_val})\n\
01813 @deftypefnx {Built-in Function} {} debug_on_warning (@var{new_val}, \"local\")\n\
01814 Query or set the internal variable that controls whether Octave will try\n\
01815 to enter the debugger when a warning is encountered.\n\
01816 \n\
01817 When called from inside a function with the \"local\" option, the variable is\n\
01818 changed locally for the function and any subroutines it calls.  The original\n\
01819 variable value is restored when exiting the function.\n\
01820 @seealso{debug_on_error, debug_on_interrupt}\n\
01821 @end deftypefn")
01822 {
01823   return SET_INTERNAL_VARIABLE (debug_on_warning);
01824 }
01825 
01826 std::string
01827 last_error_message (void)
01828 {
01829   return Vlast_error_message;
01830 }
01831 
01832 std::string
01833 last_error_id (void)
01834 {
01835   return Vlast_error_id;
01836 }
01837 
01838 std::string
01839 last_warning_message (void)
01840 {
01841   return Vlast_warning_message;
01842 }
01843 
01844 std::string
01845 last_warning_id (void)
01846 {
01847   return Vlast_warning_id;
01848 }
01849 
01850 void
01851 interpreter_try (unwind_protect& frame)
01852 {
01853   frame.protect_var (error_state);
01854   frame.protect_var (buffer_error_messages);
01855   frame.protect_var (Vdebug_on_error);
01856   frame.protect_var (Vdebug_on_warning);
01857 
01858   buffer_error_messages++;
01859   Vdebug_on_error = false;
01860   Vdebug_on_warning = false;
01861 }
01862 
01863 
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines