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