// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // % Project : GUSI - Grand Unified Socket Interface // % File : GUSIDiag.nw - Assertions and diagnostics // % Author : Matthias Neeracher // % Language : C++ // % // % $Log$ // % Revision 1.1.1.1 2001/03/03 21:50:10 chombier // % Initial import // % // % Revision 1.12 2000/06/12 04:20:58 neeri // % Introduce GUSI_*printf // % // % Revision 1.11 2000/05/23 06:58:04 neeri // % Improve formatting // % // % Revision 1.10 1999/08/26 05:45:01 neeri // % Fixes for literate edition of source code // % // % Revision 1.9 1999/08/02 07:02:43 neeri // % Support for asynchronous errors and other socket options // % // % Revision 1.8 1999/05/29 06:26:42 neeri // % Fixed header guards // % // % Revision 1.7 1999/04/10 04:45:47 neeri // % Add DCon stubs // % // % Revision 1.6 1999/03/17 09:05:07 neeri // % Added GUSITimer, expanded docs // % // % Revision 1.5 1999/02/25 03:49:00 neeri // % Switched to DCon for logging // % // % Revision 1.4 1998/01/25 20:53:53 neeri // % Engine implemented, except for signals & scheduling // % // % Revision 1.3 1996/12/16 02:17:20 neeri // % Tune messages // % // % Revision 1.2 1996/11/24 12:52:07 neeri // % Added GUSIPipeSockets // % // % Revision 1.1.1.1 1996/11/03 02:43:32 neeri // % Imported into CVS // % // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // // \chapter{Assertions and diagnostic messages} // // GUSI reports on three kinds of error conditions: // // \begin{itemize} // \item {\bf Internal} errors are usually caused by bugs in GUSI. They should be // considered fatal. // \item {\bf Client} errors are caused by calling GUSI routines with bad // parameters. They are typically handled by returning an appropriate error // code. // \item {\bf External} errors are caused by various OS and Network related // problems. Typically, they are also handled by returning an appropriate // error code. // \end{itemize} // // If you feel lucky, you can turn off the checking for internal and client errors, // but external errors will always be checked. // // = #ifndef _GUSIDiag_ #define _GUSIDiag_ #include #include #include #include __BEGIN_DECLS // \section{Definition of diagnostics} // // Depending on the diagnostic level, messages get printed to the DCon console. // // = extern char * GUSI_diag_log; // Printing is done by passing an argument list to [[GUSI_log]]. To simplify the job // for the diagnostic macros, [[GUSI_log]] returns a [[bool]] value which is // always [[false]]. [[GUSI_break]] stops with a [[DebugStr]] call. [[GUSI_pos]] // establishes the source code position for diagnostic messages. // instead of logging. // // = bool GUSI_pos(const char * file, int line); bool GUSI_log(const char * format, ...); bool GUSI_break(const char * format, ...); // There are four levels of diagnostic handling: // \begin{itemize} // \item [[GUSI_DIAG_RECKLESS]] totally ignores all internal and client errors. This // setting is not recommended. // \item [[GUSI_DIAG_RELAXED]] ignores internal errors, but checks client errors. This // setting is probably the best for production code. // \item [[GUSI_DIAG_CAUTIOUS]] checks and logs internal and client errors. This // setting is best for GUSI client development. // \item [[GUSI_DIAG_PARANOID]] immediately stops at internal errors, checks and // logs client and external errors. This is the preferred setting for GUSI // internal development. // \end{itemize} // // // = #define GUSI_DIAG_RECKLESS 0 #define GUSI_DIAG_RELAXED 1 #define GUSI_DIAG_CAUTIOUS 2 #define GUSI_DIAG_PARANOID 3 // [[GUSI_DIAG]] is defined to the diagnostic level. It can be overridden on a // module by module basis, or by changing the default setting here. // [[GUSI_MESSAGE_LEVEL]] determines how important a message has to be to print it. // [[GUSI_LOG_POS]] determines whether we want to log the code position. // // = #ifndef GUSI_DIAG #define GUSI_DIAG GUSI_DIAG_PARANOID #endif #ifndef GUSI_LOG_POS #define GUSI_LOG_POS 0 #endif #ifndef GUSI_MESSAGE_LEVEL #define GUSI_MESSAGE_LEVEL 3 #endif // = #if GUSI_LOG_POS #define GUSI_POS GUSI_pos(__FILE__, __LINE__) #define GUSI_LOG GUSI_POS || GUSI_log #else #define GUSI_LOG GUSI_log #endif #define GUSI_BREAK GUSI_break // = #if GUSI_DIAG == GUSI_DIAG_RECKLESS // [[GUSI_DIAG_RECKLESS]] only checks for external errors. // // = #define GUSI_ASSERT_INTERNAL(COND, ARGLIST) true #define GUSI_ASSERT_CLIENT(COND, ARGLIST) true #define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) (COND) #define GUSI_SASSERT_INTERNAL(COND, MSG) true #define GUSI_SASSERT_CLIENT(COND, MSG) true #define GUSI_SASSERT_EXTERNAL(COND, MSG) (COND) #elif GUSI_DIAG == GUSI_DIAG_RELAXED // [[GUSI_DIAG_RELAXED]] ignores internal errors, but checks client errors. // // = #define GUSI_ASSERT_INTERNAL(COND, ARGLIST) true #define GUSI_ASSERT_CLIENT(COND, ARGLIST) (COND) #define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) (COND) #define GUSI_SASSERT_INTERNAL(COND, MSG) true #define GUSI_SASSERT_CLIENT(COND, MSG) (COND) #define GUSI_SASSERT_EXTERNAL(COND, MSG) (COND) #elif GUSI_DIAG == GUSI_DIAG_CAUTIOUS // [[GUSI_DIAG_CAUTIOUS]] checks and logs internal and client errors. // // = #define GUSI_ASSERT_INTERNAL(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST) #define GUSI_ASSERT_CLIENT(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST) #define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) (COND) #define GUSI_SASSERT_INTERNAL(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG)) #define GUSI_SASSERT_CLIENT(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG)) #define GUSI_SASSERT_EXTERNAL(COND, MSG) (COND) #elif GUSI_DIAG == GUSI_DIAG_PARANOID // [[GUSI_DIAG_PARANOID]] immediately stops at internal errors, checks and // logs client and external errors. // // = #define GUSI_ASSERT_INTERNAL(COND, ARGLIST) ((COND) || GUSI_BREAK ARGLIST) #define GUSI_ASSERT_CLIENT(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST) #define GUSI_ASSERT_EXTERNAL(COND, ARGLIST) ((COND) || GUSI_LOG ARGLIST) #define GUSI_SASSERT_INTERNAL(COND, MSG) ((COND) || GUSI_BREAK ("%s", (MSG))) #define GUSI_SASSERT_CLIENT(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG)) #define GUSI_SASSERT_EXTERNAL(COND, MSG) ((COND) || GUSI_LOG ("%s", MSG)) #else #error "GUSI_DIAG defined to illegal value: " GUSI_DIAG #endif // There are 11 different diagnostic macros. [[GUSI_ASSERT_INTERNAL]], // [[GUSI_ASSERT_CLIENT]] and [[GUSI_ASSERT_EXTERNAL]] check for internal, // client, and external errors, respectively. Their first argument is a // conditional expression which when [[false]] indicates that an error // happened. [[GUSI_MESSAGE]] has the same logging status as // [[GUSI_ASSERT_EXTERNAL]], but does not check any conditions. The [[SASSERT]] // and [[SMESSAGE]] variants do the same checking, but only take a simple // message instead of an argument list. The [[CASSERT]] variants simply output // the condition as the message. // // = #define GUSI_CASSERT_INTERNAL(COND) \ GUSI_SASSERT_INTERNAL(COND, "(" #COND ") -- assertion failed.\n" ) #define GUSI_CASSERT_CLIENT(COND) \ GUSI_SASSERT_CLIENT(COND, "(" #COND ") -- assertion failed.\n" ) #define GUSI_CASSERT_EXTERNAL(COND) \ GUSI_SASSERT_EXTERNAL(COND, "(" #COND ") -- assertion failed.\n" ) #define GUSI_MESSAGE1(ARGLIST) \ GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>1, ARGLIST) #define GUSI_SMESSAGE1(MSG) \ GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>1, MSG) #define GUSI_MESSAGE2(ARGLIST) \ GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>2, ARGLIST) #define GUSI_SMESSAGE2(MSG) \ GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>2, MSG) #define GUSI_MESSAGE3(ARGLIST) \ GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>3, ARGLIST) #define GUSI_SMESSAGE3(MSG) \ GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>3, MSG) #define GUSI_MESSAGE4(ARGLIST) \ GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>4, ARGLIST) #define GUSI_SMESSAGE4(MSG) \ GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>4, MSG) #define GUSI_MESSAGE5(ARGLIST) \ GUSI_ASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>5, ARGLIST) #define GUSI_SMESSAGE5(MSG) \ GUSI_SASSERT_EXTERNAL(GUSI_MESSAGE_LEVEL>5, MSG) #define GUSI_MESSAGE(ARGLIST) GUSI_MESSAGE3(ARGLIST) #define GUSI_SMESSAGE(MSG) GUSI_SMESSAGE3(MSG) __END_DECLS #endif /* _GUSIDiag_ */