| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /////////////////////////////////////////////////////////////////////////EA-V1
- // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_macro.h $
- // $Author: mhoffe $
- // $Revision: #2 $
- // $DateTime: 2003/07/09 10:57:23 $
- //
- // ©2003 Electronic Arts
- //
- // Debugging macros
- //////////////////////////////////////////////////////////////////////////////
- #ifdef _MSC_VER
- # pragma once
- #endif
- #ifndef DEBUG_MACRO_H // Include guard
- #define DEBUG_MACRO_H
- // I'm putting the documentation for the following macros
- // here because Doxygen otherwise includes the values of each macro
- // in the documentation. I don't want that (it would expose some
- // internals) so I'm putting all comments for the following macros
- // here...
- #ifdef DOXYGEN // defined if Doxygen is running
- /**
- \addtogroup debug_macros Debugging and logging macros
- This module defines a number of macros. Usually only these macros should be
- used to access any debug functionality.
- All these macros are defined if either _DEBUG or _INTERNAL is defined. Otherwise
- all of them (with the exception of DCHECK and DCHECK_MSG) will be removed.
- */
- ///@{
- /**
- \brief Regular assert macro.
-
- This macro will generate an error message on screen if the evaluated expression
- returns false. The user will then have the choice of aborting the program,
- continuing once or continuing with completely ignoring that specific assertion.
- Assertions are completely removed if neither _DEBUG nor _INTERNAL are defined.
- \param expr expression, trigger assert window if false
- */
- #define DASSERT(expr)
- /**
- \brief Assert macro with custom message.
- Like \ref DASSERT but a custom message will be given in addition to the expression.
- The message can be specified in a stream-like notation, e.g.
- \code
- DASSERT_MSG( n>=0 && n<MAX_N, "n:" << n << ", max " << MAX_N);
- \endcode
- For more information see the \ref debug_stream page.
- Assertions are completely removed if neither _DEBUG nor _INTERNAL are defined.
- \param expr expression, trigger assert window if false
- \param msg custom message stream, see \ref debug_stream
- */
- #define DASSERT_MSG(expr,msg)
- /**
- \brief Compile time assertion.
- This assertion will fail during compile time. It can be used anywhere and will
- (of course) remain in release compiles as well. No code is generated in any case.
- If a compile time assertion fails the compiler will give an error message like
- this:
- \code
- debug.cpp(14) : error C2027: use of undefined type 'StaticAssertionFailed<0>'
- \endcode
- If the expression given can't be evaluated at compile time the error message
- looks like this:
- \code
- debug.cpp(15) : error C2027: use of undefined type 'StaticAssertionFailed< ?? >'
- \endcode
- \param expr expression which can be evaluated at compile time
- */
- #define DCTASSERT(expr)
- /**
- \brief Function macro, checks if the given expression is true, returns false if not.
- Additionally a message is written to the log file. This macro is usually used
- like this:
- \code
- if ( !DCHECK( n>=0 && n<MAX_N ) ) return;
- \endcode
- \note Checks will remain in place even in release builds!
- \param expr expression which will always be checked
- */
- #define DCHECK(expr)
- /**
- \brief Function macro, \ref DCHECK with additional message on failure.
- For more information see the \ref debug_stream page.
- \note Even though the expression check will remain in place in release builds the
- \a msg part is completely removed.
- \param expr expression which will always be checked
- \param msg custom message stream, see \ref debug_stream
- */
- #define DCHECK_MSG(expr,msg)
- /**
- \brief Macro for precondition-checks.
- Internally expands to
- \code
- if (!DCHECK(!(cond)))
- \endcode
- so it can be used e.g. like this:
- \code
- DFAIL_IF(!ptrval) return;
- \endcode
- \param cond condition which is checked for failure
- */
- #define DFAIL_IF(cond)
- /**
- \brief Convenience macro, \ref DFAIL_IF with additional message on failure.
- Internally expands to
- \code
- if (!DCHECK_MSG(!(cond),msg))
- \endcode
- so it can be used e.g. like this:
- \code
- DFAIL_IF_MSG(!ptrval,"pointer must not be NULL") return;
- \endcode
- \param cond condition which is checked for failure
- \param msg custom message stream, see \ref debug_stream
- */
- #define DFAIL_IF_MSG(cond,msg)
- /**
- \brief Writes a message to the log file.
- It also generates a logging group with the name of the current file (but without
- path or extension), e.g. if DLOG("hello world") is written in here a logging group
- called 'debug' would be created.
- Logs can be turned on and off based on individual logging groups.
- \param what message, see \ref debug_stream
- */
- #define DLOG(what)
- /**
- \brief Adds a description for the current file if used for logging.
- \note This macro must be used in a CPP file in file scope only.
- \param descr a short static description of what gets logged in the current file
- */
- #define DLOG_DESCR(descr)
- /**
- \brief Writes a message to the log file using a custom log group.
- Works just like \ref DLOG but instead of using the current file as a logging group
- the logging group is explicitly specified.
- \note Specifiy the group directly without quotes, e.g.
- \code
- DLOG_GROUP(my_log_group,"hello world")
- \endcode
- \param group logging group, without quotes
- \param what message, see \ref debug_stream
- */
- #define DLOG_GROUP(group,what)
- /**
- \brief Adds a description for a custom log group
- \note This macro must be used in a CPP file in file scope only.
- \param group logging group, without quotes
- \param descr a short static description of what gets logged in the specified log group
- */
- #define DLOG_GROUP_DESCR(group,descr)
- /**
- \brief Unconditionally aborts the program in debug/internal builds.
- A DCRASH can not be disabled by the user.
- \param msg custom message stream, see \ref debug_stream
- */
- #define DCRASH(msg)
- /**
- \brief Unconditional program exit that is active in release builds as well.
- \note In a release build the crash message will not include the file name or
- line number where the DCRASH_RELEASE was specified.
- \param msg custom message stream, see \ref debug_stream
- */
- #define DCRASH_RELEASE(msg)
- /**
- \brief Unconditional assert.
- Basically makes sense only as default clause in switch statements to make
- sure that no case is missed, e.g.
- \code
- switch(n)
- {
- case MY_DEF_VAL_A:
- // ...
- break;
- case MY_DEF_VAL_B:
- // ...
- break;
- default:
- DFAIL();
- }
- \endcode
- Gets removed in release builds.
- */
- #define DFAIL()
- /**
- \brief Function macro, determines if logging is active for current file or not.
- This function macro can be safely used without any #ifdefs:
- \code
- if (D_ISLOG())
- {
- // do some computationally expensive logging here...
- }
- \endcode
- In release builds this macro expands to \a false effectively removing
- the whole section.
- \return true if logging is active, false if not
- */
- #define D_ISLOG()
- /**
- \brief Function macro, determines if logging is active for the specified log group or not.
- Works just like \ref D_ISLOG but instead of using the current file as a logging group
- the logging group is explicitly specified.
- \param group logging group, without quotes
- \return true if logging is active, false if not
- */
- #define D_ISLOG_GROUP(group)
- ///@}
- #elif defined(_DEBUG) || defined(_INTERNAL)
- #define DASSERT(expr) \
- ((void)( Debug::SkipNext() || \
- (expr) || \
- Debug::AssertBegin(__FILE__,__LINE__,#expr).AssertDone() ))
- #define DASSERT_MSG(expr,msg) \
- ((void)( Debug::SkipNext() || \
- (expr) || \
- ( Debug::AssertBegin(__FILE__,__LINE__,#expr) << ": " << msg ).AssertDone() ))
- #define DCHECK(expr) \
- ( (expr) || \
- Debug::SkipNext() || \
- Debug::CheckBegin(__FILE__,__LINE__,#expr).CheckDone() )
- #define DCHECK_MSG(expr,msg) \
- ( (expr) || \
- Debug::SkipNext() || \
- ( Debug::CheckBegin(__FILE__,__LINE__,#expr) << ": " << msg ).CheckDone() )
- #define DFAIL_IF(cond) \
- if (!DCHECK(!(cond)))
- #define DFAIL_IF_MSG(cond,msg) \
- if (!DCHECK_MSG(!(cond),msg))
- #define DLOG(what) \
- ((void)( Debug::SkipNext() || \
- ( Debug::LogBegin(__FILE__) << what ).LogDone() ))
- #define DLOG_DESCR(descr) \
- static Debug::LogDescription _LogDescr_FILE(__FILE__,descr);
- #define DLOG_GROUP(group,what) \
- ((void)( Debug::SkipNext() || \
- ( Debug::LogBegin(#group) << what ).LogDone() ))
- #define DLOG_GROUP_DESCR(group,descr) \
- static Debug::LogDescription(#group,descr) _LogDescr_Grp_##group
- #define DCRASH(msg) \
- (Debug::SkipNext() || (Debug::CrashBegin(__FILE__,__LINE__) << msg).CrashDone(false))
- #define DCRASH_RELEASE(msg) \
- (Debug::SkipNext(),(Debug::CrashBegin(__FILE__,__LINE__) << msg).CrashDone(true))
- #define DFAIL() \
- Debug::AssertBegin(__FILE__,__LINE__,NULL).AssertDone()
- #define D_ISLOG() \
- Debug::IsLogEnabled(__FILE__)
- #define D_ISLOG_GROUP(group) \
- Debug::IsLogEnabled(#group)
- #else
- #define DASSERT(expr) ((void)0)
- #define DASSERT_MSG(expr,msg) ((void)0)
- #define DCHECK(expr) (expr)
- #define DCHECK_MSG(expr,msg) (expr)
- #define DFAIL_IF(cond) if (cond)
- #define DFAIL_IF_MSG(cond,msg) if (cond)
- #define DLOG(what) ((void)0)
- #define DLOG_DESCR(descr)
- #define DLOG_GROUP(group,what) ((void)0)
- #define DLOG_GROUP_DESCR(g,d)
- #define DCRASH(msg) ((void)0)
- #define DCRASH_RELEASE(msg) (Debug::SkipNext(),(Debug::CrashBegin(NULL,0) << msg).CrashDone(true))
- #define DFAIL() ((void)0)
- #define D_ISLOG() false
- #define D_ISLOG_GROUP(group) false
- #endif
- // put these helper templates in a namespace...
- namespace _Debug
- {
- template<bool> struct StaticAssertionFailed;
- template<> struct StaticAssertionFailed<true> {};
- template<int x> struct StaticAssertionTest {};
- #define DCTASSERT(expr) typedef ::_Debug::StaticAssertionTest< \
- sizeof(::_Debug::StaticAssertionFailed< (bool)(expr) >) \
- > DebugStaticAssertTypedef__;
- };
- // These are stolen from the WW3D Debug file. REALLY useful. :-)
- #define STRING_IT(a) #a
- #define TOKEN_IT(a) STRING_IT(,##a)
- /**
- The macro MESSAGE allows user to put:
- \code
- #pragma MESSAGE("Hello world")
- \endcode
- anywhere in a source file. The message:
- \code
- sourcefname.cpp (123) : Hello world
- \endcode
- would be printed if put in sourcefname.cpp on line 123 in compile window like an error.
- You can then use next/prev error hot keys to see where comment is. It is not an error and
- will be printed everytime it is compiled. Very useful to put comments in code that cannot
- be forgotten.
- */
- #define MESSAGE(a) message (__FILE__ "(" TOKEN_IT(__LINE__) ") : " a)
- #endif // DEBUG_MACRO_H
|