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