Mercurial > octave-nkf
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++; |