Merge branch 'main' of feistymeow.org:feisty_meow
[feisty_meow.git] / loggers / critical_events.h
1 #ifndef CRITICAL_EVENTS_GROUP
2 #define CRITICAL_EVENTS_GROUP
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : critical_events                                                   *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 1989-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 #include <basis/astring.h>
19
20 namespace loggers {
21
22 //! This macro wraps the notion of stopping in the debugger.
23 #ifndef _MSC_VER
24   #define CAUSE_BREAKPOINT
25 //hmmm: need a unix equivalent for this.  supporting gcc might be enough.
26 #else
27   #ifdef __MINGW32__
28     extern "C" {
29 //      #include <ddk/winddi.h>
30 //for debugbreak.  does this cause other problems?
31     }
32     #define CAUSE_BREAKPOINT 
33 //    #define CAUSE_BREAKPOINT __debugbreak()
34   #else
35     #define CAUSE_BREAKPOINT __debugbreak()
36   #endif
37 #endif
38
39 //! Tests the value "check" to ensure that it's not zero.
40 /*! This can be used instead of an ASSERT macro to check conditions in
41 builds with ERRORS_ARE_FATAL turned on.  This macro is orthogonal to the
42 build being built with debugging or release features. */
43 #ifdef ERRORS_ARE_FATAL
44   #define REQUIRE(check) if (!check) CAUSE_BREAKPOINT;
45 #else
46   #define REQUIRE(check)
47 #endif
48
49 // now more dangerous or potent guards...
50
51 //! an extra piece of information used, if available, in bounds_halt below.
52 //#define BH_ERROR_ADDITION ((basis::astring(" in ") + _global_argv[0]).s())
53
54 //! Verifies that "value" is between "low" and "high", inclusive.
55 /*! "Value" must be an object for which greater than and less than are defined.
56 The static_class_name() method and func definition are used to tag the
57 complaint that is emitted when problems are detected.  Note that if
58 CATCH_ERRORS is defined, then the program is _halted_ if the value is out
59 of bounds.  Otherwise, the "to_return" value is returned. */
60 //#ifdef CATCH_ERRORS
61 //  #define bounds_halt(value, low, high, to_return) { 
62 //    if (((value) < (low)) || ((value) > (high))) { 
63 //      critical_events::implement_bounds_halt(static_class_name(), func, #value, #low, 
64 //          #high, BH_ERROR_ADDITION); 
65 //      return to_return; 
66 //    } 
67 //  }
68 //#else
69 //  #define bounds_halt(a, b, c, d) bounds_return(a, b, c, d)
70 //#endif
71
72 //////////////
73
74 //! Provide some macros that will automatically add the file and line number.
75 /*! These use the functions below to report different types of error
76 situations and in some cases, exit the program. */
77 #define non_continuable_error(c, f, i) \
78   critical_events::FL_non_continuable_error(__FILE__, __LINE__, c, f, i, \
79       "A Non-Continuable Runtime Problem Has Occurred")
80 #define continuable_error(c, f, i) \
81   critical_events::FL_continuable_error(__FILE__, __LINE__, c, f, i, \
82       "Runtime Problem Information")
83 #define console_error(c, f, i) \
84   critical_events::FL_console_error(__FILE__, __LINE__, c, f, i)
85 #define deadly_error(c, f, i) \
86   critical_events::FL_deadly_error(__FILE__, __LINE__, c, f, i)
87 #define out_of_memory_now(c, f) \
88   critical_events::FL_out_of_memory_now(__FILE__, __LINE__, c, f)
89
90 //////////////
91
92 //! Provides a means of logging events for runtime problems.
93
94 class critical_events : public virtual basis::root_object
95 {
96 public:
97   virtual ~critical_events() {}
98
99   // super handy system inter-operation functions...
100
101   static basis::un_int system_error();
102     //!< gets the most recent system error reported on this thread.
103
104   static basis::astring system_error_text(basis::un_int error_to_show);
105     //!< returns the OS's string form of the "error_to_show".
106     /*!< this often comes from the value reported by system_error(). */
107
108   // some noisemaking methods...
109
110   //! Prints out a message to the standard error file stream.
111   static void write_to_console(const char *message);
112
113   //! shows the message in "info", with an optional "title" on the message.
114   /*! the message is sent to the program wide logger, if one is expected to
115   exist in this program. */
116   static void alert_message(const char *info, const char *title = "Alert Message");
117   static void alert_message(const basis::astring &info);  // uses default title.
118   static void alert_message(const basis::astring &info, const basis::astring &title);  // use "title".
119
120   static void write_to_critical_events(const char *message);
121     //!< sends the "message" to the critical events log file.
122     /*!< Prints out a message to the specially named file that captures all
123     serious events written to error logging functions.  If you use the
124     functions in this file, you are likely already writing to this log. */
125
126   static void set_critical_events_directory(const basis::astring &directory);
127     //!< sets the internal location where the critical events will be logged.
128     /*!< this is postponed to a higher level, although the default
129     will work too. */
130
131   static basis::astring critical_events_directory();
132     //!< returns the current location where critical events are written.
133
134   // this section implements the error macros.
135
136   //! Prints out an error message and then exits the program.
137   /*! The parameters describe the location where the error was detected.  This
138   call should only be used in test programs or where absolutely necessary
139   because it causes an almost immediate exit from the program!  deadly_error
140   should be reserved for when the program absolutely has to exit right then,
141   because this function will actually enforce a crash / abort / break into
142   debugger action rather than just calling exit(). */
143   static void FL_deadly_error(const char *file, int line, const char *classname,
144       const char *function_name, const char *info);
145   //! A version that takes strings instead of char pointers.
146   static void FL_deadly_error(const basis::astring &file, int line,
147       const basis::astring &classname, const basis::astring &function_name,
148       const basis::astring &info);
149
150   //! Describes an error like deadly_error, but does not exit the program.
151   static void FL_continuable_error(const char *file, int line,
152       const char *classname, const char *function_name, const char *info,
153       const char *title);
154
155   //! A version using astring instead of char pointers.
156   static void FL_continuable_error(const basis::astring &file, int line,
157       const basis::astring &classname, const basis::astring &function_name,
158       const basis::astring &info, const basis::astring &title);
159
160   //! Shows the same information as continuable_error, but causes an exit.
161   /*! This is a friendlier program exit than deadly_error.  This version can
162   be used when the program must stop, possibly because of a precondition failure
163   or a problem in input data or basically whatever.  it is not intended to
164   abort or break into the debugger, but to simply exit(). */
165   static void FL_non_continuable_error(const char *file, int line,
166       const char *classname, const char *function_name, const char *info,
167       const char *title);
168
169   //! A version using astring instead of char pointers.
170   static void FL_non_continuable_error(const basis::astring &file, int line,
171       const basis::astring &classname, const basis::astring &function_name,
172       const basis::astring &info, const basis::astring &title);
173
174   //! Causes the program to exit due to a memory allocation failure.
175   static void FL_out_of_memory_now(const char *file, int line,
176       const char *classname, const char *function_name);
177   
178   //! Prints out an error message to the standard error file stream.
179   static void FL_console_error(const char *file, int line, const char *error_class,
180       const char *error_function, const char *info);
181
182   //! Used to build our particular type of error message.
183   /*! It writes an error message into "guards_message_space" using our stylized
184   object::method formatting. */
185   static void make_error_message(const char *file, int line,
186       const char *error_class, const char *error_function,
187       const char *info, char *guards_message_space);
188
189   //! Provides the real implementation of bounds_halt to save code space.
190   static void implement_bounds_halt(const char *the_class_name, const char *func,
191       const char *value, const char *low, const char *high,
192       const char *error_addition);
193
194 private:
195   static basis::astring &hidden_critical_events_dir();
196
197   static void FL_continuable_error_real(const char *file, int line,
198       const char *error_class, const char *error_function, const char *info,
199       const char *title);
200 };
201
202 } //namespace.
203
204 #endif
205