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