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