1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25
26 #if ! defined (octave_error_h)
27 #define octave_error_h 1
28
29 #include "octave-config.h"
30
31 #include <cstdarg>
32 #include <cinttypes>
33 #include <string>
34
35 #include "unwind-prot.h"
36
37 #include "oct-map.h"
38
39 class octave_value_list;
40 namespace octave
41 {
42 class execution_exception;
43 }
44
45 namespace octave
46 {
47 class error_system
48 {
49 public:
50
51 error_system (interpreter& interp);
52
53 error_system (const error_system&) = delete;
54
55 error_system& operator = (const error_system&) = delete;
56
57 ~error_system (void) = default;
58
59 octave_value debug_on_error (const octave_value_list& args, int nargout);
60
set_debug_on_error(bool flag)61 void set_debug_on_error (bool flag) { m_debug_on_error = flag; }
62
debug_on_error(void)63 bool debug_on_error (void) const { return m_debug_on_error; }
64
debug_on_error(bool flag)65 bool debug_on_error (bool flag)
66 {
67 bool val = m_debug_on_error;
68 m_debug_on_error = flag;
69 return val;
70 }
71
72 octave_value debug_on_caught (const octave_value_list& args, int nargout);
73
set_debug_on_caught(bool flag)74 void set_debug_on_caught (bool flag) { m_debug_on_caught = flag; }
75
debug_on_caught(void)76 bool debug_on_caught (void) const { return m_debug_on_caught; }
77
debug_on_caught(bool flag)78 bool debug_on_caught (bool flag)
79 {
80 bool val = m_debug_on_caught;
81 m_debug_on_caught = flag;
82 return val;
83 }
84
85 octave_value debug_on_warning (const octave_value_list& args, int nargout);
86
set_debug_on_warning(bool flag)87 void set_debug_on_warning (bool flag) { m_debug_on_warning = flag; }
88
debug_on_warning(void)89 bool debug_on_warning (void) const { return m_debug_on_warning; }
90
debug_on_warning(bool flag)91 bool debug_on_warning (bool flag)
92 {
93 bool val = m_debug_on_warning;
94 m_debug_on_warning = flag;
95 return val;
96 }
97
98 octave_value discard_warning_messages (const octave_value_list& args,
99 int nargout);
100
set_discard_warning_messages(bool flag)101 void set_discard_warning_messages (bool flag) { m_discard_warning_messages = flag; }
102
discard_warning_messages(void)103 bool discard_warning_messages (void) const { return m_discard_warning_messages; }
104
discard_warning_messages(bool flag)105 bool discard_warning_messages (bool flag)
106 {
107 bool val = m_discard_warning_messages;
108 m_discard_warning_messages = flag;
109 return val;
110 }
111
112 octave_value beep_on_error (const octave_value_list& args, int nargout);
113
set_beep_on_error(bool flag)114 void set_beep_on_error (bool flag) { m_beep_on_error = flag; }
115
beep_on_error(void)116 bool beep_on_error (void) const { return m_beep_on_error; }
117
beep_on_error(bool flag)118 bool beep_on_error (bool flag)
119 {
120 bool val = m_beep_on_error;
121 m_beep_on_error = flag;
122 return val;
123 }
124
125 octave_value backtrace_on_warning (const octave_value_list& args, int nargout);
126
set_backtrace_on_warning(bool flag)127 void set_backtrace_on_warning (bool flag) { m_backtrace_on_warning = flag; }
128
backtrace_on_warning(void)129 bool backtrace_on_warning (void) const { return m_backtrace_on_warning; }
130
backtrace_on_warning(bool flag)131 bool backtrace_on_warning (bool flag)
132 {
133 bool val = m_backtrace_on_warning;
134 m_backtrace_on_warning = flag;
135 return val;
136 }
137
138 octave_value verbose_warning (const octave_value_list& args, int nargout);
139
set_verbose_warning(bool flag)140 void set_verbose_warning (bool flag) { m_verbose_warning = flag; }
141
verbose_warning(void)142 bool verbose_warning (void) const { return m_verbose_warning; }
143
verbose_warning(bool flag)144 bool verbose_warning (bool flag)
145 {
146 bool val = m_verbose_warning;
147 m_verbose_warning = flag;
148 return val;
149 }
150
151 octave_value quiet_warning (const octave_value_list& args, int nargout);
152
set_quiet_warning(bool flag)153 void set_quiet_warning (bool flag) { m_quiet_warning = flag; }
154
quiet_warning(void)155 bool quiet_warning (void) const { return m_quiet_warning; }
156
quiet_warning(bool flag)157 bool quiet_warning (bool flag)
158 {
159 bool val = m_quiet_warning;
160 m_quiet_warning = flag;
161 return val;
162 }
163
warning_options(void)164 octave_map warning_options (void) const { return m_warning_options; }
165
set_warning_options(const octave_map & val)166 void set_warning_options (const octave_map& val) { m_warning_options = val; }
167
warning_options(const octave_map & new_val)168 octave_map warning_options (const octave_map& new_val)
169 {
170 octave_map val = m_warning_options;
171 m_warning_options = new_val;
172 return val;
173 }
174
175 octave_value last_error_message (const octave_value_list& args, int nargout);
176
set_last_error_message(const std::string & val)177 void set_last_error_message (const std::string& val) { m_last_error_message = val; }
178
last_error_message(void)179 std::string last_error_message (void) const { return m_last_error_message; }
180
last_error_message(const std::string & s)181 std::string last_error_message (const std::string& s)
182 {
183 std::string val = m_last_error_message;
184 m_last_error_message = s;
185 return val;
186 }
187
188 octave_value last_warning_message (const octave_value_list& args, int nargout);
189
set_last_warning_message(const std::string & val)190 void set_last_warning_message (const std::string& val) { m_last_warning_message = val; }
191
last_warning_message(void)192 std::string last_warning_message (void) const { return m_last_warning_message; }
193
last_warning_message(const std::string & s)194 std::string last_warning_message (const std::string& s)
195 {
196 std::string val = m_last_warning_message;
197 m_last_warning_message = s;
198 return val;
199 }
200
201 octave_value last_warning_id (const octave_value_list& args, int nargout);
202
set_last_warning_id(const std::string & val)203 void set_last_warning_id (const std::string& val) { m_last_warning_id = val; }
204
last_warning_id(void)205 std::string last_warning_id (void) const { return m_last_warning_id; }
206
last_warning_id(const std::string & s)207 std::string last_warning_id (const std::string& s)
208 {
209 std::string val = m_last_warning_id;
210 m_last_warning_id = s;
211 return val;
212 }
213
214 octave_value last_error_id (const octave_value_list& args, int nargout);
215
set_last_error_id(const std::string & val)216 void set_last_error_id (const std::string& val) { m_last_error_id = val; }
217
last_error_id(void)218 std::string last_error_id (void) const { return m_last_error_id; }
219
last_error_id(const std::string & s)220 std::string last_error_id (const std::string& s)
221 {
222 std::string val = m_last_error_id;
223 m_last_error_id = s;
224 return val;
225 }
226
set_last_error_stack(const octave_map & val)227 void set_last_error_stack (const octave_map& val)
228 {
229 m_last_error_stack = val;
230 }
231
last_error_stack(void)232 octave_map last_error_stack (void) const { return m_last_error_stack; }
233
last_error_stack(const octave_map & new_val)234 octave_map last_error_stack (const octave_map& new_val)
235 {
236 octave_map val = m_last_error_stack;
237 m_last_error_stack = new_val;
238 return val;
239 }
240
241 static octave_map
242 make_stack_map (const std::list<octave::frame_info>& frames);
243
244 static std::list<octave::frame_info>
245 make_stack_frame_list (const octave_map& stack);
246
247 //! For given warning ID, return 0 if warnings are disabled, 1 if
248 //! enabled, and 2 if the given ID should be an error instead of a
249 //! warning.
250
251 int warning_enabled (const std::string& id);
252
253 void verror (bool save_last_error, std::ostream& os, const char *name,
254 const char *id, const char *fmt, va_list args,
255 bool with_cfn = false);
256
257 void vwarning (const char *name, const char *id, const char *fmt,
258 va_list args);
259
260 OCTAVE_NORETURN
261 void error_1 (execution_exception& e, const char *id, const char *fmt,
262 va_list args);
263
264 OCTAVE_NORETURN
265 void error_1 (const char *id, const char *fmt, va_list args);
266
267 OCTAVE_NORETURN
268 void vusage (const char *id, const char *fmt, va_list args);
269
270 void vwarning (const char *id, const char *fmt, va_list args);
271
272 OCTAVE_NORETURN
273 void rethrow_error (const std::string& id, const std::string& msg,
274 const octave_map& stack);
275
276 OCTAVE_NORETURN
277 void vpanic (const char *fmt, va_list args);
278
279 OCTAVE_NORETURN
280 void panic (const char *fmt, ...);
281
282 octave_scalar_map warning_query (const std::string& id_arg);
283
284 std::string default_warning_state (void);
285
286 void display_warning_options (std::ostream& os);
287
288 void set_warning_option (const std::string& state, const std::string& id);
289
290 void disable_warning (const std::string& id);
291
292 void initialize_default_warning_state (void);
293
294 void interpreter_try (octave::unwind_protect& frame);
295
296 // Throw execution_exception or, if debug_on_error is TRUE, enter
297 // debugger. If stack_info is empty, use current call stack.
298
299 OCTAVE_NORETURN
300 void throw_error (const std::string& err_type,
301 const std::string& id,
302 const std::string& message,
303 const std::list<frame_info>& stack_info
304 = std::list<frame_info> ());
305
306 OCTAVE_NORETURN
307 void throw_error (execution_exception& e);
308
309 void save_exception (const execution_exception& e);
310
311 void display_exception (const execution_exception& e,
312 std::ostream& os) const;
313
314 private:
315
316 interpreter& m_interpreter;
317
318 //! TRUE means that Octave will try to enter the debugger when an error
319 //! is encountered. This will also inhibit printing of the normal
320 //! traceback message (you will only see the top-level error message).
321
322 bool m_debug_on_error;
323
324 //! TRUE means that Octave will try to enter the debugger when an error
325 //! is encountered within the 'try' section of a 'try' / 'catch' block.
326
327 bool m_debug_on_caught;
328
329 //! TRUE means that Octave will try to enter the debugger when a warning
330 //! is encountered.
331
332 bool m_debug_on_warning;
333
334 //! TRUE means warning messages are turned off.
335
336 bool m_discard_warning_messages;
337
338 //! TRUE means that Octave will try to beep obnoxiously before
339 //! printing error messages.
340 bool m_beep_on_error;
341
342 //! TRUE means that Octave will try to display a stack trace when a
343 //! warning is encountered.
344 bool m_backtrace_on_warning;
345
346 //! TRUE means that Octave will print a verbose warning. Currently
347 //! unused.
348 bool m_verbose_warning;
349
350 //! TRUE means that Octave will print no warnings, but lastwarn will
351 //! be updated
352 bool m_quiet_warning;
353
354 //! A structure containing (most of) the current state of warnings.
355 octave_map m_warning_options;
356
357 //! The text of the last error message.
358 std::string m_last_error_message;
359
360 //! The text of the last warning message.
361 std::string m_last_warning_message;
362
363 //! The last warning message id.
364 std::string m_last_warning_id;
365
366 //! The last error message id.
367 std::string m_last_error_id;
368
369 //! The last file in which an error occurred.
370 octave_map m_last_error_stack;
371 };
372 }
373
374 // FIXME: should we move the following functions inside the octave
375 // namespace? If so, should the functions outside of the namespace be
376 // deprecated? Doing that might cause a lot of trouble... If they are
377 // not deprecated and eventually removed, does it make sense to also
378 // define them inside the octave namespace?
379
380 #define panic_impossible() \
381 panic ("impossible state reached in file '%s' at line %d", __FILE__, __LINE__)
382
383 extern OCTINTERP_API int warning_enabled (const std::string& id);
384
385 extern OCTINTERP_API void
386 vmessage (const char *name, const char *fmt, va_list args);
387
388 OCTAVE_FORMAT_PRINTF (2, 3)
389 extern OCTINTERP_API void message (const char *name, const char *fmt, ...);
390
391 extern OCTINTERP_API void vwarning (const char *fmt, va_list args);
392
393 OCTAVE_FORMAT_PRINTF (1, 2)
394 extern OCTINTERP_API void warning (const char *fmt, ...);
395
396 OCTAVE_NORETURN
397 extern OCTINTERP_API void verror (const char *fmt, va_list args);
398
399 OCTAVE_FORMAT_PRINTF (1, 2)
400 OCTAVE_NORETURN
401 extern OCTINTERP_API void error (const char *fmt, ...);
402
403 OCTAVE_NORETURN
404 extern OCTINTERP_API void
405 verror (octave::execution_exception&, const char *fmt, va_list args);
406
407 OCTAVE_FORMAT_PRINTF (2, 3)
408 OCTAVE_NORETURN
409 extern OCTINTERP_API void
410 error (octave::execution_exception&, const char *fmt, ...);
411
412 OCTAVE_NORETURN
413 extern OCTINTERP_API void
414 verror_with_cfn (const char *fmt, va_list args);
415
416 OCTAVE_FORMAT_PRINTF (1, 2)
417 OCTAVE_NORETURN
418 extern OCTINTERP_API void
419 error_with_cfn (const char *fmt, ...);
420
421 OCTAVE_NORETURN
422 extern OCTINTERP_API void
423 vparse_error (const char *fmt, va_list args);
424
425 OCTAVE_FORMAT_PRINTF (1, 2)
426 OCTAVE_NORETURN
427 extern OCTINTERP_API void
428 parse_error (const char *fmt, ...);
429
430 OCTAVE_NORETURN
431 extern OCTINTERP_API void
432 vusage_with_id (const char *id, const char *fmt, va_list args);
433
434 OCTAVE_FORMAT_PRINTF (2, 3)
435 OCTAVE_NORETURN
436 extern OCTINTERP_API void
437 usage_with_id (const char *id, const char *fmt, ...);
438
439 extern OCTINTERP_API void
440 vwarning_with_id (const char *id, const char *fmt, va_list args);
441
442 OCTAVE_FORMAT_PRINTF (2, 3)
443 extern OCTINTERP_API void
444 warning_with_id (const char *id, const char *fmt, ...);
445
446 OCTAVE_NORETURN
447 extern OCTINTERP_API void
448 verror_with_id (const char *id, const char *fmt, va_list args);
449
450 OCTAVE_FORMAT_PRINTF (2, 3)
451 OCTAVE_NORETURN
452 extern OCTINTERP_API void
453 error_with_id (const char *id, const char *fmt, ...);
454
455 OCTAVE_NORETURN
456 extern OCTINTERP_API void
457 verror_with_id_cfn (const char *id, const char *fmt, va_list args);
458
459 OCTAVE_FORMAT_PRINTF (2, 3)
460 OCTAVE_NORETURN
461 extern OCTINTERP_API void
462 error_with_id_cfn (const char *id, const char *fmt, ...);
463
464 OCTAVE_NORETURN
465 extern OCTINTERP_API void
466 vparse_error_with_id (const char *id, const char *fmt, va_list args);
467
468 OCTAVE_FORMAT_PRINTF (2, 3)
469 OCTAVE_NORETURN
470 extern OCTINTERP_API void
471 parse_error_with_id (const char *id, const char *fmt, ...);
472
473 OCTAVE_NORETURN
474 extern OCTINTERP_API void vpanic (const char *fmt, va_list args);
475
476 OCTAVE_FORMAT_PRINTF (1, 2)
477 OCTAVE_NORETURN
478 extern OCTINTERP_API void panic (const char *fmt, ...);
479
480 //! Helper function for print_usage defined in defun.cc.
481
482 extern OCTINTERP_API void defun_usage_message (const std::string& msg);
483
484 extern OCTINTERP_API octave_value_list
485 set_warning_state (const std::string& id, const std::string& state);
486
487 extern OCTINTERP_API octave_value_list
488 set_warning_state (const octave_value_list& args);
489
490 extern OCTINTERP_API void disable_warning (const std::string& id);
491
492 extern OCTINTERP_API void interpreter_try (octave::unwind_protect&);
493
494 OCTAVE_DEPRECATED (6, "this variable is obsolete and always has the value 0")
495 extern OCTINTERP_API int error_state;
496
497 OCTAVE_DEPRECATED (6, "this function is obsolete and should not be needed")
reset_error_handler(void)498 inline void reset_error_handler (void) { }
499
500 #endif
501