GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
error.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1993-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cstdarg>
31#include <cstdlib>
32#include <cstring>
33
34#include <algorithm>
35#include <iomanip>
36#include <iostream>
37#include <sstream>
38#include <string>
39
40#include "quit.h"
41
42#include "bp-table.h"
43#include "builtin-defun-decls.h"
44#include "defun.h"
45#include "error.h"
46#include "event-manager.h"
47#include "input.h"
48#include "interpreter-private.h"
49#include "interpreter.h"
50#include "oct-map.h"
51#include "octave.h"
52#include "ov-usr-fcn.h"
53#include "ov.h"
54#include "ovl.h"
55#include "pager.h"
56#include "pt-eval.h"
57#include "unwind-prot.h"
58#include "utils.h"
59#include "variables.h"
60
61static std::string
62format_message (const char *fmt, va_list args)
63{
64 if (! fmt)
65 return "";
66
67 std::ostringstream output_buf;
68
69 octave::vformat (output_buf, fmt, args);
70
71 return output_buf.str ();
72}
73
74OCTAVE_NORETURN
75static void
76error_1 (octave::execution_exception& ee, const char *id, const char *fmt,
77 va_list args)
78{
79 octave::error_system& es = octave::__get_error_system__ ("error_1");
80
81 es.error_1 (ee, id, fmt, args);
82}
83
84OCTAVE_NORETURN
85static void
86error_1 (const char *id, const char *fmt, va_list args)
87{
88 octave::error_system& es = octave::__get_error_system__ ("error_1");
89
90 es.error_1 (id, fmt, args);
91}
92
93static int
94check_state (const std::string& state)
95{
96 // -1: not found
97 // 0: found, "off"
98 // 1: found, "on"
99 // 2: found, "error"
100
101 if (state == "off")
102 return 0;
103 else if (state == "on")
104 return 1;
105 else if (state == "error")
106 return 2;
107 else
108 return -1;
109}
110
111static void
112vwarning (const char *id, const char *fmt, va_list args)
113{
114 octave::error_system& es = octave::__get_error_system__ ("warning");
115
116 es.vwarning (id, fmt, args);
117}
118
119static void
120defun_usage_message (const char *fmt, ...)
121{
122 va_list args;
123 va_start (args, fmt);
124 error_1 ("", fmt, args);
125 va_end (args);
126}
127
128typedef void (*error_fun)(const char *, const char *, ...);
129
130static std::string
131handle_message (error_fun f, const char *id, const char *msg,
132 const octave_value_list& args, bool have_fmt)
133{
134 std::string retval;
135
136 std::string tmpstr;
137
138 if (args.length () > 0)
139 {
140 octave_value arg;
141
142 if (have_fmt)
143 {
144 octave_value_list tmp = octave::Fsprintf (args, 1);
145 arg = tmp(0);
146 }
147 else
148 arg = args(0);
149
150 if (arg.is_defined ())
151 {
152 if (arg.isempty ())
153 return retval;
154 else if (arg.is_string ())
155 {
156 tmpstr = arg.string_value (); // 2-stage assignment required
157 msg = tmpstr.c_str (); // in order to generate pointer
158 // to valid memory.
159 }
160 }
161 }
162
163 // Ugh.
164
165 std::size_t len = strlen (msg);
166
167 if (len > 0)
168 {
169 if (msg[len - 1] == '\n')
170 {
171 if (len > 1)
172 {
173 std::string tmp_msg (msg, len - 1);
174 f (id, "%s\n", tmp_msg.c_str ());
175 retval = tmp_msg;
176 }
177 }
178 else
179 {
180 f (id, "%s", msg);
181 retval = msg;
182 }
183 }
184
185 return retval;
186}
187
188// Determine whether the first argument to error or warning function
189// should be handled as the message identifier or as the format string.
190
191static bool
192maybe_extract_message_id (const std::string& caller,
193 const octave_value_list& args,
194 octave_value_list& nargs,
195 std::string& id)
196{
197 nargs = args;
198 id = "";
199
200 int nargin = args.length ();
201
202 bool have_fmt = nargin > 1;
203
204 if (nargin > 0)
205 {
206 std::string arg1 = args(0).string_value ();
207
208 // For compatibility with Matlab, an identifier must contain ':',
209 // but not at the beginning or the end, and it must not contain '%'
210 // (even if it is not a valid conversion operator) or whitespace.
211
212 if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos
213 && arg1.find (':') != std::string::npos
214 && arg1[0] != ':'
215 && arg1.back () != ':')
216 {
217 if (nargin > 1)
218 {
219 id = arg1;
220
221 nargs.resize (nargin-1);
222
223 for (int i = 1; i < nargin; i++)
224 nargs(i-1) = args(i);
225 }
226 else
227 nargs(0) = "call to " + caller
228 + " with message identifier '" + arg1
229 + "' requires message";
230 }
231 }
232
233 return have_fmt;
234}
235
236OCTAVE_NAMESPACE_BEGIN
237
238 static octave_scalar_map
239 init_warning_options (const std::string& state)
240 {
241 octave_scalar_map initw;
242
243 initw.setfield ("identifier", "all");
244 initw.setfield ("state", state);
245
246 return initw;
247 }
248
249 static octave_map
251 {
252 tree_evaluator& tw = interp.get_evaluator ();
253
254 return tw.empty_backtrace ();
255 }
256
258 : m_interpreter (interp),
259 m_debug_on_error (false),
260 m_debug_on_caught (false),
261 m_debug_on_warning (false),
262 m_discard_warning_messages (false),
263 m_beep_on_error (false),
264 m_backtrace_on_warning (true),
265 m_verbose_warning (false),
266 m_quiet_warning (false),
267 m_warning_options (init_warning_options ("on")),
268 m_last_error_message (),
269 m_last_warning_message (),
270 m_last_warning_id (),
271 m_last_error_id (),
272 m_last_error_stack (init_error_stack (interp))
273 {
275 }
276
279 {
280 return set_internal_variable (m_debug_on_error, args, nargout,
281 "debug_on_error");
282 }
283
286 {
287 return set_internal_variable (m_debug_on_caught, args, nargout,
288 "debug_on_caught");
289 }
290
293 {
294 return set_internal_variable (m_debug_on_warning, args, nargout,
295 "debug_on_warning");
296 }
297
300 int nargout)
301 {
303 "discard_warning_messages");
304 }
305
308 {
309 return set_internal_variable (m_beep_on_error, args, nargout,
310 "beep_on_error");
311 }
312
315 int nargout)
316 {
317 return set_internal_variable (m_backtrace_on_warning, args, nargout,
318 "backtrace_on_warning");
319 }
320
323 {
324 return set_internal_variable (m_verbose_warning, args, nargout,
325 "verbose_warning");
326 }
327
330 {
331 return set_internal_variable (m_quiet_warning, args, nargout,
332 "quiet_warning");
333 }
334
337 {
338 return set_internal_variable (m_last_error_message, args, nargout,
339 "last_error_message");
340 }
341
344 int nargout)
345 {
346 return set_internal_variable (m_last_warning_message, args, nargout,
347 "last_warning_message");
348 }
349
352 {
353 return set_internal_variable (m_last_warning_id, args, nargout,
354 "last_warning_id");
355 }
356
359 {
360 return set_internal_variable (m_last_error_id, args, nargout,
361 "last_error_id");
362 }
363
364 // Use static fields for the best efficiency.
365 // NOTE: C++0x will allow these two to be merged into one.
366 static const char *bt_fieldnames[] =
367 { "file", "name", "line", "column", nullptr };
368
370
372 error_system::make_stack_map (const std::list<frame_info>& frames)
373 {
374 std::size_t nframes = frames.size ();
375
376 octave_map retval (dim_vector (nframes, 1), bt_fields);
377
378 Cell& file = retval.contents (0);
379 Cell& name = retval.contents (1);
380 Cell& line = retval.contents (2);
381 Cell& column = retval.contents (3);
382
383 octave_idx_type k = 0;
384
385 for (const auto& frm : frames)
386 {
387 file(k) = frm.file_name ();
388 name(k) = frm.fcn_name ();
389 line(k) = frm.line ();
390 column(k) = frm.column ();
391
392 k++;
393 }
394
395 return retval;
396 }
397
398 std::list<frame_info>
400 {
401 std::list<frame_info> frames;
402
403 Cell file = stack.contents ("file");
404 Cell name = stack.contents ("name");
405 Cell line = stack.contents ("line");
406 Cell column = stack.contents ("column");
407
408 octave_idx_type nel = name.numel ();
409
410 for (octave_idx_type i = 0; i < nel; i++)
411 frames.push_back (frame_info (file(i).string_value (),
412 name(i).string_value (),
413 line(i).int_value (),
414 column(i).int_value ()));
415
416 return frames;
417 }
418
419 // For given warning ID, return 0 if warnings are disabled, 1 if
420 // enabled, and 2 if the given ID should be an error instead of a
421 // warning.
422
423 int error_system::warning_enabled (const std::string& id)
424 {
425 int retval = 0;
426
427 int all_state = -1;
428 int id_state = -1;
429
430 octave_map opts = warning_options ();
431
432 octave_idx_type nel = opts.numel ();
433
434 if (nel > 0)
435 {
436 Cell identifier = opts.contents ("identifier");
437 Cell state = opts.contents ("state");
438
439 bool all_found = false;
440 bool id_found = false;
441
442 for (octave_idx_type i = 0; i < nel; i++)
443 {
444 octave_value ov = identifier(i);
445 std::string ovs = ov.string_value ();
446
447 if (! all_found && ovs == "all")
448 {
449 all_state = check_state (state(i).string_value ());
450
451 if (all_state >= 0)
452 all_found = true;
453 }
454
455 if (! id_found && ovs == id)
456 {
457 id_state = check_state (state(i).string_value ());
458
459 if (id_state >= 0)
460 id_found = true;
461 }
462
463 if (all_found && id_found)
464 break;
465 }
466 }
467
468 // If "all" is not present, assume warnings are enabled.
469 if (all_state == -1)
470 all_state = 1;
471
472 if (all_state == 0)
473 {
474 if (id_state >= 0)
475 retval = id_state;
476 }
477 else if (all_state == 1)
478 {
479 if (id_state == 0 || id_state == 2)
480 retval = id_state;
481 else
482 retval = all_state;
483 }
484 else if (all_state == 2)
485 {
486 if (id_state == 0)
487 retval= id_state;
488 else
489 retval = all_state;
490 }
491
492 return retval;
493 }
494
495 void error_system::vusage (const char *id, const char *fmt, va_list args)
496 {
497 std::string str_id = id ? id : "";
498 std::string message = format_message (fmt, args);
499
500 throw_error ("usage", id, message);
501 }
502
503 void error_system::vwarning (const char *name, const char *id,
504 const char *fmt, va_list args)
505 {
506 flush_stdout ();
507
508 std::string base_msg = format_message (fmt, args);
509 std::string msg_string;
510
511 if (name)
512 msg_string = std::string (name) + ": ";
513
514 msg_string += base_msg;
515
516 bool fmt_suppresses_backtrace = false;
517 std::size_t fmt_len = (fmt ? strlen (fmt) : 0);
518 fmt_suppresses_backtrace = (fmt_len > 0 && fmt[fmt_len-1] == '\n');
519
520 if (! fmt_suppresses_backtrace)
521 msg_string += '\n';
522
523 last_warning_id (id);
524 last_warning_message (base_msg);
525
527 return;
528
530
531 bool in_user_code = tw.in_user_code ();
532
533 if (! quiet_warning ())
534 {
535 octave_diary << msg_string;
536 std::cerr << msg_string;
537
538 if (! fmt_suppresses_backtrace && in_user_code
541 {
542 std::string bt_msg = tw.backtrace_message ();
543
544 if (! bt_msg.empty ())
545 bt_msg = "warning: called from\n" + bt_msg;
546
547 octave_diary << bt_msg << std::endl;
548 std::cerr << bt_msg << std::endl;
549 }
550 }
551
552 bp_table& bptab = tw.get_bp_table ();
553
556 && debug_on_warning () && in_user_code && bptab.debug_on_warn (id))
557 {
558 unwind_protect_var<bool> restore_var (m_debug_on_warning, false);
559
560 tw.enter_debugger ();
561 }
562 }
563
565 const char *fmt, va_list args)
566 {
567 ee.set_identifier (id);
568 ee.set_message (format_message (fmt, args));
569
570 throw_error (ee);
571 }
572
573 void error_system::error_1 (const char *id, const char *fmt,
574 va_list args)
575 {
576 std::string message = format_message (fmt, args);
577
578 std::list<frame_info> stack_info;
579
580 throw_error ("error", id, message);
581 }
582
583 void error_system::vwarning (const char *id, const char *fmt, va_list args)
584 {
585 int warn_opt = warning_enabled (id);
586
587 if (warn_opt == 2)
588 {
589 // Handle this warning as an error.
590
591 error_1 (id, fmt, args);
592 }
593 else if (warn_opt == 1)
594 vwarning ("warning", id, fmt, args);
595 }
596
597 void error_system::rethrow_error (const std::string& id,
598 const std::string& msg,
599 const octave_map& stack)
600 {
601 std::list<frame_info> stack_info;
602
603 execution_exception ee ("error", id, msg, stack_info);
604
605 if (! stack.isempty ())
606 {
607 if (! (stack.contains ("file") && stack.contains ("name")
608 && stack.contains ("line")))
609 error ("rethrow: STACK struct must contain the fields 'file', 'name', and 'line'");
610
611 if (! stack.contains ("column"))
612 {
613 octave_map new_stack = stack;
614
615 new_stack.setfield ("column", Cell (octave_value (-1)));
616
617 ee.set_stack_info (make_stack_frame_list (new_stack));
618 }
619 else
620 ee.set_stack_info (make_stack_frame_list (stack));
621 }
622
623 throw_error (ee);
624 }
625
626 void error_system::vpanic (const char *fmt, va_list args)
627 {
628 // Is there any point in trying to write the panic message to the
629 // diary?
630
631 std::cerr << "panic: " << format_message (fmt, args) << std::endl;
632
633 abort ();
634 }
635
636 void error_system::panic (const char *fmt, ...)
637 {
638 va_list args;
639 va_start (args, fmt);
640 vpanic (fmt, args);
641 va_end (args);
642 }
643
645 {
646 octave_scalar_map retval;
647
648 std::string id = id_arg;
649
650 if (id == "last")
651 id = last_warning_id ();
652
653 octave_map opts = warning_options ();
654
655 Cell ident = opts.contents ("identifier");
656 Cell state = opts.contents ("state");
657
658 octave_idx_type nel = ident.numel ();
659
660 assert (nel != 0);
661
662 bool found = false;
663
664 std::string val;
665
666 for (octave_idx_type i = 0; i < nel; i++)
667 {
668 if (ident(i).string_value () == id)
669 {
670 val = state(i).string_value ();
671 found = true;
672 break;
673 }
674 }
675
676 if (! found)
677 {
678 for (octave_idx_type i = 0; i < nel; i++)
679 {
680 if (ident(i).string_value () == "all")
681 {
682 val = state(i).string_value ();
683 found = true;
684 break;
685 }
686 }
687 }
688
689 // The warning state "all" is always supposed to remain in the list,
690 // so we should always find a state, either explicitly or by using the
691 // state for "all".
692
693 assert (found);
694
695 retval.assign ("identifier", id);
696 retval.assign ("state", val);
697
698 return retval;
699 }
700
702 {
703 std::string retval = "on";
704
705 octave_map opts = warning_options ();
706
707 Cell ident = opts.contents ("identifier");
708 Cell state = opts.contents ("state");
709
710 octave_idx_type nel = ident.numel ();
711
712 for (octave_idx_type i = 0; i < nel; i++)
713 {
714 if (ident(i).string_value () == "all")
715 {
716 retval = state(i).string_value ();
717 break;
718 }
719 }
720
721 return retval;
722 }
723
725 {
726 octave_map opts = warning_options ();
727
728 Cell ident = opts.contents ("identifier");
729 Cell state = opts.contents ("state");
730
731 octave_idx_type nel = ident.numel ();
732
733 std::string all_state = default_warning_state ();
734
735 if (all_state == "on")
736 os << "By default, warnings are enabled.";
737 else if (all_state == "off")
738 os << "By default, warnings are disabled.";
739 else if (all_state == "error")
740 os << "By default, warnings are treated as errors.";
741 else
743
744 if (nel > 1)
745 {
746 os << "\n";
747 os << "Non-default warning states are:\n\n";
748 os << " State Warning ID\n";
749 }
750
751 // The state for "all" is always supposed to be first in the list.
752
753 for (octave_idx_type i = 1; i < nel; i++)
754 {
755 std::string tid = ident(i).string_value ();
756 std::string tst = state(i).string_value ();
757
758 os << std::setw (7) << tst << " " << tid << "\n";
759 }
760
761 os << std::endl;
762 }
763
764 void error_system::set_warning_option (const std::string& state,
765 const std::string& ident)
766 {
767 std::string all_state = default_warning_state ();
768
769 if (state != "on" && state != "off" && state != "error")
770 error ("invalid warning state: %s", state.c_str ());
771
772 octave_map opts = warning_options ();
773
774 Cell tid = opts.contents ("identifier");
775 Cell tst = opts.contents ("state");
776
777 octave_idx_type nel = tid.numel ();
778
779 for (octave_idx_type i = 0; i < nel; i++)
780 {
781 if (tid(i).string_value () == ident)
782 {
783 // We found it in the current list of options. If the state
784 // for "all" is same as arg1, we can simply remove the item
785 // from the list.
786
787 if (state == all_state && ident != "all")
788 {
789 for (i = i + 1; i < nel; i++)
790 {
791 tid(i-1) = tid(i);
792 tst(i-1) = tst(i);
793 }
794
795 tid.resize (dim_vector (1, nel-1));
796 tst.resize (dim_vector (1, nel-1));
797 }
798 else
799 tst(i) = state;
800
801 opts.clear ();
802
803 opts.assign ("identifier", tid);
804 opts.assign ("state", tst);
805
806 warning_options (opts);
807
808 return;
809 }
810 }
811
812 // The option wasn't already in the list. Append it.
813
814 tid.resize (dim_vector (1, nel+1));
815 tst.resize (dim_vector (1, nel+1));
816
817 tid(nel) = ident;
818 tst(nel) = state;
819
820 opts.clear ();
821
822 opts.assign ("identifier", tid);
823 opts.assign ("state", tst);
824
825 warning_options (opts);
826 }
827
828 void error_system::disable_warning (const std::string& id)
829 {
830 set_warning_option ("off", id);
831 }
832
834 {
836
837 // Most people will want to have the following disabled.
838
839 disable_warning ("Octave:array-as-logical");
840 disable_warning ("Octave:array-to-scalar");
841 disable_warning ("Octave:array-to-vector");
842 disable_warning ("Octave:imag-to-real");
843 disable_warning ("Octave:language-extension");
844 disable_warning ("Octave:missing-semicolon");
845 disable_warning ("Octave:neg-dim-as-zero");
846 disable_warning ("Octave:separator-insert");
847 disable_warning ("Octave:single-quote-string");
848 disable_warning ("Octave:str-to-num");
849 disable_warning ("Octave:mixed-string-concat");
850 disable_warning ("Octave:variable-switch-label");
851 }
852
853 void error_system::interpreter_try (unwind_protect& frame)
854 {
855 frame.protect_var (m_debug_on_error);
856 m_debug_on_error = false;
857
858 frame.protect_var (m_debug_on_warning);
859 m_debug_on_warning = false;
860
861 // Leave debug_on_caught as it was, so errors in try/catch are still
862 // caught.
863 }
864
865 void error_system::throw_error (const std::string& err_type,
866 const std::string& id,
867 const std::string& message,
868 const std::list<frame_info>& stack_info_arg)
869 {
870 std::list<frame_info> stack_info = stack_info_arg;
871
872 if (stack_info.empty ())
873 {
875
876 stack_info = tw.backtrace_info ();
877
878 // Print the error message only if it is different from the
879 // previous one; makes the output more concise and readable.
880
881 stack_info.unique ();
882 }
883
884 execution_exception ex (err_type, id, message, stack_info);
885
886 throw_error (ex);
887 }
888
890 {
891 throw ex;
892 }
893
895 {
896 last_error_id (ee.identifier ());
897 std::string message = ee.message ();
898 std::string xmsg
899 = (message.size () > 0 && message.back () == '\n'
900 ? message.substr (0, message.size () - 1) : message);
901 last_error_message (xmsg);
902 last_error_stack (make_stack_map (ee.stack_info ()));
903 }
904
905 // DEPRECATED in Octave 7.
907 std::ostream& os) const
908 {
909 if (m_beep_on_error)
910 os << "\a";
911
912 ee.display (octave_diary);
913 ee.display (os);
914 }
915
917 {
918 // FIXME: How should we handle beep_on_error?
919
920 ee.display (octave_diary);
921
922 // FIXME: Handle display using an event manager message so that the
923 // GUI or other client can receive error messages without needing to
924 // capture them from std::cerr or some other stream.
925
927
929 }
930
931OCTAVE_NAMESPACE_END
932
933void
934vmessage (const char *name, const char *fmt, va_list args)
935{
936 std::string message;
937
938 if (name)
939 message = std::string (name) + ": ";
940
941 message += format_message (fmt, args);
942
943 octave_diary << message << std::endl;
944 std::cerr << message << std::endl;
945}
946
947void
948message (const char *name, const char *fmt, ...)
949{
950 va_list args;
951 va_start (args, fmt);
952 vmessage (name, fmt, args);
953 va_end (args);
954}
955
956void
957vusage_with_id (const char *id, const char *fmt, va_list args)
958{
959 octave::error_system& es = octave::__get_error_system__ ("warning_enabled");
960
961 es.vusage (id, fmt, args);
962}
963
964void
965usage_with_id (const char *id, const char *fmt, ...)
966{
967 va_list args;
968 va_start (args, fmt);
969 vusage_with_id (id, fmt, args);
970 va_end (args);
971}
972
973void
974verror (const char *fmt, va_list args)
975{
976 error_1 ("", fmt, args);
977}
978
979void
980error (const char *fmt, ...)
981{
982 va_list args;
983 va_start (args, fmt);
984 verror (fmt, args);
985 va_end (args);
986}
987
988void
989verror (octave::execution_exception& ee, const char *fmt, va_list args)
990{
991 error_1 (ee, "", fmt, args);
992}
993
994void
995error (octave::execution_exception& ee, const char *fmt, ...)
996{
997 va_list args;
998 va_start (args, fmt);
999 verror (ee, fmt, args);
1000 va_end (args);
1001}
1002
1003void
1004verror_with_cfn (const char *fmt, va_list args)
1005{
1006 error_1 ("", fmt, args);
1007}
1008
1009void
1010error_with_cfn (const char *fmt, ...)
1011{
1012 va_list args;
1013 va_start (args, fmt);
1014 verror_with_cfn (fmt, args);
1015 va_end (args);
1016}
1017
1018void
1019verror_with_id (const char *id, const char *fmt, va_list args)
1020{
1021 error_1 (id, fmt, args);
1022}
1023
1024void
1025error_with_id (const char *id, const char *fmt, ...)
1026{
1027 va_list args;
1028 va_start (args, fmt);
1029 verror_with_id (id, fmt, args);
1030 va_end (args);
1031}
1032
1033void
1034verror_with_id_cfn (const char *id, const char *fmt, va_list args)
1035{
1036 error_1 (id, fmt, args);
1037}
1038
1039void
1040error_with_id_cfn (const char *id, const char *fmt, ...)
1041{
1042 va_list args;
1043 va_start (args, fmt);
1044 verror_with_id_cfn (id, fmt, args);
1045 va_end (args);
1046}
1047
1048void
1049vwarning (const char *fmt, va_list args)
1050{
1051 vwarning ("", fmt, args);
1052}
1053
1054void
1055warning (const char *fmt, ...)
1056{
1057 va_list args;
1058 va_start (args, fmt);
1059 vwarning (fmt, args);
1060 va_end (args);
1061}
1062
1063void
1064vwarning_with_id (const char *id, const char *fmt, va_list args)
1065{
1066 vwarning (id, fmt, args);
1067}
1068
1069void
1070warning_with_id (const char *id, const char *fmt, ...)
1071{
1072 va_list args;
1073 va_start (args, fmt);
1074 vwarning (id, fmt, args);
1075 va_end (args);
1076}
1077
1078void
1079vparse_error (const char *fmt, va_list args)
1080{
1081 error_1 ("", fmt, args);
1082}
1083
1084void
1085parse_error (const char *fmt, ...)
1086{
1087 va_list args;
1088 va_start (args, fmt);
1089 vparse_error (fmt, args);
1090 va_end (args);
1091}
1092
1093void
1094vparse_error_with_id (const char *id, const char *fmt, va_list args)
1095{
1096 error_1 (id, fmt, args);
1097}
1098
1099void
1100parse_error_with_id (const char *id, const char *fmt, ...)
1101{
1102 va_list args;
1103 va_start (args, fmt);
1104 vparse_error_with_id (id, fmt, args);
1105 va_end (args);
1106}
1107
1108OCTAVE_NORETURN
1109void
1110vpanic (const char *fmt, va_list args)
1111{
1112 octave::error_system& es = octave::__get_error_system__ ("vpanic");
1113
1114 es.vpanic (fmt, args);
1115}
1116
1117OCTAVE_NORETURN
1118void
1119panic (const char *fmt, ...)
1120{
1121 va_list args;
1122 va_start (args, fmt);
1123 vpanic (fmt, args);
1124 va_end (args);
1125}
1126
1127OCTAVE_NAMESPACE_BEGIN
1128
1129void
1130defun_usage_message (const std::string& msg)
1131{
1132 ::defun_usage_message ("%s", msg.c_str ());
1133}
1134
1135DEFMETHOD (rethrow, interp, args, ,
1136 doc: /* -*- texinfo -*-
1137@deftypefn {} {} rethrow (@var{err})
1138Reissue a previous error as defined by @var{err}.
1139
1140@var{err} is a structure that must contain at least the @qcode{"message"}
1141and @qcode{"identifier"} fields. @var{err} can also contain a field
1142@qcode{"stack"} that gives information on the assumed location of the
1143error. Typically @var{err} is returned from @code{lasterror}.
1144@seealso{lasterror, lasterr, error}
1145@end deftypefn */)
1146{
1147 if (args.length () != 1)
1148 print_usage ();
1149
1150 const octave_scalar_map err = args(0).scalar_map_value ();
1151
1152 if (! (err.contains ("message") && err.contains ("identifier")))
1153 error ("rethrow: ERR struct must contain the fields 'message' and 'identifier'");
1154
1155 std::string msg = err.contents ("message").string_value ();
1156 std::string id = err.contents ("identifier").string_value ();
1157
1158 octave_map err_stack = init_error_stack (interp);
1159
1160 if (err.contains ("stack"))
1161 err_stack = err.contents ("stack").xmap_value ("ERR.STACK must be a struct");
1162
1163 error_system& es = interp.get_error_system ();
1164
1165 es.rethrow_error (id, msg, err_stack);
1166
1167 return ovl ();
1168}
1169
1170DEFMETHOD (error, interp, args, ,
1171 doc: /* -*- texinfo -*-
1172@deftypefn {} {} error (@var{template}, @dots{})
1173@deftypefnx {} {} error (@var{id}, @var{template}, @dots{})
1174Display an error message and stop m-file execution.
1175
1176Format the optional arguments under the control of the template string
1177@var{template} using the same rules as the @code{printf} family of
1178functions (@pxref{Formatted Output}) and print the resulting message
1179on the @code{stderr} stream. The message is prefixed by the character
1180string @samp{error: }.
1181
1182Calling @code{error} also sets Octave's internal error state such that
1183control will return to the top level without evaluating any further
1184commands. This is useful for aborting from functions or scripts.
1185
1186If the error message does not end with a newline character, Octave will
1187print a traceback of all the function calls leading to the error. For
1188example, given the following function definitions:
1189
1190@example
1191@group
1192function f () g (); end
1193function g () h (); end
1194function h () nargin == 1 || error ("nargin != 1"); end
1195@end group
1196@end example
1197
1198@noindent
1199calling the function @code{f} will result in a list of messages that
1200can help you to quickly find the exact location of the error:
1201
1202@example
1203@group
1204f ()
1205error: nargin != 1
1206error: called from:
1207error: h at line 1, column 27
1208error: g at line 1, column 15
1209error: f at line 1, column 15
1210@end group
1211@end example
1212
1213If the error message ends in a newline character, Octave will print the
1214message but will not display any traceback messages as it returns
1215control to the top level. For example, modifying the error message
1216in the previous example to end in a newline causes Octave to only print
1217a single message:
1218
1219@example
1220@group
1221function h () nargin == 1 || error ("nargin != 1\n"); end
1222f ()
1223error: nargin != 1
1224@end group
1225@end example
1226
1227A null string ("") input to @code{error} will be ignored and the code
1228will continue running as if the statement were a NOP@. This is for
1229compatibility with @sc{matlab}. It also makes it possible to write code
1230such as
1231
1232@example
1233@group
1234err_msg = "";
1235if (CONDITION 1)
1236 err_msg = "CONDITION 1 found";
1237elseif (CONDITION2)
1238 err_msg = "CONDITION 2 found";
1239@dots{}
1240endif
1241error (err_msg);
1242@end group
1243@end example
1244
1245@noindent
1246which will only stop execution if an error has been found.
1247
1248Implementation Note: For compatibility with @sc{matlab}, escape
1249sequences in @var{template} (e.g., @qcode{"@backslashchar{}n"} =>
1250newline) are processed regardless of whether @var{template} has been defined
1251with single quotes, as long as there are two or more input arguments. To
1252disable escape sequence expansion use a second backslash before the sequence
1253(e.g., @qcode{"@backslashchar{}@backslashchar{}n"}) or use the
1254@code{regexptranslate} function.
1255@seealso{warning, lasterror}
1256@end deftypefn */)
1257{
1258
1259 int nargin = args.length ();
1260
1261 if (nargin == 0)
1262 print_usage ();
1263
1264 octave_value retval;
1265
1266 std::string id;
1267 std::string message;
1268 std::list<frame_info> stack_info;
1269
1270 bool have_fmt = false;
1271
1272 if (nargin == 1 && args(0).isstruct ())
1273 {
1274 // empty struct is not an error. return and resume calling function.
1275 if (args(0).isempty ())
1276 return retval;
1277
1278 octave_scalar_map m = args(0).scalar_map_value ();
1279
1280 // empty struct is not an error. return and resume calling function.
1281 if (m.nfields () == 0)
1282 return retval;
1283
1284 if (m.contains ("message"))
1285 {
1286 octave_value c = m.getfield ("message");
1287
1288 if (c.is_string ())
1289 message = c.string_value ();
1290 }
1291
1292 if (m.contains ("identifier"))
1293 {
1294 octave_value c = m.getfield ("identifier");
1295
1296 if (c.is_string ())
1297 id = c.string_value ();
1298 }
1299
1300 if (m.contains ("stack"))
1301 {
1302 octave_value c = m.getfield ("stack");
1303
1304 if (c.isstruct ())
1305 stack_info
1307 }
1308 }
1309 else
1310 {
1311 octave_value_list nargs = args;
1312
1313 have_fmt = maybe_extract_message_id ("error", args, nargs, id);
1314
1315 if (nargs.length () == 0)
1316 message = "unspecified error";
1317 else
1318 {
1319 octave_value arg;
1320
1321 if (have_fmt)
1322 {
1323 octave_value_list tmp = Fsprintf (nargs, 1);
1324 arg = tmp(0);
1325 }
1326 else
1327 arg = nargs(0);
1328
1329 if (arg.is_defined ())
1330 {
1331 if (arg.isempty ())
1332 message = "";
1333 else if (arg.is_string ())
1334 message = arg.string_value ();
1335 }
1336 }
1337 }
1338
1339 if (message.empty ())
1340 return retval;
1341
1342 error_system& es = interp.get_error_system ();
1343
1344 es.throw_error ("error", id, message, stack_info);
1345
1346 return retval;
1347}
1348
1349DEFMETHOD (warning, interp, args, nargout,
1350 doc: /* -*- texinfo -*-
1351@deftypefn {} {} warning (@var{template}, @dots{})
1352@deftypefnx {} {} warning (@var{id}, @var{template}, @dots{})
1353@deftypefnx {} {} warning ("on", @var{id})
1354@deftypefnx {} {} warning ("off", @var{id})
1355@deftypefnx {} {} warning ("error", @var{id})
1356@deftypefnx {} {} warning ("query", @var{id})
1357@deftypefnx {} {} warning (@var{state}, @var{id}, "local")
1358@deftypefnx {} {} warning (@var{warning_struct})
1359@deftypefnx {} {@var{warning_struct} =} warning (@dots{})
1360@deftypefnx {} {} warning (@var{state}, @var{mode})
1361
1362Display a warning message or control the behavior of Octave's warning system.
1363
1364The first call form uses a template @var{template} and optional additional
1365arguments to display a message on the @code{stderr} stream. The message is
1366formatted using the same rules as the @code{printf} family of functions
1367(@pxref{Formatted Output}) and prefixed by the character string
1368@w{@samp{warning: }}. You should use this function when you want to notify the
1369user of an unusual condition, but only when it makes sense for your program to
1370go on. For example:
1371
1372@example
1373@group
1374warning ("foo: maybe something wrong here");
1375@end group
1376@end example
1377
1378If the warning message does not end with a newline character, Octave will
1379print a traceback of all the function calls leading to the warning. If the
1380warning message does end in a newline character, Octave will suppress the
1381traceback messages as it returns control to the top level. For more details
1382and examples, @pxref{XREFerror,,@code{error}}.
1383
1384The optional warning identifier @var{id} allows users to enable or disable
1385warnings tagged by this identifier. A message identifier is a string of the
1386form @qcode{"NAMESPACE:WARNING-NAME"}. Octave's own warnings use the
1387@qcode{"Octave"} namespace (@pxref{XREFwarning_ids,,@code{warning_ids}}). For
1388example:
1389
1390@example
1391@group
1392warning ("MyNameSpace:check-something",
1393 "foo: maybe something wrong here");
1394@end group
1395@end example
1396
1397The second call form is meant to change and/or query the state of warnings.
1398The first input argument must be a string @var{state} (@qcode{"on"},
1399@qcode{"off"}, @qcode{"error"}, or @qcode{"query"}) followed by an optional
1400warning identifier @var{id} or @qcode{"all"} (default).
1401
1402The optional output argument @var{warning_struct} is a structure or structure
1403array with fields @qcode{"state"} and @qcode{"identifier"}. The @var{state}
1404argument may have the following values:
1405
1406@table @asis
1407@item @qcode{"on"}|@qcode{"off"}:
1408Enable or disable the display of warnings identified by @var{id} and optionally
1409return their previous state @var{stout}.
1410
1411@item @qcode{"error"}:
1412Turn warnings identified by @var{id} into errors and optionally return their
1413previous state @var{stout}.
1414
1415@item @qcode{"query"}:
1416Return the current state of warnings identified by @var{id}.
1417@end table
1418
1419A structure or structure array @var{warning_struct}, with fields
1420@qcode{"state"} and @qcode{"identifier"}, may be given as an input to achieve
1421equivalent results. The following example shows how to temporarily disable a
1422warning and then restore its original state:
1423
1424@example
1425@group
1426loglog (-1:10);
1427## Disable the previous warning and save its original state
1428[~, id] = lastwarn ();
1429warnstate = warning ("off", id);
1430loglog (-1:10);
1431## Restore its original state
1432warning (warnstate);
1433@end group
1434@end example
1435
1436If a final argument @qcode{"local"} is provided then the warning state will be
1437set temporarily until the end of the current function. Changes to warning
1438states that are set locally affect the current function and all functions
1439called from the current scope. The previous warning state is restored on
1440return from the current function. The @qcode{"local"} option is ignored if
1441used in the top-level workspace.
1442
1443With no input argument @code{warning ()} is equivalent to
1444@code{warning ("query", "all")} except that in the absence of an output
1445argument, the state of warnings is displayed on @code{stderr}.
1446
1447The level of verbosity of the warning system may also be controlled by two
1448modes @var{mode}:
1449
1450@table @asis
1451@item @qcode{"backtrace"}:
1452enable/disable the display of the stack trace after the warning message
1453
1454@item @qcode{"verbose"}:
1455enable/disable the display of additional information after the warning message
1456@end table
1457
1458In this case the @var{state} argument may only be @qcode{"on"} or
1459@qcode{"off"}.
1460
1461Implementation Note: For compatibility with @sc{matlab}, escape sequences in
1462@var{template} (e.g., @qcode{"@backslashchar{}n"} => newline) are processed
1463regardless of whether @var{template} has been defined with single quotes, as
1464long as there are two or more input arguments. To disable escape sequence
1465expansion use a second backslash before the sequence (e.g.,
1466@qcode{"@backslashchar{}@backslashchar{}n"}) or use the
1467@code{regexptranslate} function.
1468@seealso{warning_ids, lastwarn, error}
1469@end deftypefn */)
1470{
1471 octave_value retval;
1472
1473 int nargin = args.length ();
1474 bool done = false;
1475
1476 error_system& es = interp.get_error_system ();
1477
1478 if (nargin > 0 && args.all_strings_p ())
1479 {
1480 string_vector argv = args.make_argv ("warning");
1481
1482 std::string arg1 = argv[1];
1483 std::transform (arg1.begin (), arg1.end (), arg1.begin (), tolower);
1484 std::string arg2 = "all";
1485 std::string arg2_lc = "all";
1486
1487 if (nargin >= 2)
1488 {
1489 arg2 = argv[2];
1490 arg2_lc = arg2;
1491 std::transform (arg2_lc.begin (), arg2_lc.end (), arg2_lc.begin (),
1492 tolower);
1493 }
1494
1495 if (arg1 == "on" || arg1 == "off" || arg1 == "error")
1496 {
1497 // Prepare output structure
1498 octave_map old_warning_options;
1499 if (arg2_lc == "all")
1500 old_warning_options = es.warning_options ();
1501 else
1502 old_warning_options = octave_map (es.warning_query (arg2));
1503
1504 if (nargin == 3)
1505 {
1506 std::string arg3_lc = argv[3];
1507 std::transform (arg3_lc.begin (), arg3_lc.end (),
1508 arg3_lc.begin (), tolower);
1509 if (arg3_lc == "local" && ! interp.at_top_level ())
1510 {
1511 octave_scalar_map val = es.warning_query (arg2);
1512
1513 octave_value curr_state = val.contents ("state");
1514
1515 // FIXME: this might be better with a dictionary object.
1516 tree_evaluator& tw = interp.get_evaluator ();
1517
1518 octave_value curr_warning_states
1519 = tw.get_auto_fcn_var (stack_frame::SAVED_WARNING_STATES);
1520
1521 octave_map m;
1522
1523 if (curr_warning_states.is_defined ())
1524 m = curr_warning_states.map_value ();
1525 else
1526 {
1527 string_vector fields (2);
1528
1529 fields(0) = "identifier";
1530 fields(1) = "state";
1531
1532 m = octave_map (dim_vector (0, 1), fields);
1533 }
1534
1535 Cell ids = m.contents ("identifier");
1536 Cell states = m.contents ("state");
1537
1538 octave_idx_type nel = states.numel ();
1539 bool found = false;
1541 for (i = 0; i < nel; i++)
1542 {
1543 std::string id = ids(i).string_value ();
1544
1545 if (id == arg2)
1546 {
1547 states(i) = curr_state;
1548 found = true;
1549 break;
1550 }
1551 }
1552
1553 if (! found)
1554 {
1555 m.resize (dim_vector (nel+1, 1));
1556
1557 ids.resize (dim_vector (nel+1, 1));
1558 states.resize (dim_vector (nel+1, 1));
1559
1560 ids(nel) = arg2;
1561 states(nel) = curr_state;
1562 }
1563
1564 m.contents ("identifier") = ids;
1565 m.contents ("state") = states;
1566
1567 tw.set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, m);
1568
1569 // Now ignore the "local" argument,
1570 // and continue to handle the current setting.
1571 nargin--;
1572 }
1573 }
1574
1575 if ((nargin == 1
1576 && (arg1 == "on" || arg1 == "off" || arg1 == "error"))
1577 || (nargin >= 2 && arg2_lc == "all"))
1578 {
1579 // If "all" is given implicitly or explicitly as ID.
1580 if (arg1 == "error")
1581 error (R"(warning: cannot specify "all" warning ID with state "error")");
1582
1583 octave_map tmp;
1584
1585 Cell id (1, 1);
1586 Cell st (1, 1);
1587
1588 id(0) = "all";
1589 st(0) = arg1;
1590
1591 tmp.assign ("identifier", id);
1592 tmp.assign ("state", st);
1593
1594 es.warning_options (tmp);
1595
1596 done = true;
1597 }
1598 else if (arg2_lc == "backtrace")
1599 {
1600 if (arg1 != "error")
1601 {
1602 es.backtrace_on_warning (arg1 == "on");
1603 done = true;
1604 }
1605 }
1606 else if (arg2_lc == "debug")
1607 {
1608 if (arg1 != "error")
1609 {
1610 es.debug_on_warning (arg1 == "on");
1611 done = true;
1612 }
1613 }
1614 else if (arg2_lc == "verbose")
1615 {
1616 if (arg1 != "error")
1617 {
1618 es.verbose_warning (arg1 == "on");
1619 done = true;
1620 }
1621 }
1622 else if (arg2_lc == "quiet")
1623 {
1624 if (arg1 != "error")
1625 {
1626 es.quiet_warning (arg1 == "on");
1627 done = true;
1628 }
1629 }
1630 else
1631 {
1632 if (arg2_lc == "last")
1633 arg2 = es.last_warning_id ();
1634
1635 es.set_warning_option (arg1, arg2);
1636
1637 done = true;
1638 }
1639
1640 if (done && nargout > 0)
1641 retval = old_warning_options;
1642 }
1643 else if (arg1 == "query")
1644 {
1645 if (arg2_lc == "all")
1646 {
1647 if (nargout > 0)
1648 retval = es.warning_options ();
1649 else
1651 }
1652 else if (arg2_lc == "backtrace" || arg2_lc == "debug"
1653 || arg2_lc == "verbose" || arg2_lc == "quiet")
1654 {
1655 if (nargout > 0)
1656 {
1658 tmp.assign ("identifier", arg2_lc);
1659 if (arg2_lc == "backtrace")
1660 tmp.assign ("state", es.backtrace_on_warning () ? "on" : "off");
1661 else if (arg2_lc == "debug")
1662 tmp.assign ("state", es.debug_on_warning () ? "on" : "off");
1663 else if (arg2_lc == "verbose")
1664 tmp.assign ("state", es.verbose_warning () ? "on" : "off");
1665 else
1666 tmp.assign ("state", es.quiet_warning () ? "on" : "off");
1667
1668 retval = tmp;
1669 }
1670 else
1671 {
1672 if (arg2_lc == "backtrace")
1673 octave_stdout << R"("backtrace" warning state is ")" <<
1674 (es.backtrace_on_warning () ? "on" : "off") <<
1675 "\"\n";
1676 else if (arg2_lc == "debug")
1677 octave_stdout << R"("debug" warning state is ")" <<
1678 (es.debug_on_warning () ? "on" : "off") <<
1679 "\"\n";
1680 else if (arg2_lc == "verbose")
1681 octave_stdout << R"("verbose" warning state is ")" <<
1682 (es.verbose_warning () ? "on" : "off") <<
1683 "\"\n";
1684 else
1685 octave_stdout << R"("quiet" warning state is ")" <<
1686 (es.quiet_warning () ? "on" : "off") <<
1687 "\"\n";
1688 }
1689 }
1690 else
1691 {
1692 if (nargout > 0)
1693 retval = es.warning_query (arg2);
1694 else
1695 {
1696 octave_scalar_map tmp = es.warning_query (arg2);
1697
1698 octave_stdout << '"' << arg2 << R"(" warning state is ")" <<
1699 tmp.getfield ("state").string_value () <<
1700 "\"\n";
1701 }
1702 }
1703
1704 done = true;
1705 }
1706 }
1707 else if (nargin == 0)
1708 {
1709 if (nargout > 0)
1710 retval = es.warning_options ();
1711 else
1713
1714 done = true;
1715 }
1716 else if (nargin == 1)
1717 {
1718 octave_value arg = args(0);
1719
1720 octave_map old_warning_options;
1721
1722 if (arg.isstruct ())
1723 {
1724 octave_map m = arg.map_value ();
1725
1726 if (! m.contains ("identifier") || ! m.contains ("state"))
1727 error ("warning: STATE structure must have fields 'identifier' and 'state'");
1728
1729 // Simply step through the struct elements one at a time.
1730
1731 Cell ident = m.contents ("identifier");
1732 Cell state = m.contents ("state");
1733
1734 octave_idx_type nel = ident.numel ();
1735
1736 // Prepare output structure
1737 old_warning_options = octave_map (m);
1738 Cell oldstate (state);
1739
1740 for (octave_idx_type i = 0; i < nel; i++)
1741 {
1742 std::string tid = ident(i).string_value ();
1743 oldstate(i) = es.warning_query (tid).getfield ("state");
1744 }
1745 old_warning_options.setfield ("state", oldstate);
1746
1747 // Set new values
1748 for (octave_idx_type i = 0; i < nel; i++)
1749 {
1750 std::string tst = state(i).string_value ();
1751 std::string tid = ident(i).string_value ();
1752
1753 es.set_warning_option (tst, tid);
1754 }
1755
1756 done = true;
1757
1758 if (nargout > 0)
1759 retval = old_warning_options;
1760 }
1761 }
1762
1763 if (! done)
1764 {
1765 octave_value_list nargs = args;
1766
1767 std::string id;
1768
1769 bool have_fmt = maybe_extract_message_id ("warning", args, nargs, id);
1770
1771 std::string prev_msg = es.last_warning_message ();
1772
1773 std::string curr_msg = handle_message (warning_with_id, id.c_str (),
1774 "unspecified warning", nargs,
1775 have_fmt);
1776
1777 if (nargout > 0)
1778 retval = prev_msg;
1779 }
1780
1781 return retval;
1782}
1783
1784/*
1785
1786%!test <*51997>
1787%! id = "Octave:logical-conversion";
1788%! current = warning ("query", id);
1789%! current_all = warning ();
1790%! previous = warning (current_all);
1791%! assert (previous, current_all);
1792%! previous = warning (current);
1793%! assert (previous, current);
1794%! previous = warning (current.state, id);
1795%! assert (previous, current);
1796
1797%!test <*57290>
1798%! warning ("oN", "Octave:test-57290-ID");
1799%! warnst = warning ("QUery", "Octave:test-57290-ID");
1800%! assert (warnst.state, "on");
1801%! assert (warnst.identifier, "Octave:test-57290-ID");
1802%! warning ("OFF", "Octave:test-57290-ID");
1803%! warnst = warning ("QUery", "ALL");
1804%! idx = strcmp ({warnst.identifier}, "Octave:test-57290-ID");
1805%! assert (warnst(idx).state, "off");
1806
1807%!error <cannot specify "all" warning ID> warning ("error")
1808
1809*/
1810
1812set_warning_state (const std::string& id, const std::string& state)
1813{
1814 octave_value_list args;
1815
1816 args(1) = id;
1817 args(0) = state;
1818
1819 interpreter& interp = __get_interpreter__ ("set_warning_state");
1820
1821 return Fwarning (interp, args, 1);
1822}
1823
1826{
1827 interpreter& interp = __get_interpreter__ ("set_warning_state");
1828
1829 return Fwarning (interp, args, 1);
1830}
1831
1832int
1833warning_enabled (const std::string& id)
1834{
1835 error_system& es = __get_error_system__ ("warning_enabled");
1836
1837 return es.warning_enabled (id);
1838}
1839
1840void
1841disable_warning (const std::string& id)
1842{
1843 error_system& es = __get_error_system__ ("disable_warning");
1844
1845 es.disable_warning (id);
1846}
1847
1848DEFMETHOD (lasterror, interp, args, ,
1849 doc: /* -*- texinfo -*-
1850@deftypefn {} {@var{lasterr} =} lasterror ()
1851@deftypefnx {} {} lasterror (@var{err})
1852@deftypefnx {} {} lasterror ("reset")
1853Query or set the last error message structure.
1854
1855When called without arguments, return a structure containing the last error
1856message and other information related to this error. The elements of the
1857structure are:
1858
1859@table @code
1860@item message
1861The text of the last error message
1862
1863@item identifier
1864The message identifier of this error message
1865
1866@item stack
1867A structure containing information on where the message occurred. This may
1868be an empty structure if the information cannot be obtained. The fields of
1869the structure are:
1870
1871@table @code
1872@item file
1873The name of the file where the error occurred
1874
1875@item name
1876The name of function in which the error occurred
1877
1878@item line
1879The line number at which the error occurred
1880
1881@item column
1882An optional field with the column number at which the error occurred
1883@end table
1884@end table
1885
1886The last error structure may be set by passing a scalar structure,
1887@var{err}, as input. Any fields of @var{err} that match those above are
1888set while any unspecified fields are initialized with default values.
1889
1890If @code{lasterror} is called with the argument @qcode{"reset"}, all
1891fields are set to their default values.
1892@seealso{lasterr, error, lastwarn}
1893@end deftypefn */)
1894{
1895 int nargin = args.length ();
1896
1897 if (nargin > 1)
1898 print_usage ();
1899
1900 error_system& es = interp.get_error_system ();
1901
1903
1904 err.assign ("message", es.last_error_message ());
1905 err.assign ("identifier", es.last_error_id ());
1906
1907 err.assign ("stack", octave_value (es.last_error_stack ()));
1908
1909 if (nargin == 1)
1910 {
1911 tree_evaluator& tw = interp.get_evaluator ();
1912
1913 if (args(0).is_string ())
1914 {
1915 if (args(0).string_value () != "reset")
1916 error ("lasterror: unrecognized string argument");
1917
1918 es.last_error_message ("");
1919 es.last_error_id ("");
1920
1922 }
1923 else if (args(0).isstruct ())
1924 {
1925 octave_scalar_map new_err = args(0).scalar_map_value ();
1926 octave_scalar_map new_err_stack;
1927 std::string new_error_message;
1928 std::string new_error_id;
1929 std::string new_error_file;
1930 std::string new_error_name;
1931 int new_error_line = -1;
1932 int new_error_column = -1;
1933 bool initialize_stack = false;
1934
1935 if (new_err.contains ("message"))
1936 {
1937 const std::string tmp
1938 = new_err.getfield ("message").string_value ();
1939 new_error_message = tmp;
1940 }
1941
1942 if (new_err.contains ("identifier"))
1943 {
1944 const std::string tmp
1945 = new_err.getfield ("identifier").string_value ();
1946 new_error_id = tmp;
1947 }
1948
1949 if (new_err.contains ("stack"))
1950 {
1951 if (new_err.getfield ("stack").isempty ())
1952 initialize_stack = true;
1953 else
1954 {
1955 new_err_stack
1956 = new_err.getfield ("stack").scalar_map_value ();
1957
1958 if (new_err_stack.contains ("file"))
1959 {
1960 const std::string tmp
1961 = new_err_stack.getfield ("file").string_value ();
1962 new_error_file = tmp;
1963 }
1964
1965 if (new_err_stack.contains ("name"))
1966 {
1967 const std::string tmp
1968 = new_err_stack.getfield ("name").string_value ();
1969 new_error_name = tmp;
1970 }
1971
1972 if (new_err_stack.contains ("line"))
1973 {
1974 const int tmp
1975 = new_err_stack.getfield ("line").nint_value ();
1976 new_error_line = tmp;
1977 }
1978
1979 if (new_err_stack.contains ("column"))
1980 {
1981 const int tmp
1982 = new_err_stack.getfield ("column").nint_value ();
1983 new_error_column = tmp;
1984 }
1985 }
1986 }
1987
1988 es.last_error_message (new_error_message);
1989 es.last_error_id (new_error_id);
1990
1991 if (initialize_stack)
1993 else if (new_err.contains ("stack"))
1994 {
1995 new_err_stack.setfield ("file", new_error_file);
1996 new_err_stack.setfield ("name", new_error_name);
1997 new_err_stack.setfield ("line", new_error_line);
1998 new_err_stack.setfield ("column", new_error_column);
1999
2000 es.last_error_stack (new_err_stack);
2001 }
2002 else
2003 es.last_error_stack (tw.backtrace ());
2004 }
2005 else
2006 error ("lasterror: argument must be a structure or a string");
2007 }
2008
2009 return ovl (err);
2010}
2011
2012/*
2013## Test lasterror with empty error state
2014%!test
2015%! lasterror ("reset");
2016%! x = lasterror ();
2017%! assert (x.identifier, "")
2018%! assert (x.message, "")
2019%! assert (isempty (x.stack))
2020%! lasterror (x);
2021%! y = lasterror ();
2022%! assert (y, x);
2023*/
2024
2025DEFMETHOD (lasterr, interp, args, nargout,
2026 doc: /* -*- texinfo -*-
2027@deftypefn {} {[@var{msg}, @var{msgid}] =} lasterr ()
2028@deftypefnx {} {} lasterr (@var{msg})
2029@deftypefnx {} {} lasterr (@var{msg}, @var{msgid})
2030Query or set the last error message.
2031
2032When called without input arguments, return the last error message and
2033message identifier.
2034
2035With one argument, set the last error message to @var{msg}.
2036
2037With two arguments, also set the last message identifier.
2038@seealso{lasterror, error, lastwarn}
2039@end deftypefn */)
2040{
2041 int nargin = args.length ();
2042
2043 if (nargin > 2)
2044 print_usage ();
2045
2046 error_system& es = interp.get_error_system ();
2047
2048 string_vector argv = args.make_argv ("lasterr");
2049
2050 std::string prev_error_id = es.last_error_id ();
2051 std::string prev_error_message = es.last_error_message ();
2052
2053 if (nargin == 2)
2054 {
2055 es.last_error_id (argv[2]);
2056 es.last_error_message (argv[1]);
2057 }
2058 else if (nargin == 1)
2059 {
2060 es.last_error_id ("");
2061 es.last_error_message (argv[1]);
2062 }
2063
2064 if (nargin == 0 || nargout > 0)
2065 return ovl (prev_error_message, prev_error_id);
2066 else
2067 return ovl ();
2068}
2069
2070DEFMETHOD (lastwarn, interp, args, nargout,
2071 doc: /* -*- texinfo -*-
2072@deftypefn {} {[@var{msg}, @var{msgid}] =} lastwarn ()
2073@deftypefnx {} {} lastwarn (@var{msg})
2074@deftypefnx {} {} lastwarn (@var{msg}, @var{msgid})
2075Query or set the last warning message.
2076
2077When called without input arguments, return the last warning message and
2078message identifier.
2079
2080With one argument, set the last warning message to @var{msg}.
2081
2082With two arguments, also set the last message identifier.
2083@seealso{warning, lasterror, lasterr}
2084@end deftypefn */)
2085{
2086 int nargin = args.length ();
2087
2088 if (nargin > 2)
2089 print_usage ();
2090
2091 error_system& es = interp.get_error_system ();
2092
2093 string_vector argv = args.make_argv ("lastwarn");
2094
2095 std::string prev_warning_id = es.last_warning_id ();
2096 std::string prev_warning_message = es.last_warning_message ();
2097
2098 if (nargin == 2)
2099 {
2100 es.last_warning_id (argv[2]);
2101 es.last_warning_message (argv[1]);
2102 }
2103 else if (nargin == 1)
2104 {
2105 es.last_warning_id ("");
2106 es.last_warning_message (argv[1]);
2107 }
2108
2109 if (nargin == 0 || nargout > 0)
2110 return ovl (prev_warning_message, prev_warning_id);
2111 else
2112 return ovl ();
2113}
2114
2115DEFMETHOD (beep_on_error, interp, args, nargout,
2116 doc: /* -*- texinfo -*-
2117@deftypefn {} {@var{val} =} beep_on_error ()
2118@deftypefnx {} {@var{old_val} =} beep_on_error (@var{new_val})
2119@deftypefnx {} {} beep_on_error (@var{new_val}, "local")
2120Query or set the internal variable that controls whether Octave will try
2121to ring the terminal bell before printing an error message.
2122
2123When called from inside a function with the @qcode{"local"} option, the
2124variable is changed locally for the function and any subroutines it calls.
2125The original variable value is restored when exiting the function.
2126@end deftypefn */)
2127{
2128 error_system& es = interp.get_error_system ();
2129
2130 return es.beep_on_error (args, nargout);
2131}
2132
2133DEFMETHOD (debug_on_error, interp, args, nargout,
2134 doc: /* -*- texinfo -*-
2135@deftypefn {} {@var{val} =} debug_on_error ()
2136@deftypefnx {} {@var{old_val} =} debug_on_error (@var{new_val})
2137@deftypefnx {} {} debug_on_error (@var{new_val}, "local")
2138Query or set the internal variable that controls whether Octave will try
2139to enter the debugger when an error is encountered.
2140
2141This will also inhibit printing of the normal traceback message (you will
2142only see the top-level error message).
2143
2144When called from inside a function with the @qcode{"local"} option, the
2145variable is changed locally for the function and any subroutines it calls.
2146The original variable value is restored when exiting the function.
2147@seealso{debug_on_warning, debug_on_interrupt}
2148@end deftypefn */)
2149{
2150 error_system& es = interp.get_error_system ();
2151
2152 return es.debug_on_error (args, nargout);
2153}
2154
2155DEFMETHOD (debug_on_warning, interp, args, nargout,
2156 doc: /* -*- texinfo -*-
2157@deftypefn {} {@var{val} =} debug_on_warning ()
2158@deftypefnx {} {@var{old_val} =} debug_on_warning (@var{new_val})
2159@deftypefnx {} {} debug_on_warning (@var{new_val}, "local")
2160Query or set the internal variable that controls whether Octave will try
2161to enter the debugger when a warning is encountered.
2162
2163When called from inside a function with the @qcode{"local"} option, the
2164variable is changed locally for the function and any subroutines it calls.
2165The original variable value is restored when exiting the function.
2166@seealso{debug_on_error, debug_on_interrupt}
2167@end deftypefn */)
2168{
2169 error_system& es = interp.get_error_system ();
2170
2171 return es.debug_on_warning (args, nargout);
2172}
2173
2174void
2175interpreter_try (unwind_protect& frame)
2176{
2177 error_system& es = __get_error_system__ ("interpreter_try");
2178
2179 es.interpreter_try (frame);
2180}
2181
2182OCTAVE_NAMESPACE_END
2183
2184// Deprecated variables and functions.
2185
2186// This variable is obsolete and always has the value 0.
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:411
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1010
Definition: Cell.h:43
Cell column(octave_idx_type i) const
Definition: Cell.cc:303
static bool forced_interactive(void)
Definition: octave.cc:325
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
bool m_backtrace_on_warning
TRUE means that Octave will try to display a stack trace when a warning is encountered.
Definition: error.h:374
bool quiet_warning(void) const
Definition: error.h:166
OCTINTERP_API error_system(interpreter &interp)
Definition: error.cc:257
OCTINTERP_API void initialize_default_warning_state(void)
Definition: error.cc:833
OCTINTERP_API octave_value beep_on_error(const octave_value_list &args, int nargout)
Definition: error.cc:307
bool m_discard_warning_messages
TRUE means warning messages are turned off.
Definition: error.h:366
std::string m_last_error_id
The last error message id.
Definition: error.h:397
bool backtrace_on_warning(void) const
Definition: error.h:138
OCTINTERP_API void interpreter_try(unwind_protect &frame)
Definition: error.cc:853
OCTINTERP_API void display_warning_options(std::ostream &os)
Definition: error.cc:724
std::string last_error_message(void) const
Definition: error.h:194
static OCTINTERP_API std::list< frame_info > make_stack_frame_list(const octave_map &stack)
Definition: error.cc:399
OCTINTERP_API octave_value last_error_id(const octave_value_list &args, int nargout)
Definition: error.cc:358
OCTAVE_NORETURN OCTINTERP_API void error_1(execution_exception &ee, const char *id, const char *fmt, va_list args)
Definition: error.cc:564
OCTAVE_NORETURN OCTINTERP_API void vpanic(const char *fmt, va_list args)
Definition: error.cc:626
OCTINTERP_API octave_value quiet_warning(const octave_value_list &args, int nargout)
Definition: error.cc:329
std::string m_last_error_message
The text of the last error message.
Definition: error.h:388
OCTINTERP_API void set_warning_option(const std::string &state, const std::string &id)
Definition: error.cc:764
bool debug_on_caught(void) const
Definition: error.h:76
OCTAVE_NORETURN OCTINTERP_API void rethrow_error(const std::string &id, const std::string &msg, const octave_map &stack)
Definition: error.cc:597
OCTINTERP_API octave_scalar_map warning_query(const std::string &id_arg)
Definition: error.cc:644
octave_map warning_options(void) const
Definition: error.h:175
OCTINTERP_API octave_value backtrace_on_warning(const octave_value_list &args, int nargout)
Definition: error.cc:314
std::string last_error_id(void) const
Definition: error.h:236
OCTINTERP_API octave_value last_warning_message(const octave_value_list &args, int nargout)
Definition: error.cc:343
OCTAVE_NORETURN OCTINTERP_API void throw_error(const std::string &err_type, const std::string &id, const std::string &message, const std::list< frame_info > &stack_info=std::list< frame_info >())
Definition: error.cc:865
std::string last_warning_id(void) const
Definition: error.h:222
OCTINTERP_API int warning_enabled(const std::string &id)
For given warning ID, return 0 if warnings are disabled, 1 if enabled, and 2 if the given ID should b...
Definition: error.cc:423
std::string m_last_warning_id
The last warning message id.
Definition: error.h:394
static OCTINTERP_API octave_map make_stack_map(const std::list< frame_info > &frames)
Definition: error.cc:372
bool beep_on_error(void) const
Definition: error.h:124
bool discard_warning_messages(void) const
Definition: error.h:107
OCTAVE_NORETURN OCTINTERP_API void vusage(const char *id, const char *fmt, va_list args)
Definition: error.cc:495
OCTINTERP_API octave_value debug_on_warning(const octave_value_list &args, int nargout)
Definition: error.cc:292
OCTINTERP_API octave_value verbose_warning(const octave_value_list &args, int nargout)
Definition: error.cc:322
bool m_debug_on_caught
TRUE means that Octave will try to enter the debugger when an error is encountered within the 'try' s...
Definition: error.h:357
bool m_debug_on_warning
TRUE means that Octave will try to enter the debugger when a warning is encountered.
Definition: error.h:362
OCTINTERP_API void display_exception(const execution_exception &ee, std::ostream &os) const
Definition: error.cc:906
OCTINTERP_API void disable_warning(const std::string &id)
Definition: error.cc:828
OCTINTERP_API void vwarning(const char *name, const char *id, const char *fmt, va_list args)
Definition: error.cc:503
bool debug_on_warning(void) const
Definition: error.h:90
OCTINTERP_API octave_value last_warning_id(const octave_value_list &args, int nargout)
Definition: error.cc:351
bool debug_on_error(void) const
Definition: error.h:62
OCTINTERP_API void save_exception(const execution_exception &ee)
Definition: error.cc:894
OCTINTERP_API octave_value debug_on_error(const octave_value_list &args, int nargout)
Definition: error.cc:278
bool m_beep_on_error
TRUE means that Octave will try to beep obnoxiously before printing error messages.
Definition: error.h:370
std::string last_warning_message(void) const
Definition: error.h:208
OCTINTERP_API octave_value last_error_message(const octave_value_list &args, int nargout)
Definition: error.cc:336
bool m_debug_on_error
TRUE means that Octave will try to enter the debugger when an error is encountered.
Definition: error.h:352
interpreter & m_interpreter
Definition: error.h:346
bool m_quiet_warning
TRUE means that Octave will print no warnings, but lastwarn will be updated.
Definition: error.h:382
bool m_verbose_warning
TRUE means that Octave will print a verbose warning.
Definition: error.h:378
octave_map last_error_stack(void) const
Definition: error.h:250
OCTINTERP_API std::string default_warning_state(void)
Definition: error.cc:701
OCTAVE_NORETURN OCTINTERP_API void panic(const char *fmt,...)
Definition: error.cc:636
std::string m_last_warning_message
The text of the last warning message.
Definition: error.h:391
bool verbose_warning(void) const
Definition: error.h:152
Provides threadsafe access to octave.
bool display_exception(const execution_exception &ee, bool beep=false)
tree_evaluator & get_evaluator(void)
event_manager & get_event_manager(void)
Definition: interpreter.h:328
bool interactive(void) const
Definition: interpreter.h:171
void resize(const dim_vector &dv, bool fill=false)
Definition: oct-map.cc:576
const Cell & contents(const_iterator p) const
Definition: oct-map.h:331
void setfield(const std::string &key, const Cell &val)
Definition: oct-map.cc:282
octave_idx_type numel(void) const
Definition: oct-map.h:389
bool contains(const std::string &name) const
Definition: oct-map.h:350
void assign(const std::string &k, const Cell &val)
Definition: oct-map.h:365
void clear(void)
Definition: oct-map.h:382
bool isempty(void) const
Definition: oct-map.h:391
const octave_value & contents(const_iterator p) const
Definition: oct-map.h:205
bool contains(const std::string &name) const
Definition: oct-map.h:224
octave_idx_type nfields(void) const
Definition: oct-map.h:218
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:190
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:238
octave_value getfield(const std::string &key) const
Definition: oct-map.cc:183
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
Definition: ovl.h:117
octave_idx_type length(void) const
Definition: ovl.h:113
OCTINTERP_API octave_scalar_map scalar_map_value(void) const
OCTINTERP_API octave_map xmap_value(const char *fmt,...) const
bool is_string(void) const
Definition: ov.h:682
bool is_defined(void) const
Definition: ov.h:637
bool isstruct(void) const
Definition: ov.h:694
std::string string_value(bool force=false) const
Definition: ov.h:1019
int nint_value(bool frc_str_conv=false) const
Definition: ov.h:864
bool isempty(void) const
Definition: ov.h:646
OCTINTERP_API octave_map map_value(void) const
OCTINTERP_API octave_idx_type length(void) const
octave_map empty_backtrace(void) const
Definition: pt-eval.cc:2606
octave_value get_auto_fcn_var(stack_frame::auto_var_type avt) const
Definition: pt-eval.cc:2204
octave_map backtrace(octave_idx_type &curr_user_frame, bool print_subfn=true) const
Definition: pt-eval.cc:2595
bp_table & get_bp_table(void)
Definition: pt-eval.h:416
bool in_user_code(void) const
Definition: pt-eval.cc:2964
std::string backtrace_message(void) const
Definition: pt-eval.cc:2611
std::list< frame_info > backtrace_info(octave_idx_type &curr_user_frame, bool print_subfn=true) const
Definition: pt-eval.cc:2583
void set_auto_fcn_var(stack_frame::auto_var_type avt, const octave_value &val=octave_value())
Definition: pt-eval.cc:2197
void enter_debugger(const std::string &prompt="debug> ")
Definition: pt-eval.cc:1377
OCTINTERP_API void print_usage(void)
Definition: defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:111
void interpreter_try(unwind_protect &frame)
Definition: error.cc:2175
void error_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1025
static const octave_fields bt_fields(bt_fieldnames)
static int check_state(const std::string &state)
Definition: error.cc:94
void usage_with_id(const char *id, const char *fmt,...)
Definition: error.cc:965
void warning(const char *fmt,...)
Definition: error.cc:1055
OCTAVE_NAMESPACE_END int error_state
Definition: error.cc:2187
OCTAVE_NORETURN void panic(const char *fmt,...)
Definition: error.cc:1119
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1070
void verror_with_id_cfn(const char *id, const char *fmt, va_list args)
Definition: error.cc:1034
void parse_error_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1100
OCTAVE_EXPORT octave_value_list Fwarning(octave::interpreter &interp, const octave_value_list &args, int nargout)
Definition: error.cc:1469
static OCTAVE_NORETURN void error_1(octave::execution_exception &ee, const char *id, const char *fmt, va_list args)
Definition: error.cc:76
OCTAVE_NAMESPACE_END void vmessage(const char *name, const char *fmt, va_list args)
Definition: error.cc:934
static void vwarning(const char *id, const char *fmt, va_list args)
Definition: error.cc:112
OCTAVE_NORETURN void vpanic(const char *fmt, va_list args)
Definition: error.cc:1110
static std::string handle_message(error_fun f, const char *id, const char *msg, const octave_value_list &args, bool have_fmt)
Definition: error.cc:131
void error_with_id_cfn(const char *id, const char *fmt,...)
Definition: error.cc:1040
void vwarning_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:1064
void verror(const char *fmt, va_list args)
Definition: error.cc:974
void verror_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:1019
static const char * bt_fieldnames[]
Definition: error.cc:366
void vusage_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:957
void verror_with_cfn(const char *fmt, va_list args)
Definition: error.cc:1004
void error_with_cfn(const char *fmt,...)
Definition: error.cc:1010
static OCTAVE_NAMESPACE_BEGIN octave_scalar_map init_warning_options(const std::string &state)
Definition: error.cc:239
void vparse_error_with_id(const char *id, const char *fmt, va_list args)
Definition: error.cc:1094
void parse_error(const char *fmt,...)
Definition: error.cc:1085
static void defun_usage_message(const char *fmt,...)
Definition: error.cc:120
void error(const char *fmt,...)
Definition: error.cc:980
static std::string format_message(const char *fmt, va_list args)
Definition: error.cc:62
void vparse_error(const char *fmt, va_list args)
Definition: error.cc:1079
static octave_map init_error_stack(interpreter &interp)
Definition: error.cc:250
static bool maybe_extract_message_id(const std::string &caller, const octave_value_list &args, octave_value_list &nargs, std::string &id)
Definition: error.cc:192
void message(const char *name, const char *fmt,...)
Definition: error.cc:948
octave_value_list set_warning_state(const std::string &id, const std::string &state)
Definition: error.cc:1812
void(* error_fun)(const char *, const char *,...)
Definition: error.cc:128
void disable_warning(const std::string &id)
Definition: error.cc:1841
int warning_enabled(const std::string &id)
Definition: error.cc:1833
#define panic_impossible()
Definition: error.h:411
OCTAVE_EXPORT octave_value_list Fsprintf(const octave_value_list &args, int)
Definition: file-io.cc:942
ColumnVector transform(const Matrix &m, double x, double y, double z)
Definition: graphics.cc:5861
QString name
F77_RET_T const F77_DBLE const F77_DBLE * f
error_system & __get_error_system__(const std::string &who)
static uint32_t state[624]
Definition: randmtzig.cc:192
interpreter & __get_interpreter__(const std::string &who)
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:85
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
void flush_stdout(void)
Definition: pager.cc:260
#define octave_stdout
Definition: pager.h:314
#define octave_diary
Definition: pager.h:316
std::size_t vformat(std::ostream &os, const char *fmt, va_list args)
Definition: utils.cc:1485
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:587
F77_RET_T len
Definition: xerbla.cc:61