00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00050
00051 static bool Vbeep_on_error = false;
00052
00053
00054
00055
00056 bool Vdebug_on_error = false;
00057
00058
00059
00060 bool Vdebug_on_warning = false;
00061
00062
00063
00064 static bool Vbacktrace_on_warning = false;
00065
00066
00067 static bool Vverbose_warning;
00068
00069
00070
00071 static bool Vquiet_warning = false;
00072
00073
00074 static octave_map warning_options;
00075
00076
00077 static std::string Vlast_error_message;
00078
00079
00080 static std::string Vlast_warning_message;
00081
00082
00083 static std::string Vlast_warning_id;
00084
00085
00086 static std::string Vlast_error_id;
00087
00088
00089 static octave_map Vlast_error_stack;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 int error_state = 0;
00101
00102
00103
00104
00105
00106
00107
00108
00109 int warning_state = 0;
00110
00111
00112
00113
00114 int buffer_error_messages = 0;
00115
00116
00117 bool discard_error_messages = false;
00118
00119
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
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
00168
00169
00170
00171 std::string msg_string = output_buf.str ();
00172
00173 if (! warning_state)
00174 {
00175
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
00201
00202
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
00221
00222
00223
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
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
00271
00272
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
00540
00541
00542
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
00555
00556
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
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
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
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
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
00899
00900
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
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
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
01084
01085
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
01167
01168
01169
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
01262
01263
01264
01265 state(i) = arg1;
01266 warning_options.assign ("state", state);
01267 found = true;
01268 break;
01269 }
01270 }
01271
01272 if (! found)
01273 {
01274
01275
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
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
01480
01481
01482
01483
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