comparison src/error.cc @ 5567:80e629357483

[project @ 2005-12-07 06:31:28 by jwe]
author jwe
date Wed, 07 Dec 2005 06:31:28 +0000
parents a892ee7ac114
children 6bf56668b01a
comparison
equal deleted inserted replaced
5566:2f5d0d8a7f13 5567:80e629357483
35 #include "defun.h" 35 #include "defun.h"
36 #include "error.h" 36 #include "error.h"
37 #include "input.h" 37 #include "input.h"
38 #include "pager.h" 38 #include "pager.h"
39 #include "oct-obj.h" 39 #include "oct-obj.h"
40 #include "oct-map.h"
40 #include "utils.h" 41 #include "utils.h"
41 #include "ov.h" 42 #include "ov.h"
42 #include "ov-usr-fcn.h" 43 #include "ov-usr-fcn.h"
43 #include "pt-pr-code.h" 44 #include "pt-pr-code.h"
44 #include "pt-stmt.h" 45 #include "pt-stmt.h"
57 58
58 // TRUE means that Octave will try to enter the debugger when a warning 59 // TRUE means that Octave will try to enter the debugger when a warning
59 // is encountered. 60 // is encountered.
60 static bool Vdebug_on_warning; 61 static bool Vdebug_on_warning;
61 62
63 // TRUE means that Octave will try to display a stack trace when a
64 // warning is encountered.
65 static bool Vbacktrace_on_warning = false;
66
67 // TRUE means that Octave will print a verbose warning. Currently unused.
68 static bool Vverbose_warning;
69
70 // A structure containing (most of) the current state of warnings.
71 static Octave_map warning_options;
72
62 // The text of the last error message. 73 // The text of the last error message.
63 static std::string Vlast_error_message; 74 static std::string Vlast_error_message;
64 75
65 // The text of the last warning message. 76 // The text of the last warning message.
66 static std::string Vlast_warning_message; 77 static std::string Vlast_warning_message;
67 78
68 // The warning frequency for Matlab handle graphics backwards 79 // The last warning message id.
69 // compatibility warnings (currently not used). 80 static std::string Vlast_warning_id;
70 static std::string Vwarning_frequency = "once"; 81
71 82 // The last error message id.
72 // The current warning state. Valid values are "on", "off", 83 static std::string Vlast_error_id;
73 // "backtrace", or "debug".
74 std::string Vwarning_option = "backtrace";
75 84
76 // Current error state. 85 // Current error state.
77 // 86 //
78 // Valid values: 87 // Valid values:
79 // 88 //
114 warning_state = 0; 123 warning_state = 0;
115 buffer_error_messages = 0; 124 buffer_error_messages = 0;
116 discard_error_messages = false; 125 discard_error_messages = false;
117 } 126 }
118 127
128 static void
129 init_warning_options (const std::string& state = "on")
130 {
131 warning_options.clear ();
132
133 warning_options.assign ("identifier", "all");
134 warning_options.assign ("state", state);
135 }
136
119 // Warning messages are never buffered. 137 // Warning messages are never buffered.
120 138
121 static void 139 static void
122 vwarning (const char *name, const char *fmt, va_list args) 140 vwarning (const char *name, const char *id, const char *fmt, va_list args)
123 { 141 {
124 if (discard_warning_messages) 142 if (discard_warning_messages)
125 return; 143 return;
126 144
127 flush_octave_stdout (); 145 flush_octave_stdout ();
144 OSSTREAM_FREEZE (output_buf); 162 OSSTREAM_FREEZE (output_buf);
145 163
146 if (! warning_state) 164 if (! warning_state)
147 { 165 {
148 // This is the first warning in a possible series. 166 // This is the first warning in a possible series.
167
168 Vlast_warning_id = id;
149 Vlast_warning_message = msg_string; 169 Vlast_warning_message = msg_string;
150 } 170 }
151 171
152 octave_diary << msg_string; 172 octave_diary << msg_string;
153 173
154 std::cerr << msg_string; 174 std::cerr << msg_string;
155 } 175 }
156 176
157 static void 177 static void
158 verror (bool save_last_error, std::ostream& os, 178 verror (bool save_last_error, std::ostream& os,
159 const char *name, const char *fmt, va_list args) 179 const char *name, const char *id, const char *fmt, va_list args)
160 { 180 {
161 if (discard_error_messages) 181 if (discard_error_messages)
162 return; 182 return;
163 183
164 if (! buffer_error_messages) 184 if (! buffer_error_messages)
187 OSSTREAM_FREEZE (output_buf); 207 OSSTREAM_FREEZE (output_buf);
188 208
189 if (! error_state && save_last_error) 209 if (! error_state && save_last_error)
190 { 210 {
191 // This is the first error in a possible series. 211 // This is the first error in a possible series.
212
213 Vlast_error_id = id;
192 Vlast_error_message = msg_string; 214 Vlast_error_message = msg_string;
193 } 215 }
194 216
195 if (buffer_error_messages) 217 if (buffer_error_messages)
196 { 218 {
225 // Note that we don't actually print any message if the error string 247 // Note that we don't actually print any message if the error string
226 // is just "" or "\n". This allows error ("") and error ("\n") to 248 // is just "" or "\n". This allows error ("") and error ("\n") to
227 // just set the error state. 249 // just set the error state.
228 250
229 static void 251 static void
230 error_1 (std::ostream& os, const char *name, const char *fmt, va_list args) 252 error_1 (std::ostream& os, const char *name, const char *id,
253 const char *fmt, va_list args)
231 { 254 {
232 if (error_state != -2) 255 if (error_state != -2)
233 { 256 {
234 if (fmt) 257 if (fmt)
235 { 258 {
240 { 263 {
241 if (len > 1) 264 if (len > 1)
242 { 265 {
243 char *tmp_fmt = strsave (fmt); 266 char *tmp_fmt = strsave (fmt);
244 tmp_fmt[len - 1] = '\0'; 267 tmp_fmt[len - 1] = '\0';
245 verror (true, os, name, tmp_fmt, args); 268 verror (true, os, name, id, tmp_fmt, args);
246 delete [] tmp_fmt; 269 delete [] tmp_fmt;
247 } 270 }
248 271
249 error_state = -2; 272 error_state = -2;
250 } 273 }
251 else 274 else
252 verror (true, os, name, fmt, args); 275 verror (true, os, name, id, fmt, args);
253 } 276 }
254 } 277 }
255 else 278 else
256 panic ("error_1: invalid format"); 279 panic ("error_1: invalid format");
257 280
263 void 286 void
264 message (const char *name, const char *fmt, ...) 287 message (const char *name, const char *fmt, ...)
265 { 288 {
266 va_list args; 289 va_list args;
267 va_start (args, fmt); 290 va_start (args, fmt);
268 verror (false, std::cerr, name, fmt, args); 291 verror (false, std::cerr, name, "", fmt, args);
269 va_end (args); 292 va_end (args);
270 } 293 }
271 294
272 void 295 void
273 usage (const char *fmt, ...) 296 message_with_id (const char *name, const char *id, const char *fmt, ...)
274 { 297 {
275 va_list args; 298 va_list args;
276 va_start (args, fmt); 299 va_start (args, fmt);
277 verror (true, std::cerr, "usage", fmt, args); 300 verror (false, std::cerr, name, id, fmt, args);
301 va_end (args);
302 }
303
304 void
305 usage_1 (const char *id, const char *fmt, va_list args)
306 {
307 verror (true, std::cerr, "usage", id, fmt, args);
278 error_state = -1; 308 error_state = -1;
309 }
310
311 void
312 usage (const char *fmt, ...)
313 {
314 va_list args;
315 va_start (args, fmt);
316 usage_1 ("", fmt, args);
317 va_end (args);
318 }
319
320 void
321 usage_with_id (const char *id, const char *fmt, ...)
322 {
323 va_list args;
324 va_start (args, fmt);
325 usage_1 (id, fmt, args);
279 va_end (args); 326 va_end (args);
280 } 327 }
281 328
282 static void 329 static void
283 pr_where_2 (const char *fmt, va_list args) 330 pr_where_2 (const char *fmt, va_list args)
291 { 338 {
292 if (len > 1) 339 if (len > 1)
293 { 340 {
294 char *tmp_fmt = strsave (fmt); 341 char *tmp_fmt = strsave (fmt);
295 tmp_fmt[len - 1] = '\0'; 342 tmp_fmt[len - 1] = '\0';
296 verror (false, std::cerr, 0, tmp_fmt, args); 343 verror (false, std::cerr, 0, "", tmp_fmt, args);
297 delete [] tmp_fmt; 344 delete [] tmp_fmt;
298 } 345 }
299 } 346 }
300 else 347 else
301 verror (false, std::cerr, 0, fmt, args); 348 verror (false, std::cerr, 0, "", fmt, args);
302 } 349 }
303 } 350 }
304 else 351 else
305 panic ("pr_where_2: invalid format"); 352 panic ("pr_where_2: invalid format");
306 } 353 }
385 OSSTREAM_FREEZE (output_buf); 432 OSSTREAM_FREEZE (output_buf);
386 } 433 }
387 } 434 }
388 } 435 }
389 436
390 void 437 static int
391 warning (const char *fmt, ...) 438 check_state (const std::string& state)
392 { 439 {
393 if (Vwarning_option != "off") 440 // -1: not found
441 // 0: found, "off"
442 // 1: found, "on"
443 // 2: found, "error"
444
445 if (state == "off")
446 return 0;
447 else if (state == "on")
448 return 1;
449 else if (state == "error")
450 return 2;
451 else
452 return -1;
453 }
454
455 // For given warning ID, return 0 if warnings are disabled, 1 if
456 // enabled, and 2 if this ID should be an error instead of a warning.
457
458 static int
459 warning_enabled (const std::string& id)
460 {
461 int retval = 0;
462
463 int all_state = -1;
464 int id_state = -1;
465
466 octave_idx_type nel = warning_options.numel ();
467
468 if (nel > 0)
469 {
470 Cell identifier = warning_options.contents ("identifier");
471 Cell state = warning_options.contents ("state");
472
473 bool all_found = false;
474 bool id_found = false;
475
476 for (octave_idx_type i = 0; i < nel; i++)
477 {
478 octave_value ov = identifier(i);
479 std::string ovs = ov.string_value ();
480
481 if (! all_found && ovs == "all")
482 {
483 all_state = check_state (state(i).string_value ());
484
485 if (all_state >= 0)
486 all_found = true;
487 }
488
489 if (! id_found && ovs == id)
490 {
491 id_state = check_state (state(i).string_value ());
492
493 if (id_state >= 0)
494 id_found = true;
495 }
496
497 if (all_found && id_found)
498 break;
499 }
500
501 }
502
503 if (all_state == -1)
504 panic_impossible ();
505
506 if (all_state == 0)
507 {
508 if (id_state >= 0)
509 retval = id_state;
510 }
511 else if (all_state == 1)
512 {
513 if (id_state == 0 || id_state == 2)
514 retval = id_state;
515 else
516 retval = all_state;
517 }
518 else if (all_state == 2)
519 retval = 2;
520
521 return retval;
522 }
523
524 static void
525 warning_1 (const char *id, const char *fmt, va_list args)
526 {
527 int warn_opt = warning_enabled (id);
528
529 if (warn_opt == 2)
530 {
531 // Handle this warning as an error.
532
533 error (id, fmt, args);
534 }
535 else if (warn_opt == 1)
394 { 536 {
395 if (curr_sym_tab != top_level_sym_tab 537 if (curr_sym_tab != top_level_sym_tab
396 && Vwarning_option == "backtrace" 538 && Vbacktrace_on_warning
397 && ! warning_state 539 && ! warning_state
398 && ! discard_warning_messages) 540 && ! discard_warning_messages)
399 pr_where ("warning", false); 541 pr_where ("warning", false);
400 542
401 va_list args; 543 vwarning ("warning", id, fmt, args);
402 va_start (args, fmt);
403 vwarning ("warning", fmt, args);
404 va_end (args);
405 544
406 warning_state = 1; 545 warning_state = 1;
407 546
408 if ((interactive || forced_interactive) 547 if ((interactive || forced_interactive)
409 && Vdebug_on_warning && curr_function) 548 && Vdebug_on_warning && curr_function)
417 } 556 }
418 } 557 }
419 } 558 }
420 559
421 void 560 void
422 error (const char *fmt, ...) 561 warning (const char *fmt, ...)
423 { 562 {
424 int init_state = error_state;
425
426 va_list args; 563 va_list args;
427 va_start (args, fmt); 564 va_start (args, fmt);
428 error_1 (std::cerr, "error", fmt, args); 565 warning_1 ("", fmt, args);
429 va_end (args); 566 va_end (args);
567 }
568
569 void
570 warning_with_id (const char *id, const char *fmt, ...)
571 {
572 va_list args;
573 va_start (args, fmt);
574 warning_1 (id, fmt, args);
575 va_end (args);
576 }
577
578 static void
579 error_2 (const char *id, const char *fmt, va_list args)
580 {
581 int init_state = error_state;
582
583 error_1 (std::cerr, "error", id, fmt, args);
430 584
431 if ((interactive || forced_interactive) 585 if ((interactive || forced_interactive)
432 && Vdebug_on_error && init_state == 0 && curr_function) 586 && Vdebug_on_error && init_state == 0 && curr_function)
433 { 587 {
434 unwind_protect_bool (Vdebug_on_error); 588 unwind_protect_bool (Vdebug_on_error);
443 unwind_protect::run (); 597 unwind_protect::run ();
444 } 598 }
445 } 599 }
446 600
447 void 601 void
448 parse_error (const char *fmt, ...) 602 error (const char *fmt, ...)
449 { 603 {
450 va_list args; 604 va_list args;
451 va_start (args, fmt); 605 va_start (args, fmt);
452 error_1 (std::cerr, 0, fmt, args); 606 error_2 ("", fmt, args);
607 va_end (args);
608 }
609
610 void
611 error_with_id (const char *id, const char *fmt, ...)
612 {
613 va_list args;
614 va_start (args, fmt);
615 error_2 (id, fmt, args);
616 va_end (args);
617 }
618
619 void
620 parse_error (const char *fmt, ...)
621 {
622 va_list args;
623 va_start (args, fmt);
624 error_1 (std::cerr, 0, "", fmt, args);
625 va_end (args);
626 }
627
628 void
629 parse_error_with_id (const char *id, const char *fmt, ...)
630 {
631 va_list args;
632 va_start (args, fmt);
633 error_1 (std::cerr, 0, id, fmt, args);
453 va_end (args); 634 va_end (args);
454 } 635 }
455 636
456 void 637 void
457 panic (const char *fmt, ...) 638 panic (const char *fmt, ...)
458 { 639 {
459 va_list args; 640 va_list args;
460 va_start (args, fmt); 641 va_start (args, fmt);
461 buffer_error_messages = 0; 642 buffer_error_messages = 0;
462 discard_error_messages = false; 643 discard_error_messages = false;
463 verror (false, std::cerr, "panic", fmt, args); 644 verror (false, std::cerr, "panic", "", fmt, args);
464 va_end (args); 645 va_end (args);
465 abort (); 646 abort ();
466 } 647 }
467 648
468 static void 649 static void
469 defun_usage_message_1 (const char *fmt, ...) 650 defun_usage_message_1 (const char *fmt, ...)
470 { 651 {
471 va_list args; 652 va_list args;
472 va_start (args, fmt); 653 va_start (args, fmt);
473 error_1 (octave_stdout, 0, fmt, args); 654 error_1 (octave_stdout, 0, "", fmt, args);
474 va_end (args); 655 va_end (args);
475 } 656 }
476 657
477 void 658 void
478 defun_usage_message (const std::string& msg) 659 defun_usage_message (const std::string& msg)
479 { 660 {
480 defun_usage_message_1 ("%s", msg.c_str ()); 661 defun_usage_message_1 ("%s", msg.c_str ());
481 } 662 }
482 663
483 typedef void (*error_fun)(const char *, ...); 664 typedef void (*error_fun)(const char *, const char *, ...);
484 665
485 extern octave_value_list Fsprintf (const octave_value_list&, int); 666 extern octave_value_list Fsprintf (const octave_value_list&, int);
486 667
487 static std::string 668 static std::string
488 handle_message (error_fun f, const char *msg, const octave_value_list& args) 669 handle_message (error_fun f, const char *id, const char *msg,
670 const octave_value_list& args)
489 { 671 {
490 std::string retval; 672 std::string retval;
491 673
492 std::string tstr; 674 std::string tstr;
493 675
527 { 709 {
528 if (len > 1) 710 if (len > 1)
529 { 711 {
530 char *tmp_msg = strsave (msg); 712 char *tmp_msg = strsave (msg);
531 tmp_msg[len - 1] = '\0'; 713 tmp_msg[len - 1] = '\0';
532 f ("%s\n", tmp_msg); 714 f (id, "%s\n", tmp_msg);
533 retval = tmp_msg; 715 retval = tmp_msg;
534 delete [] tmp_msg; 716 delete [] tmp_msg;
535 } 717 }
536 } 718 }
537 else 719 else
538 { 720 {
539 f ("%s", msg); 721 f (id, "%s", msg);
540 retval = msg; 722 retval = msg;
541 } 723 }
542 724
543 return retval; 725 return retval;
544 } 726 }
597 error: nargin != 1\n\ 779 error: nargin != 1\n\
598 @end group\n\ 780 @end group\n\
599 @end example\n\ 781 @end example\n\
600 @end deftypefn") 782 @end deftypefn")
601 { 783 {
784 // XXX FIXME XXX -- need to extract and pass message id to
785 // handle_message.
786
602 octave_value_list retval; 787 octave_value_list retval;
603 handle_message (error, "unspecified error", args); 788 handle_message (error_with_id, "", "unspecified error", args);
604 return retval; 789 return retval;
605 } 790 }
606 791
607 static inline octave_value_list 792 DEFCMD (warning, args, nargout,
608 set_warning_option (const std::string& state,
609 const std::string& frequency, int nargout)
610 {
611 octave_value_list retval;
612
613 if (nargout > 1)
614 retval(1) = Vwarning_frequency;
615
616 if (nargout >= 0)
617 retval(0) = Vwarning_option;
618
619 if (! state.empty ())
620 Vwarning_option = state;
621
622 if (! frequency.empty ())
623 Vwarning_frequency = frequency;
624
625 return retval;
626 }
627
628 DEFUN (warning, args, nargout,
629 "-*- texinfo -*-\n\ 793 "-*- texinfo -*-\n\
630 @deftypefn {Built-in Function} {} warning (@var{msg})\n\ 794 @deftypefn {Built-in Function} {} warning (@var{msg})\n\
631 Print a warning message @var{msg} prefixed by the string @samp{warning: }. \n\ 795 Print a warning message @var{msg} prefixed by the string @samp{warning: }. \n\
632 After printing the warning message, Octave will continue to execute\n\ 796 After printing the warning message, Octave will continue to execute\n\
633 commands. You should use this function when you want to notify the user\n\ 797 commands. You should use this function when you want to notify the user\n\
634 of an unusual condition, but only when it makes sense for your program\n\ 798 of an unusual condition, but only when it makes sense for your program\n\
635 to go on.\n\ 799 to go on.\n\
636 @end deftypefn") 800 @end deftypefn")
637 { 801 {
638 octave_value_list retval; 802 octave_value retval;
639 803
640 int argc = args.length () + 1; 804 int nargin = args.length ();
805 int argc = nargin + 1;
641 806
642 bool done = false; 807 bool done = false;
643 808
644 if (args.all_strings_p ()) 809 if (argc > 1 && args.all_strings_p ())
645 { 810 {
646 string_vector argv = args.make_argv ("warning"); 811 string_vector argv = args.make_argv ("warning");
647 812
648 if (! error_state) 813 if (! error_state)
649 { 814 {
650 if (argc == 1) 815 std::string arg1 = argv(1);
816 std::string arg2 = "all";
817
818 if (argc == 3)
819 arg2 = argv(2);
820
821 if (arg1 == "on" || arg1 == "off" || arg1 == "error")
651 { 822 {
652 retval = set_warning_option ("", "", nargout); 823 Octave_map old_warning_options = warning_options;
824
825 if (arg2 == "all")
826 {
827 Octave_map tmp;
828
829 tmp.assign ("identifier", arg2);
830 tmp.assign ("state", arg1);
831
832 warning_options = tmp;
833
834 done = true;
835 }
836 else if (arg2 == "backtrace")
837 {
838 if (arg1 != "error")
839 {
840 Vbacktrace_on_warning = (arg1 == "on");
841 done = true;
842 }
843 }
844 else if (arg2 == "debug")
845 {
846 if (arg1 != "error")
847 {
848 bind_builtin_variable ("debug_on_warning", arg1 == "on");
849 done = true;
850 }
851 }
852 else if (arg2 == "verbose")
853 {
854 if (arg1 != "error")
855 {
856 Vverbose_warning = (arg1 == "on");
857 done = true;
858 }
859 }
860 else
861 {
862 if (arg2 == "last")
863 arg2 = Vlast_warning_id;
864
865 if (arg2 == "all")
866 init_warning_options (arg1);
867 else
868 {
869 Cell ident = warning_options.contents ("identifier");
870 Cell state = warning_options.contents ("state");
871
872 octave_idx_type nel = ident.numel ();
873
874 bool found = false;
875
876 for (octave_idx_type i = 0; i < nel; i++)
877 {
878 if (ident(i).string_value () == arg2)
879 {
880 // XXX FIXME XXX -- if state for "all" is
881 // same as arg1, we can simply remove the
882 // item from the list.
883
884 state(i) = arg1;
885 warning_options.assign ("state", state);
886 found = true;
887 break;
888 }
889 }
890
891 if (! found)
892 {
893 // XXX FIXME XXX -- if state for "all" is
894 // same as arg1, we don't need to do anything.
895
896 ident.resize (dim_vector (1, nel+1));
897 state.resize (dim_vector (1, nel+1));
898
899 ident(nel) = arg2;
900 state(nel) = arg1;
901
902 warning_options.clear ();
903
904 warning_options.assign ("identifier", ident);
905 warning_options.assign ("state", state);
906 }
907 }
908
909 done = true;
910 }
911
912 if (done && nargout > 0)
913 retval = warning_options;
914 }
915 else if (arg1 == "query")
916 {
917 if (arg2 == "all")
918 retval = warning_options;
919 else if (arg2 == "backtrace" || arg2 == "debug"
920 || arg2 == "verbose")
921 {
922 Octave_map tmp;
923 tmp.assign ("identifier", arg2);
924 if (arg2 == "backtrace")
925 tmp.assign ("state", Vbacktrace_on_warning ? "on" : "off");
926 else if (arg2 == "debug")
927 tmp.assign ("state", Vdebug_on_warning ? "on" : "off");
928 else
929 tmp.assign ("state", Vverbose_warning ? "on" : "off");
930 }
931 else
932 {
933 if (arg2 == "last")
934 arg2 = Vlast_warning_id;
935
936 Cell ident = warning_options.contents ("identifier");
937 Cell state = warning_options.contents ("state");
938
939 octave_idx_type nel = ident.numel ();
940
941 bool found = false;
942
943 std::string val;
944
945 for (octave_idx_type i = 0; i < nel; i++)
946 {
947 if (ident(i).string_value () == arg2)
948 {
949 val = state(i).string_value ();
950 found = true;
951 break;
952 }
953 }
954
955 if (found)
956 {
957 Octave_map tmp;
958
959 tmp.assign ("identifier", arg2);
960 tmp.assign ("state", val);
961
962 retval = tmp;
963 }
964 else
965 error ("warning: invalid warning tag `%s'", arg2.c_str ());
966 }
967
653 done = true; 968 done = true;
654 } 969 }
655 else if (argc == 2) 970 }
971 }
972 else if (argc == 1)
973 {
974 retval = warning_options;
975
976 done = true;
977 }
978 else if (argc == 2)
979 {
980 octave_value arg = args(0);
981
982 Octave_map old_warning_options = warning_options;
983
984 if (arg.is_map ())
985 {
986 Octave_map m = arg.map_value ();
987
988 if (m.contains ("identifier") && m.contains ("state"))
989 warning ("warning: setting state with structure not implemented");
990 else
991 error ("warning: expecting structure with fields `identifier' and `state'");
992
993 done = true;
994
995 if (nargout > 0)
996 retval = old_warning_options;
997 }
998 }
999
1000 if (! (error_state || done))
1001 {
1002 octave_value_list nargs = args;
1003
1004 std::string id;
1005
1006 if (nargin > 1)
1007 {
1008 std::string arg1 = args(0).string_value ();
1009
1010 if (! error_state)
656 { 1011 {
657 std::string arg = argv(1); 1012 if (arg1.find ('%') == NPOS)
658
659 if (arg == "on" || arg == "off" || arg == "backtrace")
660 { 1013 {
661 retval = set_warning_option (arg, "", nargout); 1014 id = arg1;
662 done = true; 1015
663 } 1016 nargs.resize (nargin-1);
664 else if (arg == "once" || arg == "always") 1017
665 { 1018 for (int i = 1; i < nargin; i++)
666 retval = set_warning_option ("", arg, nargout); 1019 nargs(i-1) = args(i);
667 done = true;
668 }
669 else if (arg == "debug")
670 {
671 bind_builtin_variable ("debug_on_warning", true);
672 retval = set_warning_option ("", "", nargout);
673 done = true;
674 } 1020 }
675 } 1021 }
676 } 1022 else
677 } 1023 return retval;
678 1024 }
679 if (! done) 1025
680 { 1026 // handle_message.
1027
681 std::string prev_msg = Vlast_warning_message; 1028 std::string prev_msg = Vlast_warning_message;
682 1029
683 std::string curr_msg 1030 std::string curr_msg = handle_message (warning_with_id, id.c_str (),
684 = handle_message (warning, "unspecified warning", args); 1031 "unspecified warning", nargs);
685 1032
686 if (nargout > 0) 1033 if (nargout > 0)
687 retval(0) = Vlast_warning_message; 1034 retval = prev_msg;
688 } 1035 }
689 1036
690 return retval; 1037 return retval;
691 } 1038 }
692 1039
693 DEFUN (lasterr, args, , 1040 DEFUN (lasterr, args, nargout,
694 "-*- texinfo -*-\n\ 1041 "-*- texinfo -*-\n\
695 @deftypefn {Built-in Function} {} lasterr ()\n\ 1042 @deftypefn {Built-in Function} {[@var{msg}, @var{msgid}] =} lasterr (@var{msg}, @var{msgid})\n\
696 @deftypefnx {Built-in Function} {} lasterr (@var{msg})\n\
697 Without any arguments, return the last error message. With one\n\ 1043 Without any arguments, return the last error message. With one\n\
698 argument, set the last error message to @var{msg}.\n\ 1044 argument, set the last error message to @var{msg}. With two arguments,\n\
1045 also set the last message identifier.\n\
699 @end deftypefn") 1046 @end deftypefn")
700 { 1047 {
701 octave_value_list retval; 1048 octave_value_list retval;
702 1049
703 int argc = args.length () + 1; 1050 int argc = args.length () + 1;
704 1051
705 if (argc == 1 || argc == 2) 1052 if (argc < 4)
706 { 1053 {
707 string_vector argv = args.make_argv ("lasterr"); 1054 string_vector argv = args.make_argv ("lasterr");
708 1055
709 if (! error_state) 1056 if (! error_state)
710 { 1057 {
711 if (argc == 1) 1058 std::string prev_error_id = Vlast_error_id;
712 retval(0) = Vlast_error_message; 1059 std::string prev_error_message = Vlast_error_message;
713 else 1060
1061 if (argc > 2)
1062 Vlast_error_id = argv(2);
1063
1064 if (argc > 1)
714 Vlast_error_message = argv(1); 1065 Vlast_error_message = argv(1);
715 } 1066
1067 if (argc == 1 || nargout > 0)
1068 {
1069 retval(1) = prev_error_id;
1070 retval(0) = prev_error_message;
1071 }
1072 }
1073 else
1074 error ("lastwarn: expecting arguments to be character strings");
716 } 1075 }
717 else 1076 else
718 print_usage ("lasterr"); 1077 print_usage ("lasterr");
719 1078
720 return retval; 1079 return retval;
722 1081
723 // For backward compatibility. 1082 // For backward compatibility.
724 DEFALIAS (error_text, lasterr); 1083 DEFALIAS (error_text, lasterr);
725 DEFALIAS (__error_text__, lasterr); 1084 DEFALIAS (__error_text__, lasterr);
726 1085
727 DEFUN (lastwarn, args, , 1086 DEFUN (lastwarn, args, nargout,
728 "-*- texinfo -*-\n\ 1087 "-*- texinfo -*-\n\
729 @deftypefn {Built-in Function} {} lastwarn ()\n\ 1088 @deftypefn {Built-in Function} {[@var{msg}, @var{msgid}] =} lastwarn (@var{msg}, @var{msgid})\n\
730 @deftypefnx {Built-in Function} {} lastwarn (@var{msg})\n\
731 Without any arguments, return the last warning message. With one\n\ 1089 Without any arguments, return the last warning message. With one\n\
732 argument, set the last warning message to @var{msg}.\n\ 1090 argument, set the last warning message to @var{msg}. With two arguments,\n\
1091 also set the last message identifier.\n\
733 @end deftypefn") 1092 @end deftypefn")
734 { 1093 {
735 octave_value_list retval; 1094 octave_value_list retval;
736 1095
737 int argc = args.length () + 1; 1096 int argc = args.length () + 1;
738 1097
739 string_vector argv = args.make_argv ("lastwarn"); 1098 if (argc < 4)
740 1099 {
741 if (argc == 1) 1100 string_vector argv = args.make_argv ("lastwarn");
742 retval(0) = Vlast_warning_message; 1101
743 else if (argc == 2) 1102 if (! error_state)
744 Vlast_warning_message = argv(1); 1103 {
1104 std::string prev_warning_id = Vlast_warning_id;
1105 std::string prev_warning_message = Vlast_warning_message;
1106
1107 if (argc > 2)
1108 Vlast_warning_id = argv(2);
1109
1110 if (argc > 1)
1111 Vlast_warning_message = argv(1);
1112
1113 if (argc == 1 || nargout > 0)
1114 {
1115 retval(1) = prev_warning_id;
1116 retval(0) = prev_warning_message;
1117 }
1118 }
1119 else
1120 error ("lastwarn: expecting arguments to be character strings");
1121 }
745 else 1122 else
746 print_usage ("lastwarn"); 1123 print_usage ("lastwarn");
747 1124
748 return retval; 1125 return retval;
749 } 1126 }
776 @noindent\n\ 1153 @noindent\n\
777 to check for the proper number of arguments.\n\ 1154 to check for the proper number of arguments.\n\
778 @end deftypefn") 1155 @end deftypefn")
779 { 1156 {
780 octave_value_list retval; 1157 octave_value_list retval;
781 handle_message (usage, "unknown", args); 1158 handle_message (usage_with_id, "", "unknown", args);
782 return retval; 1159 return retval;
783 } 1160 }
784 1161
785 static int 1162 static int
786 beep_on_error (void) 1163 beep_on_error (void)
807 } 1184 }
808 1185
809 void 1186 void
810 symbols_of_error (void) 1187 symbols_of_error (void)
811 { 1188 {
1189 init_warning_options ();
1190
812 DEFVAR (beep_on_error, false, beep_on_error, 1191 DEFVAR (beep_on_error, false, beep_on_error,
813 "-*- texinfo -*-\n\ 1192 "-*- texinfo -*-\n\
814 @defvr {Built-in Variable} beep_on_error\n\ 1193 @defvr {Built-in Variable} beep_on_error\n\
815 If the value of @code{beep_on_error} is nonzero, Octave will try\n\ 1194 If the value of @code{beep_on_error} is nonzero, Octave will try\n\
816 to ring your terminal's bell before printing an error message. The\n\ 1195 to ring your terminal's bell before printing an error message. The\n\