comparison libinterp/corefcn/error.cc @ 20569:b70cc4bd8109

begin removal of global error_state variable * gripes.h, gripes.cc (gripe_library_execution_error): Delete. * error.cc (warning_state): Delete unused variable. (reset_error_handler): Don't set warning_state or error_state. (debug_or_throw_exception): New static function. (verror): Don't check error_state. (vmessage): Call debug_or_throw_exception instead of setting error_state. (error_1, error_2): Combine into single function, error_1 that prints error message and ultimately calls debug_or_throw_exception. (verror, verror_with_cfn, verror_with_id_cfn): Call error_1. Don't check or set warning_state. (error): Don't check error_state. (Flasterror, Flasterr): Adapt to not using error_state. (interpreter_try): Don't unwind_protect error_state. * NEWS: Update. * doc/interpreter/external.txi: Explain octave_execution_exception instead of error_state for matrix addition example. * jit-typeinfo.cc (octave_jit_gripe_nan_to_logical_conversion, octave_jit_ginvalid_index, octave_jit_gindex_range, octave_jit_paren_scalar, octave_jit_paren_scalar_subsasgn): Don't catch octave_execution_exception. * cellfun.cc (Fcellfun): Use exceptions instead of error_state. * ls-mat-ascii.cc (save_mat_ascii_data): Likewise. * mex.cc (mexCallMATLAB, mexEvalString): Likewise. * variables.cc (safe_symbol_lookup): Likewise. * svd.cc (Fsvd): Eliminate use of error_state. * __magick_read__.cc (read_file, write_file): Likewise. * variables.cc (generate_struct_completions): Eliminate use of obsolete warning_state variable. * ov-builtin.cc (octave_builtin::do_multi_index_op): Don't catch octave_execution_exception and call gripe_library_execution_error. * ov-class.cc (octave_class::reconstruct_exemplar): Eliminate use of error_state. Catch possible octave_execution_exception in do_multi_index_op. * ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Eliminate use of error_state. Catch possible octave_execution_exception in call_mex. * ov-fcn-handle.cc (octave_fcn_binder::maybe_binder): Eliminate use of error_state. * ov-oncleanup.cc (octave_oncleanup::~octave_oncleanup): Eliminate use of error_state. Propagate possible octave_execution_exception from do_multi_index_op. * ov.cc (octave_value::assign, do_binary_op, do_unary_op, octave_value::do_non_const_unary_op): Don't catch octave_execution_exception here. * oct-parse.in.yy (octave_base_parser::finish_colon_expression, octave_base_parser::finish_array_list): Eliminate use of warning_state and error_state. (Feval, Fevalin): Use exceptions instead of error_state. * pt-eval.cc, pt-eval.h (tree_evaluator::unwind_protect_exception): New static variable. * (tree_evaluator::visit_statement): Don't catch octave_execution_exception here. (tree_evaluator::visit_try_catch_command, tree_evaluator::do_unwind_protect_cleanup): Eliminate use of error_state. (tree_evaluator::visit_unwind_protect_command): Use unwind_protect_exception to track whether an exception has occurred in the try block.
author John W. Eaton <jwe@octave.org>
date Thu, 01 Oct 2015 16:18:19 -0400
parents 9502e0142c19
children
comparison
equal deleted inserted replaced
20568:fcb792acab9b 20569:b70cc4bd8109
91 91
92 // Current error state. 92 // Current error state.
93 // 93 //
94 // Valid values: 94 // Valid values:
95 // 95 //
96 // -2: an error has occurred, but don't print any messages.
97 // -1: an error has occurred, we are printing a traceback
98 // 0: no error 96 // 0: no error
99 // 1: an error has occurred 97 // 1: an error has occurred
100 // 98 //
101 int error_state = 0; 99 int error_state = 0;
102 100
103 // Current warning state.
104 //
105 // Valid values:
106 //
107 // 0: no warning
108 // 1: a warning has occurred
109 //
110 int warning_state = 0;
111
112 // Tell the error handler whether to print messages, or just store 101 // Tell the error handler whether to print messages, or just store
113 // them for later. Used for handling errors in eval() and 102 // them for later. Used for handling errors in eval() and
114 // the 'unwind_protect' statement. 103 // the 'unwind_protect' statement.
115 int buffer_error_messages = 0; 104 int buffer_error_messages = 0;
116 105
121 bool discard_warning_messages = false; 110 bool discard_warning_messages = false;
122 111
123 void 112 void
124 reset_error_handler (void) 113 reset_error_handler (void)
125 { 114 {
126 error_state = 0;
127 warning_state = 0;
128 buffer_error_messages = 0; 115 buffer_error_messages = 0;
129 discard_error_messages = false; 116 discard_error_messages = false;
130 } 117 }
131 118
132 static void 119 static void
142 129
143 static octave_map 130 static octave_map
144 initialize_last_error_stack (void) 131 initialize_last_error_stack (void)
145 { 132 {
146 return octave_call_stack::empty_backtrace (); 133 return octave_call_stack::empty_backtrace ();
134 }
135
136 static void
137 debug_or_throw_exception (void)
138 {
139 if ((interactive || forced_interactive)
140 && Vdebug_on_error && octave_call_stack::caller_user_code ())
141 {
142 unwind_protect frame;
143 frame.protect_var (Vdebug_on_error);
144 Vdebug_on_error = false;
145
146 tree_evaluator::debug_mode = true;
147
148 tree_evaluator::current_frame = octave_call_stack::current_frame ();
149
150 do_keyboard (octave_value_list ());
151 }
152 else
153 octave_throw_execution_exception ();
147 } 154 }
148 155
149 // Warning messages are never buffered. 156 // Warning messages are never buffered.
150 157
151 static void 158 static void
202 209
203 octave_vformat (output_buf, fmt, args); 210 octave_vformat (output_buf, fmt, args);
204 211
205 std::string base_msg = output_buf.str (); 212 std::string base_msg = output_buf.str ();
206 213
207 bool to_beep_or_not_to_beep_p = Vbeep_on_error && ! error_state; 214 bool to_beep_or_not_to_beep_p = Vbeep_on_error;
208 215
209 std::string msg_string; 216 std::string msg_string;
210 217
211 if (to_beep_or_not_to_beep_p) 218 if (to_beep_or_not_to_beep_p)
212 msg_string = "\a"; 219 msg_string = "\a";
236 } 243 }
237 } 244 }
238 245
239 msg_string += base_msg + "\n"; 246 msg_string += base_msg + "\n";
240 247
241 if (! error_state && save_last_error) 248 if (save_last_error)
242 { 249 {
243 // This is the first error in a possible series. 250 // This is the first error in a possible series.
244 251
245 Vlast_error_id = id; 252 Vlast_error_id = id;
246 Vlast_error_message = base_msg; 253 Vlast_error_message = base_msg;
330 pr_where_1 (" %s at line %d column %d\n", 337 pr_where_1 (" %s at line %d column %d\n",
331 fcn_name.c_str (), line, column); 338 fcn_name.c_str (), line, column);
332 } 339 }
333 } 340 }
334 341
335 // Note that we don't actually print any message if the error string
336 // is just "" or "\n". This allows error ("") and error ("\n") to
337 // just set the error state.
338
339 static void
340 error_1 (std::ostream& os, const char *name, const char *id,
341 const char *fmt, va_list args, bool with_cfn = false)
342 {
343 if (error_state != -2)
344 {
345 if (fmt && *fmt)
346 {
347 size_t len = strlen (fmt);
348
349 if (len > 0)
350 {
351 if (fmt[len - 1] == '\n')
352 {
353 if (len > 1)
354 {
355 // Strip newline before issuing error
356 std::string tmp_fmt (fmt, len - 1);
357 verror (true, os, name, id, tmp_fmt.c_str (),
358 args, with_cfn);
359 }
360
361 error_state = -2;
362 }
363 else
364 {
365 verror (true, os, name, id, fmt, args, with_cfn);
366
367 if (! error_state)
368 error_state = 1;
369 }
370 }
371 }
372 else
373 panic ("error_1: invalid format");
374 }
375 }
376
377 void 342 void
378 vmessage (const char *name, const char *fmt, va_list args) 343 vmessage (const char *name, const char *fmt, va_list args)
379 { 344 {
380 verror (false, std::cerr, name, "", fmt, args); 345 verror (false, std::cerr, name, "", fmt, args);
381 } 346 }
407 372
408 void 373 void
409 usage_1 (const char *id, const char *fmt, va_list args) 374 usage_1 (const char *id, const char *fmt, va_list args)
410 { 375 {
411 verror (true, std::cerr, "usage", id, fmt, args); 376 verror (true, std::cerr, "usage", id, fmt, args);
412 error_state = -1; 377
378 debug_or_throw_exception ();
413 } 379 }
414 380
415 void 381 void
416 vusage (const char *fmt, va_list args) 382 vusage (const char *fmt, va_list args)
417 { 383 {
441 vusage_with_id (id, fmt, args); 407 vusage_with_id (id, fmt, args);
442 va_end (args); 408 va_end (args);
443 } 409 }
444 410
445 static void 411 static void
446 error_2 (const char *id, const char *fmt, va_list args, bool with_cfn = false) 412 error_1 (std::ostream& os, const char *name, const char *id,
447 { 413 const char *fmt, va_list args, bool with_cfn = false)
448 int init_state = error_state; 414 {
449 415 if (fmt)
450 error_1 (std::cerr, "error", id, fmt, args, with_cfn); 416 {
451 417 if (*fmt)
452 bool in_user_code = octave_call_stack::caller_user_code () != 0; 418 {
453 419 size_t len = strlen (fmt);
454 if (error_state != -2 && in_user_code && ! discard_error_messages) 420
455 pr_where ("error"); 421 if (len > 0)
456 422 {
457 if (interactive && Vdebug_on_error && init_state == 0 && in_user_code) 423 if (fmt[len - 1] == '\n')
458 { 424 {
459 unwind_protect frame; 425 if (len > 1)
460 frame.protect_var (Vdebug_on_error); 426 {
461 Vdebug_on_error = false; 427 char *tmp_fmt = strsave (fmt);
462 428 tmp_fmt[len - 1] = '\0';
463 error_state = 0; 429 verror (true, os, name, id, tmp_fmt, args, with_cfn);
464 430 delete [] tmp_fmt;
465 tree_evaluator::debug_mode = true; 431 }
466 432 }
467 tree_evaluator::current_frame = octave_call_stack::current_frame (); 433 else
468 434 {
469 do_keyboard (octave_value_list ()); 435 verror (true, os, name, id, fmt, args, with_cfn);
470 } 436
437 bool in_user_code = octave_call_stack::caller_user_code () != 0;
438
439 if (in_user_code && ! discard_error_messages)
440 pr_where ("error");
441 }
442 }
443 }
444 }
445 else
446 panic ("error_1: invalid format");
447
448 debug_or_throw_exception ();
471 } 449 }
472 450
473 void 451 void
474 verror (const char *fmt, va_list args) 452 verror (const char *fmt, va_list args)
475 { 453 {
476 error_2 ("", fmt, args); 454 error_1 (std::cerr, "error", "", fmt, args);
477 } 455 }
478 456
479 void 457 void
480 error (const char *fmt, ...) 458 error (const char *fmt, ...)
481 { 459 {
486 } 464 }
487 465
488 void 466 void
489 verror_with_cfn (const char *fmt, va_list args) 467 verror_with_cfn (const char *fmt, va_list args)
490 { 468 {
491 error_2 ("", fmt, args, true); 469 error_1 (std::cerr, "error", "", fmt, args, true);
492 } 470 }
493 471
494 void 472 void
495 error_with_cfn (const char *fmt, ...) 473 error_with_cfn (const char *fmt, ...)
496 { 474 {
501 } 479 }
502 480
503 void 481 void
504 verror_with_id (const char *id, const char *fmt, va_list args) 482 verror_with_id (const char *id, const char *fmt, va_list args)
505 { 483 {
506 error_2 (id, fmt, args); 484 error_1 (std::cerr, "error", id, fmt, args);
507 } 485 }
508 486
509 void 487 void
510 error_with_id (const char *id, const char *fmt, ...) 488 error_with_id (const char *id, const char *fmt, ...)
511 { 489 {
516 } 494 }
517 495
518 void 496 void
519 verror_with_id_cfn (const char *id, const char *fmt, va_list args) 497 verror_with_id_cfn (const char *id, const char *fmt, va_list args)
520 { 498 {
521 error_2 (id, fmt, args, true); 499 error_1 (std::cerr, "error", id, fmt, args, true);
522 } 500 }
523 501
524 void 502 void
525 error_with_id_cfn (const char *id, const char *fmt, ...) 503 error_with_id_cfn (const char *id, const char *fmt, ...)
526 { 504 {
630 608
631 if (warn_opt == 2) 609 if (warn_opt == 2)
632 { 610 {
633 // Handle this warning as an error. 611 // Handle this warning as an error.
634 612
635 error_2 (id, fmt, args); 613 error_1 (std::cerr, "error", id, fmt, args);
636 } 614 }
637 else if (warn_opt == 1) 615 else if (warn_opt == 1)
638 { 616 {
639 bool fmt_suppresses_backtrace = false; 617 bool fmt_suppresses_backtrace = false;
640 size_t fmt_len = fmt ? strlen (fmt) : 0; 618 size_t fmt_len = fmt ? strlen (fmt) : 0;
649 else 627 else
650 vwarning ("warning", id, fmt, args); 628 vwarning ("warning", id, fmt, args);
651 629
652 bool in_user_code = octave_call_stack::caller_user_code () != 0; 630 bool in_user_code = octave_call_stack::caller_user_code () != 0;
653 631
654
655 if (! fmt_suppresses_backtrace && in_user_code 632 if (! fmt_suppresses_backtrace && in_user_code
656 && Vbacktrace_on_warning && ! warning_state 633 && Vbacktrace_on_warning
657 && ! discard_warning_messages) 634 && ! discard_warning_messages)
658 pr_where ("warning"); 635 pr_where ("warning");
659
660 warning_state = 1;
661 636
662 if ((interactive || forced_interactive) 637 if ((interactive || forced_interactive)
663 && Vdebug_on_warning && in_user_code) 638 && Vdebug_on_warning && in_user_code)
664 { 639 {
665 unwind_protect frame; 640 unwind_protect frame;
858 print_usage (); 833 print_usage ();
859 else 834 else
860 { 835 {
861 const octave_scalar_map err = args(0).scalar_map_value (); 836 const octave_scalar_map err = args(0).scalar_map_value ();
862 837
863 if (! error_state) 838 if (err.contains ("message") && err.contains ("identifier"))
864 { 839 {
865 if (err.contains ("message") && err.contains ("identifier")) 840 std::string msg = err.contents ("message").string_value ();
841 std::string id = err.contents ("identifier").string_value ();
842 int len = msg.length ();
843
844 std::string file;
845 std::string nm;
846 int l = -1;
847 int c = -1;
848
849 octave_map err_stack = initialize_last_error_stack ();
850
851 if (err.contains ("stack"))
866 { 852 {
867 std::string msg = err.contents ("message").string_value (); 853 err_stack = err.contents ("stack").map_value ();
868 std::string id = err.contents ("identifier").string_value (); 854
869 int len = msg.length (); 855 if (err_stack.numel () > 0)
870 856 {
871 std::string file; 857 if (err_stack.contains ("file"))
872 std::string nm; 858 file = err_stack.contents ("file")(0).string_value ();
873 int l = -1; 859
874 int c = -1; 860 if (err_stack.contains ("name"))
875 861 nm = err_stack.contents ("name")(0).string_value ();
876 octave_map err_stack = initialize_last_error_stack (); 862
877 863 if (err_stack.contains ("line"))
878 if (err.contains ("stack")) 864 l = err_stack.contents ("line")(0).nint_value ();
879 { 865
880 err_stack = err.contents ("stack").map_value (); 866 if (err_stack.contains ("column"))
881 867 c = err_stack.contents ("column")(0).nint_value ();
882 if (err_stack.numel () > 0) 868 }
869 }
870
871 // Ugh.
872 char *tmp_msg = strsave (msg.c_str ());
873 if (tmp_msg[len-1] == '\n')
874 {
875 if (len > 1)
876 {
877 tmp_msg[len - 1] = '\0';
878 rethrow_error (id.c_str (), "%s\n", tmp_msg);
879 }
880 }
881 else
882 rethrow_error (id.c_str (), "%s", tmp_msg);
883 delete [] tmp_msg;
884
885 // FIXME: is this the right thing to do for Vlast_error_stack?
886 // Should it be saved and restored with unwind_protect?
887
888 Vlast_error_stack = err_stack;
889
890 if (err.contains ("stack"))
891 {
892 if (file.empty ())
893 {
894 if (nm.empty ())
883 { 895 {
884 if (err_stack.contains ("file")) 896 if (l > 0)
885 file = err_stack.contents ("file")(0).string_value ();
886
887 if (err_stack.contains ("name"))
888 nm = err_stack.contents ("name")(0).string_value ();
889
890 if (err_stack.contains ("line"))
891 l = err_stack.contents ("line")(0).nint_value ();
892
893 if (err_stack.contains ("column"))
894 c = err_stack.contents ("column")(0).nint_value ();
895 }
896 }
897
898 // Ugh.
899 char *tmp_msg = strsave (msg.c_str ());
900 if (tmp_msg[len-1] == '\n')
901 {
902 if (len > 1)
903 {
904 tmp_msg[len - 1] = '\0';
905 rethrow_error (id.c_str (), "%s\n", tmp_msg);
906 }
907 }
908 else
909 rethrow_error (id.c_str (), "%s", tmp_msg);
910 delete [] tmp_msg;
911
912 // FIXME: is this the right thing to do for Vlast_error_stack?
913 // Should it be saved and restored with unwind_protect?
914
915 Vlast_error_stack = err_stack;
916
917 if (err.contains ("stack"))
918 {
919 if (file.empty ())
920 {
921 if (nm.empty ())
922 { 897 {
923 if (l > 0) 898 if (c > 0)
924 { 899 pr_where_1 ("error: near line %d, column %d",
925 if (c > 0) 900 l, c);
926 pr_where_1 ("error: near line %d, column %d", 901 else
927 l, c); 902 pr_where_1 ("error: near line %d", l);
928 else
929 pr_where_1 ("error: near line %d", l);
930 }
931 }
932 else
933 {
934 if (l > 0)
935 {
936 if (c > 0)
937 pr_where_1 ("error: called from '%s' near line %d, column %d",
938 nm.c_str (), l, c);
939 else
940 pr_where_1 ("error: called from '%d' near line %d",
941 nm.c_str (), l);
942 }
943 } 903 }
944 } 904 }
945 else 905 else
946 { 906 {
947 if (nm.empty ()) 907 if (l > 0)
948 { 908 {
949 if (l > 0) 909 if (c > 0)
950 { 910 pr_where_1 ("error: called from '%s' near line %d, column %d",
951 if (c > 0) 911 nm.c_str (), l, c);
952 pr_where_1 ("error: in file %s near line %d, column %d", 912 else
953 file.c_str (), l, c); 913 pr_where_1 ("error: called from '%d' near line %d",
954 else 914 nm.c_str (), l);
955 pr_where_1 ("error: in file %s near line %d",
956 file.c_str (), l);
957 }
958 }
959 else
960 {
961 if (l > 0)
962 {
963 if (c > 0)
964 pr_where_1 ("error: called from '%s' in file %s near line %d, column %d",
965 nm.c_str (), file.c_str (), l, c);
966 else
967 pr_where_1 ("error: called from '%d' in file %s near line %d",
968 nm.c_str (), file.c_str (), l);
969 }
970 } 915 }
971 } 916 }
972 } 917 }
918 else
919 {
920 if (nm.empty ())
921 {
922 if (l > 0)
923 {
924 if (c > 0)
925 pr_where_1 ("error: in file %s near line %d, column %d",
926 file.c_str (), l, c);
927 else
928 pr_where_1 ("error: in file %s near line %d",
929 file.c_str (), l);
930 }
931 }
932 else
933 {
934 if (l > 0)
935 {
936 if (c > 0)
937 pr_where_1 ("error: called from '%s' in file %s near line %d, column %d",
938 nm.c_str (), file.c_str (), l, c);
939 else
940 pr_where_1 ("error: called from '%d' in file %s near line %d",
941 nm.c_str (), file.c_str (), l);
942 }
943 }
944 }
973 } 945 }
974 else 946 }
975 error ("rethrow: ERR structure must contain the fields 'message and 'identifier'"); 947 else
976 } 948 error ("rethrow: ERR structure must contain the fields 'message and 'identifier'");
977 } 949 }
978 return retval; 950 return retval;
979 } 951 }
980 952
981 // Determine whether the first argument to error or warning function 953 // Determine whether the first argument to error or warning function
996 968
997 if (nargin > 0) 969 if (nargin > 0)
998 { 970 {
999 std::string arg1 = args(0).string_value (); 971 std::string arg1 = args(0).string_value ();
1000 972
1001 if (! error_state) 973 // For compatibility with Matlab, an identifier must contain
1002 { 974 // ':', but not at the beginning or the end, and it must not
1003 // For compatibility with Matlab, an identifier must contain 975 // contain '%' (even if it is not a valid conversion
1004 // ':', but not at the beginning or the end, and it must not 976 // operator) or whitespace.
1005 // contain '%' (even if it is not a valid conversion 977
1006 // operator) or whitespace. 978 if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos
1007 979 && arg1.find (':') != std::string::npos
1008 if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos 980 && arg1[0] != ':'
1009 && arg1.find (':') != std::string::npos 981 && arg1[arg1.length ()-1] != ':')
1010 && arg1[0] != ':' 982 {
1011 && arg1[arg1.length ()-1] != ':') 983 if (nargin > 1)
1012 { 984 {
1013 if (nargin > 1) 985 id = arg1;
1014 { 986
1015 id = arg1; 987 nargs.resize (nargin-1);
1016 988
1017 nargs.resize (nargin-1); 989 for (int i = 1; i < nargin; i++)
1018 990 nargs(i-1) = args(i);
1019 for (int i = 1; i < nargin; i++)
1020 nargs(i-1) = args(i);
1021 }
1022 else
1023 nargs(0) = "call to " + caller
1024 + " with message identifier requires message";
1025 } 991 }
992 else
993 nargs(0) = "call to " + caller
994 + " with message identifier requires message";
1026 } 995 }
1027 } 996 }
1028 997
1029 return have_fmt; 998 return have_fmt;
1030 } 999 }
1165 // FIXME: also need to handle "stack" field in error structure, 1134 // FIXME: also need to handle "stack" field in error structure,
1166 // but that will require some more significant surgery on 1135 // but that will require some more significant surgery on
1167 // handle_message, error_with_id, etc. 1136 // handle_message, error_with_id, etc.
1168 } 1137 }
1169 else 1138 else
1170 { 1139 have_fmt = maybe_extract_message_id ("error", args, nargs, id);
1171 have_fmt = maybe_extract_message_id ("error", args, nargs, id);
1172
1173 if (error_state)
1174 return retval;
1175 }
1176 1140
1177 handle_message (error_with_id, id.c_str (), "unspecified error", 1141 handle_message (error_with_id, id.c_str (), "unspecified error",
1178 nargs, have_fmt); 1142 nargs, have_fmt);
1179 } 1143 }
1180 1144
1193 1157
1194 Cell ident = warning_options.contents ("identifier"); 1158 Cell ident = warning_options.contents ("identifier");
1195 Cell state = warning_options.contents ("state"); 1159 Cell state = warning_options.contents ("state");
1196 1160
1197 octave_idx_type nel = ident.numel (); 1161 octave_idx_type nel = ident.numel ();
1162
1163 assert (nel != 0);
1198 1164
1199 bool found = false; 1165 bool found = false;
1200 1166
1201 std::string val; 1167 std::string val;
1202 1168
1221 break; 1187 break;
1222 } 1188 }
1223 } 1189 }
1224 } 1190 }
1225 1191
1226 if (found) 1192 // The warning state "all" is always supposed to remain in the list,
1227 { 1193 // so we should always find a state, either explicitly or by using the
1228 retval.assign ("identifier", id); 1194 // state for "all".
1229 retval.assign ("state", val); 1195
1230 } 1196 assert (found);
1231 else 1197
1232 error ("warning: unable to find default warning state!"); 1198 retval.assign ("identifier", id);
1199 retval.assign ("state", val);
1233 1200
1234 return retval; 1201 return retval;
1235 } 1202 }
1236 1203
1237 static std::string 1204 static std::string
1811 @seealso{lasterr, error, lastwarn}\n\ 1778 @seealso{lasterr, error, lastwarn}\n\
1812 @end deftypefn") 1779 @end deftypefn")
1813 { 1780 {
1814 octave_value retval; 1781 octave_value retval;
1815 int nargin = args.length (); 1782 int nargin = args.length ();
1816
1817 unwind_protect frame;
1818
1819 frame.protect_var (error_state);
1820 error_state = 0;
1821 1783
1822 if (nargin < 2) 1784 if (nargin < 2)
1823 { 1785 {
1824 octave_scalar_map err; 1786 octave_scalar_map err;
1825 1787
1851 std::string new_error_file; 1813 std::string new_error_file;
1852 std::string new_error_name; 1814 std::string new_error_name;
1853 int new_error_line = -1; 1815 int new_error_line = -1;
1854 int new_error_column = -1; 1816 int new_error_column = -1;
1855 1817
1856 if (! error_state && new_err.contains ("message")) 1818 if (new_err.contains ("message"))
1857 { 1819 {
1858 const std::string tmp = 1820 const std::string tmp =
1859 new_err.getfield ("message").string_value (); 1821 new_err.getfield ("message").string_value ();
1860 new_error_message = tmp; 1822 new_error_message = tmp;
1861 } 1823 }
1862 1824
1863 if (! error_state && new_err.contains ("identifier")) 1825 if (new_err.contains ("identifier"))
1864 { 1826 {
1865 const std::string tmp = 1827 const std::string tmp =
1866 new_err.getfield ("identifier").string_value (); 1828 new_err.getfield ("identifier").string_value ();
1867 new_error_id = tmp; 1829 new_error_id = tmp;
1868 } 1830 }
1869 1831
1870 if (! error_state && new_err.contains ("stack")) 1832 if (new_err.contains ("stack"))
1871 { 1833 {
1872 new_err_stack = 1834 new_err_stack =
1873 new_err.getfield ("stack").scalar_map_value (); 1835 new_err.getfield ("stack").scalar_map_value ();
1874 1836
1875 if (! error_state && new_err_stack.contains ("file")) 1837 if (new_err_stack.contains ("file"))
1876 { 1838 {
1877 const std::string tmp = 1839 const std::string tmp =
1878 new_err_stack.getfield ("file").string_value (); 1840 new_err_stack.getfield ("file").string_value ();
1879 new_error_file = tmp; 1841 new_error_file = tmp;
1880 } 1842 }
1881 1843
1882 if (! error_state && new_err_stack.contains ("name")) 1844 if (new_err_stack.contains ("name"))
1883 { 1845 {
1884 const std::string tmp = 1846 const std::string tmp =
1885 new_err_stack.getfield ("name").string_value (); 1847 new_err_stack.getfield ("name").string_value ();
1886 new_error_name = tmp; 1848 new_error_name = tmp;
1887 } 1849 }
1888 1850
1889 if (! error_state && new_err_stack.contains ("line")) 1851 if (new_err_stack.contains ("line"))
1890 { 1852 {
1891 const int tmp = 1853 const int tmp =
1892 new_err_stack.getfield ("line").nint_value (); 1854 new_err_stack.getfield ("line").nint_value ();
1893 new_error_line = tmp; 1855 new_error_line = tmp;
1894 } 1856 }
1895 1857
1896 if (! error_state && new_err_stack.contains ("column")) 1858 if (new_err_stack.contains ("column"))
1897 { 1859 {
1898 const int tmp = 1860 const int tmp =
1899 new_err_stack.getfield ("column").nint_value (); 1861 new_err_stack.getfield ("column").nint_value ();
1900 new_error_column = tmp; 1862 new_error_column = tmp;
1901 } 1863 }
1902 } 1864 }
1903 1865
1904 if (! error_state) 1866 Vlast_error_message = new_error_message;
1905 { 1867 Vlast_error_id = new_error_id;
1906 Vlast_error_message = new_error_message; 1868
1907 Vlast_error_id = new_error_id; 1869 if (new_err.contains ("stack"))
1908 1870 {
1909 if (new_err.contains ("stack")) 1871 new_err_stack.setfield ("file", new_error_file);
1910 { 1872 new_err_stack.setfield ("name", new_error_name);
1911 new_err_stack.setfield ("file", new_error_file); 1873 new_err_stack.setfield ("line", new_error_line);
1912 new_err_stack.setfield ("name", new_error_name); 1874 new_err_stack.setfield ("column", new_error_column);
1913 new_err_stack.setfield ("line", new_error_line); 1875 Vlast_error_stack = new_err_stack;
1914 new_err_stack.setfield ("column", new_error_column); 1876 }
1915 Vlast_error_stack = new_err_stack; 1877 else
1916 } 1878 {
1917 else 1879 // No stack field. Fill it in with backtrace info.
1918 { 1880 octave_idx_type curr_frame = -1;
1919 // No stack field. Fill it in with backtrace info. 1881
1920 octave_idx_type curr_frame = -1; 1882 Vlast_error_stack
1921 1883 = octave_call_stack::backtrace (0, curr_frame);
1922 Vlast_error_stack
1923 = octave_call_stack::backtrace (0, curr_frame);
1924 }
1925 } 1884 }
1926 } 1885 }
1927 else 1886 else
1928 error ("lasterror: argument must be a structure or a string"); 1887 error ("lasterror: argument must be a structure or a string");
1929 } 1888 }
1930 1889
1931 if (! error_state) 1890 retval = err;
1932 retval = err;
1933 } 1891 }
1934 else 1892 else
1935 print_usage (); 1893 print_usage ();
1936 1894
1937 return retval; 1895 return retval;
1953 @seealso{lasterror, error, lastwarn}\n\ 1911 @seealso{lasterror, error, lastwarn}\n\
1954 @end deftypefn") 1912 @end deftypefn")
1955 { 1913 {
1956 octave_value_list retval; 1914 octave_value_list retval;
1957 1915
1958 unwind_protect frame;
1959
1960 frame.protect_var (error_state);
1961 error_state = 0;
1962
1963 int argc = args.length () + 1; 1916 int argc = args.length () + 1;
1964 1917
1965 if (argc < 4) 1918 if (argc < 4)
1966 { 1919 {
1967 string_vector argv = args.make_argv ("lasterr"); 1920 string_vector argv = args.make_argv ("lasterr");
1968 1921
1969 if (! error_state) 1922 std::string prev_error_id = Vlast_error_id;
1970 { 1923 std::string prev_error_message = Vlast_error_message;
1971 std::string prev_error_id = Vlast_error_id; 1924
1972 std::string prev_error_message = Vlast_error_message; 1925 if (argc > 2)
1973 1926 Vlast_error_id = argv(2);
1974 if (argc > 2) 1927
1975 Vlast_error_id = argv(2); 1928 if (argc > 1)
1976 1929 Vlast_error_message = argv(1);
1977 if (argc > 1) 1930
1978 Vlast_error_message = argv(1); 1931 if (argc == 1 || nargout > 0)
1979 1932 {
1980 if (argc == 1 || nargout > 0) 1933 retval(1) = prev_error_id;
1981 { 1934 retval(0) = prev_error_message;
1982 retval(1) = prev_error_id; 1935 }
1983 retval(0) = prev_error_message;
1984 }
1985 }
1986 else
1987 error ("lasterr: all arguments must be strings");
1988 } 1936 }
1989 else 1937 else
1990 print_usage (); 1938 print_usage ();
1991 1939
1992 return retval; 1940 return retval;
2014 1962
2015 if (argc < 4) 1963 if (argc < 4)
2016 { 1964 {
2017 string_vector argv = args.make_argv ("lastwarn"); 1965 string_vector argv = args.make_argv ("lastwarn");
2018 1966
2019 if (! error_state) 1967 std::string prev_warning_id = Vlast_warning_id;
2020 { 1968 std::string prev_warning_message = Vlast_warning_message;
2021 std::string prev_warning_id = Vlast_warning_id; 1969
2022 std::string prev_warning_message = Vlast_warning_message; 1970 if (argc > 2)
2023 1971 Vlast_warning_id = argv(2);
2024 if (argc > 2) 1972
2025 Vlast_warning_id = argv(2); 1973 if (argc > 1)
2026 1974 Vlast_warning_message = argv(1);
2027 if (argc > 1) 1975
2028 Vlast_warning_message = argv(1); 1976 if (argc == 1 || nargout > 0)
2029 1977 {
2030 if (argc == 1 || nargout > 0) 1978 retval(1) = prev_warning_id;
2031 { 1979 retval(0) = prev_warning_message;
2032 warning_state = 0; 1980 }
2033 retval(1) = prev_warning_id;
2034 retval(0) = prev_warning_message;
2035 }
2036 }
2037 else
2038 error ("lastwarn: all arguments must be strings");
2039 } 1981 }
2040 else 1982 else
2041 print_usage (); 1983 print_usage ();
2042 1984
2043 return retval; 1985 return retval;
2162 } 2104 }
2163 2105
2164 void 2106 void
2165 interpreter_try (unwind_protect& frame) 2107 interpreter_try (unwind_protect& frame)
2166 { 2108 {
2167 frame.protect_var (error_state);
2168 frame.protect_var (buffer_error_messages); 2109 frame.protect_var (buffer_error_messages);
2169 frame.protect_var (Vdebug_on_error); 2110 frame.protect_var (Vdebug_on_error);
2170 frame.protect_var (Vdebug_on_warning); 2111 frame.protect_var (Vdebug_on_warning);
2171 2112
2172 buffer_error_messages++; 2113 buffer_error_messages++;