diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/sam2p/error.hpp |
Initial commit
Diffstat (limited to 'graphics/sam2p/error.hpp')
-rw-r--r-- | graphics/sam2p/error.hpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/graphics/sam2p/error.hpp b/graphics/sam2p/error.hpp new file mode 100644 index 0000000000..af9a58ed20 --- /dev/null +++ b/graphics/sam2p/error.hpp @@ -0,0 +1,170 @@ +/* error.hpp -- handling errors/warnings etc. + * by pts@fazekas.hu at Fri Mar 1 11:32:36 CET 2002 + */ + +#ifdef __GNUC__ +#ifndef __clang__ +#pragma interface +#endif +#endif + +#ifndef ERROR_HPP +#define ERROR_HPP 1 + +#include "config2.h" +#include "gensi.hpp" + +/** This may be usafe if an error happens inside an error. Usage: + * Error::sev(Error::WARNING) << "Zero-length image." << (Error*)0; + */ +class Error { + public: + static char const* banner0; + static char const* argv0; + static char const* tmpargv0; + static char const* long_argv0; + /** Error types. */ + BEGIN_STATIC_ENUM(int,level_t) + ASSERT=4, FATAL=3, + EERROR=2, /* ERROR conflicts with the Win32 API :-( */ + ERROR_CONT=-2, /* error, but continue running program */ + WARNING=-3, + WARNING_DEFER=-4, /* warning, but defer (and later possibly omit) displaying it */ + NOTICE=-5, + NOTICE_DEFER=-6, INFO=-111, DEBUG=-222 + END_STATIC_ENUM() + /** Standard error stream (stderr) of the current process. */ + static GenBuffer::Writable * serr; + /** Returns address to statically allocated buffer. */ + static char const*level2str(level_t level); + /** This is the (carefully hidden :-)) method of raising errors (i.e + * displaying error messages and terminating the program). + * Example usage: + * Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires " + * "/Predictor " << 1 << (Error*)0; + * The error is interpreted according to the current policy. The policy + * divides errors into three categories: + * + * -- secret: nothing happens (even the error message is _not_ printed) + * -- recorded: nothing happens (even the error message is _not_ printed), + * but the message is remembered for further processing. + * -- printed: the error message is printed, and program execution continues + * Before printing this message, all recorded errors on the policy stack + * are also printed (deepest first). + * -- killer: like `printed', but runs cleanup handlers and terminates the + * program immediately. + * + * @param level is one of the constants mentioned above (FATAL, EERROR, + * WARNING, NOTICE etc). Can be positive, zero or negative. The larger + * the `level', the more severe the error is. The default policy is: + * level>=0 errors are killer, -99<=level<=-1 errors are printed, + * -199<=level<=-100 are recorded and level<=-200 errors are secret. + */ + static GenBuffer::Writable& sev(level_t level); + + public: + /** The field order is important in this struct, because of the initializers. */ + struct Policy { + /** All recorded messages. Default: NULL. This means empty. */ + SimBuffer::B *record; + /** The highest level of Secret category encountered so far. Default: -9999 */ + level_t topSecret; + /** The highest level of Recorded category encountered so far. Default: -9999 */ + level_t topRecorded; + /** Lower bound of these categories in this policy. */ + level_t killer, printed, recorded; + /** Error stream to print printed and killer messages. */ + GenBuffer::Writable *err; + /** NULL for top policy */ + Policy *prev, *next; + /** Level of the current error being raised. */ + level_t curlev; + }; + protected: + /** Boundaries of the policy stack. */ + static Policy *policy_top, *policy_bottom; + public: + friend GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*); + /** Creates a new policy and makes it active by pushing it onto the top of + * the policy stack. + */ + static void pushPolicy(level_t killer_, level_t printed_, level_t recorded_, GenBuffer::Writable *err=(GenBuffer::Writable*)NULLP); + /** @return the messages already recorded, and clears the `record' entry + * of the current policy. The caller is responsible for deleting the + * pointer returned. May return NULLP for empty records. Typical example: + * delete Error::getRecorded(); + */ + static SimBuffer::B *getRecorded(); + /** Prints all recorded error messages, and removes the topmost element of + * the policy stack. Typical example: + * delete Error::getRecorded(); popPolicy(); + */ + static void popPolicy(); + + /** @example Error::setTopPrinted(Error::ERROR_CONT); suppress anything + * below error, such as warnings. + */ + static void setTopPrinted(level_t printed_); + + static level_t getTopPrinted(); + + /** The Cleanup mechanism is similar to atexit(3) and on_exit(3). This is + * just a simple struct with no destructors, virtual methods or inheritance. + * + * Additional data (char[] buffer) can be allocated and stored right + * after the object (this+1), it can be retrieved with getBuf(), and it will + * be deleted when the object is deleted by runCleanups(). + */ + struct Cleanup { + /** Must _not_ cause any Errors. + * @return an exit code. If larger than the current one, replaces it + */ + typedef int (*handler_t)(Cleanup*); + /** Owned externally. */ + handler_t handler; + /** size of extra data allocated at getBuf(). */ + slen_t bufSize; + /** Arbitrary data, owned by `handler': handler' must delete `data' + * when called. + */ + void *data; + /** NULLP: no next, end of chain */ + Cleanup *next; + inline char *getBuf() { return (char*)(this+1); } + inline slen_t getSize() { return bufSize; } + }; + /** Creates and returns a new Cleanup, and registers it in front of the + * existing ones. Copies `handler' and `data' to it. Also allocates `bufSize' bytes + * of char[] buffer (at result->getBuf()) owned by the cleanup, but doesn't + * initialize the buffer. + * + * Doesn't take ownership of `handler', takes ownership of `data'. + * `handler' must delete `data' or pass on ownership when called, + * typically by runCleanups(). + */ + static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, slen_t bufSize); + /** Creates and returns a new Cleanup, and registers it in front of the + * existing ones. Copies `handler' and `data' to it. Also allocates + * strlen(bufCstr)+1 bytes of char[] buffer (at result->getBuf()) owned by + * the cleanup, and initializes it from bufCstr. + * + * Doesn't take ownership of `handler', takes ownership of `data'. + * `handler' must delete `data' or pass on ownership when called, + * typically by runCleanups(). + */ + static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, char const*bufCstr); + /** Reverts to the default logging policy, + * executes the cleanup handlers (in reverse-registration order), + * unregisters and deletes all the cleanups, and returns the + * new exit code, which is at least exitCode. + */ + static int runCleanups(int exitCode); + /* Exits from the process with the specified exit code. */ + static void cexit(int exitCode); + protected: + static Cleanup *first_cleanup; +}; + +GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*); + +#endif |