1 /* error.hpp -- handling errors/warnings etc. 2 * by pts@fazekas.hu at Fri Mar 1 11:32:36 CET 2002 3 */ 4 5 #ifdef __GNUC__ 6 #ifndef __clang__ 7 #pragma interface 8 #endif 9 #endif 10 11 #ifndef ERROR_HPP 12 #define ERROR_HPP 1 13 14 #include "config2.h" 15 #include "gensi.hpp" 16 17 /** This may be usafe if an error happens inside an error. Usage: 18 * Error::sev(Error::WARNING) << "Zero-length image." << (Error*)0; 19 */ 20 class Error { 21 public: 22 static char const* banner0; 23 static char const* argv0; 24 static char const* tmpargv0; 25 static char const* long_argv0; 26 /** Error types. */ 27 BEGIN_STATIC_ENUM(int,level_t) 28 ASSERT=4, FATAL=3, 29 EERROR=2, /* ERROR conflicts with the Win32 API :-( */ 30 ERROR_CONT=-2, /* error, but continue running program */ 31 WARNING=-3, 32 WARNING_DEFER=-4, /* warning, but defer (and later possibly omit) displaying it */ 33 NOTICE=-5, 34 NOTICE_DEFER=-6, INFO=-111, DEBUG=-222 35 END_STATIC_ENUM() 36 /** Standard error stream (stderr) of the current process. */ 37 static GenBuffer::Writable * serr; 38 /** Returns address to statically allocated buffer. */ 39 static char const*level2str(level_t level); 40 /** This is the (carefully hidden :-)) method of raising errors (i.e 41 * displaying error messages and terminating the program). 42 * Example usage: 43 * Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires " 44 * "/Predictor " << 1 << (Error*)0; 45 * The error is interpreted according to the current policy. The policy 46 * divides errors into three categories: 47 * 48 * -- secret: nothing happens (even the error message is _not_ printed) 49 * -- recorded: nothing happens (even the error message is _not_ printed), 50 * but the message is remembered for further processing. 51 * -- printed: the error message is printed, and program execution continues 52 * Before printing this message, all recorded errors on the policy stack 53 * are also printed (deepest first). 54 * -- killer: like `printed', but runs cleanup handlers and terminates the 55 * program immediately. 56 * 57 * @param level is one of the constants mentioned above (FATAL, EERROR, 58 * WARNING, NOTICE etc). Can be positive, zero or negative. The larger 59 * the `level', the more severe the error is. The default policy is: 60 * level>=0 errors are killer, -99<=level<=-1 errors are printed, 61 * -199<=level<=-100 are recorded and level<=-200 errors are secret. 62 */ 63 static GenBuffer::Writable& sev(level_t level); 64 65 public: 66 /** The field order is important in this struct, because of the initializers. */ 67 struct Policy { 68 /** All recorded messages. Default: NULL. This means empty. */ 69 SimBuffer::B *record; 70 /** The highest level of Secret category encountered so far. Default: -9999 */ 71 level_t topSecret; 72 /** The highest level of Recorded category encountered so far. Default: -9999 */ 73 level_t topRecorded; 74 /** Lower bound of these categories in this policy. */ 75 level_t killer, printed, recorded; 76 /** Error stream to print printed and killer messages. */ 77 GenBuffer::Writable *err; 78 /** NULL for top policy */ 79 Policy *prev, *next; 80 /** Level of the current error being raised. */ 81 level_t curlev; 82 }; 83 protected: 84 /** Boundaries of the policy stack. */ 85 static Policy *policy_top, *policy_bottom; 86 public: 87 friend GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*); 88 /** Creates a new policy and makes it active by pushing it onto the top of 89 * the policy stack. 90 */ 91 static void pushPolicy(level_t killer_, level_t printed_, level_t recorded_, GenBuffer::Writable *err=(GenBuffer::Writable*)NULLP); 92 /** @return the messages already recorded, and clears the `record' entry 93 * of the current policy. The caller is responsible for deleting the 94 * pointer returned. May return NULLP for empty records. Typical example: 95 * delete Error::getRecorded(); 96 */ 97 static SimBuffer::B *getRecorded(); 98 /** Prints all recorded error messages, and removes the topmost element of 99 * the policy stack. Typical example: 100 * delete Error::getRecorded(); popPolicy(); 101 */ 102 static void popPolicy(); 103 104 /** @example Error::setTopPrinted(Error::ERROR_CONT); suppress anything 105 * below error, such as warnings. 106 */ 107 static void setTopPrinted(level_t printed_); 108 109 static level_t getTopPrinted(); 110 111 /** The Cleanup mechanism is similar to atexit(3) and on_exit(3). This is 112 * just a simple struct with no destructors, virtual methods or inheritance. 113 * 114 * Additional data (char[] buffer) can be allocated and stored right 115 * after the object (this+1), it can be retrieved with getBuf(), and it will 116 * be deleted when the object is deleted by runCleanups(). 117 */ 118 struct Cleanup { 119 /** Must _not_ cause any Errors. 120 * @return an exit code. If larger than the current one, replaces it 121 */ 122 typedef int (*handler_t)(Cleanup*); 123 /** Owned externally. */ 124 handler_t handler; 125 /** size of extra data allocated at getBuf(). */ 126 slen_t bufSize; 127 /** Arbitrary data, owned by `handler': handler' must delete `data' 128 * when called. 129 */ 130 void *data; 131 /** NULLP: no next, end of chain */ 132 Cleanup *next; getBufError::Cleanup133 inline char *getBuf() { return (char*)(this+1); } getSizeError::Cleanup134 inline slen_t getSize() { return bufSize; } 135 }; 136 /** Creates and returns a new Cleanup, and registers it in front of the 137 * existing ones. Copies `handler' and `data' to it. Also allocates `bufSize' bytes 138 * of char[] buffer (at result->getBuf()) owned by the cleanup, but doesn't 139 * initialize the buffer. 140 * 141 * Doesn't take ownership of `handler', takes ownership of `data'. 142 * `handler' must delete `data' or pass on ownership when called, 143 * typically by runCleanups(). 144 */ 145 static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, slen_t bufSize); 146 /** Creates and returns a new Cleanup, and registers it in front of the 147 * existing ones. Copies `handler' and `data' to it. Also allocates 148 * strlen(bufCstr)+1 bytes of char[] buffer (at result->getBuf()) owned by 149 * the cleanup, and initializes it from bufCstr. 150 * 151 * Doesn't take ownership of `handler', takes ownership of `data'. 152 * `handler' must delete `data' or pass on ownership when called, 153 * typically by runCleanups(). 154 */ 155 static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, char const*bufCstr); 156 /** Reverts to the default logging policy, 157 * executes the cleanup handlers (in reverse-registration order), 158 * unregisters and deletes all the cleanups, and returns the 159 * new exit code, which is at least exitCode. 160 */ 161 static int runCleanups(int exitCode); 162 /* Exits from the process with the specified exit code. */ 163 static void cexit(int exitCode); 164 protected: 165 static Cleanup *first_cleanup; 166 }; 167 168 GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*); 169 170 #endif 171