changelog shortlog tags changeset files revisions annotate raw

src/error.cc

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