Mercurial > hg > octave-nkf
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\ |