debug_macro.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /////////////////////////////////////////////////////////////////////////EA-V1
  19. // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_macro.h $
  20. // $Author: mhoffe $
  21. // $Revision: #2 $
  22. // $DateTime: 2003/07/09 10:57:23 $
  23. //
  24. // ©2003 Electronic Arts
  25. //
  26. // Debugging macros
  27. //////////////////////////////////////////////////////////////////////////////
  28. #ifdef _MSC_VER
  29. # pragma once
  30. #endif
  31. #ifndef DEBUG_MACRO_H // Include guard
  32. #define DEBUG_MACRO_H
  33. // I'm putting the documentation for the following macros
  34. // here because Doxygen otherwise includes the values of each macro
  35. // in the documentation. I don't want that (it would expose some
  36. // internals) so I'm putting all comments for the following macros
  37. // here...
  38. #ifdef DOXYGEN // defined if Doxygen is running
  39. /**
  40. \addtogroup debug_macros Debugging and logging macros
  41. This module defines a number of macros. Usually only these macros should be
  42. used to access any debug functionality.
  43. All these macros are defined if either _DEBUG or _INTERNAL is defined. Otherwise
  44. all of them (with the exception of DCHECK and DCHECK_MSG) will be removed.
  45. */
  46. ///@{
  47. /**
  48. \brief Regular assert macro.
  49. This macro will generate an error message on screen if the evaluated expression
  50. returns false. The user will then have the choice of aborting the program,
  51. continuing once or continuing with completely ignoring that specific assertion.
  52. Assertions are completely removed if neither _DEBUG nor _INTERNAL are defined.
  53. \param expr expression, trigger assert window if false
  54. */
  55. #define DASSERT(expr)
  56. /**
  57. \brief Assert macro with custom message.
  58. Like \ref DASSERT but a custom message will be given in addition to the expression.
  59. The message can be specified in a stream-like notation, e.g.
  60. \code
  61. DASSERT_MSG( n>=0 && n<MAX_N, "n:" << n << ", max " << MAX_N);
  62. \endcode
  63. For more information see the \ref debug_stream page.
  64. Assertions are completely removed if neither _DEBUG nor _INTERNAL are defined.
  65. \param expr expression, trigger assert window if false
  66. \param msg custom message stream, see \ref debug_stream
  67. */
  68. #define DASSERT_MSG(expr,msg)
  69. /**
  70. \brief Compile time assertion.
  71. This assertion will fail during compile time. It can be used anywhere and will
  72. (of course) remain in release compiles as well. No code is generated in any case.
  73. If a compile time assertion fails the compiler will give an error message like
  74. this:
  75. \code
  76. debug.cpp(14) : error C2027: use of undefined type 'StaticAssertionFailed<0>'
  77. \endcode
  78. If the expression given can't be evaluated at compile time the error message
  79. looks like this:
  80. \code
  81. debug.cpp(15) : error C2027: use of undefined type 'StaticAssertionFailed< ?? >'
  82. \endcode
  83. \param expr expression which can be evaluated at compile time
  84. */
  85. #define DCTASSERT(expr)
  86. /**
  87. \brief Function macro, checks if the given expression is true, returns false if not.
  88. Additionally a message is written to the log file. This macro is usually used
  89. like this:
  90. \code
  91. if ( !DCHECK( n>=0 && n<MAX_N ) ) return;
  92. \endcode
  93. \note Checks will remain in place even in release builds!
  94. \param expr expression which will always be checked
  95. */
  96. #define DCHECK(expr)
  97. /**
  98. \brief Function macro, \ref DCHECK with additional message on failure.
  99. For more information see the \ref debug_stream page.
  100. \note Even though the expression check will remain in place in release builds the
  101. \a msg part is completely removed.
  102. \param expr expression which will always be checked
  103. \param msg custom message stream, see \ref debug_stream
  104. */
  105. #define DCHECK_MSG(expr,msg)
  106. /**
  107. \brief Macro for precondition-checks.
  108. Internally expands to
  109. \code
  110. if (!DCHECK(!(cond)))
  111. \endcode
  112. so it can be used e.g. like this:
  113. \code
  114. DFAIL_IF(!ptrval) return;
  115. \endcode
  116. \param cond condition which is checked for failure
  117. */
  118. #define DFAIL_IF(cond)
  119. /**
  120. \brief Convenience macro, \ref DFAIL_IF with additional message on failure.
  121. Internally expands to
  122. \code
  123. if (!DCHECK_MSG(!(cond),msg))
  124. \endcode
  125. so it can be used e.g. like this:
  126. \code
  127. DFAIL_IF_MSG(!ptrval,"pointer must not be NULL") return;
  128. \endcode
  129. \param cond condition which is checked for failure
  130. \param msg custom message stream, see \ref debug_stream
  131. */
  132. #define DFAIL_IF_MSG(cond,msg)
  133. /**
  134. \brief Writes a message to the log file.
  135. It also generates a logging group with the name of the current file (but without
  136. path or extension), e.g. if DLOG("hello world") is written in here a logging group
  137. called 'debug' would be created.
  138. Logs can be turned on and off based on individual logging groups.
  139. \param what message, see \ref debug_stream
  140. */
  141. #define DLOG(what)
  142. /**
  143. \brief Adds a description for the current file if used for logging.
  144. \note This macro must be used in a CPP file in file scope only.
  145. \param descr a short static description of what gets logged in the current file
  146. */
  147. #define DLOG_DESCR(descr)
  148. /**
  149. \brief Writes a message to the log file using a custom log group.
  150. Works just like \ref DLOG but instead of using the current file as a logging group
  151. the logging group is explicitly specified.
  152. \note Specifiy the group directly without quotes, e.g.
  153. \code
  154. DLOG_GROUP(my_log_group,"hello world")
  155. \endcode
  156. \param group logging group, without quotes
  157. \param what message, see \ref debug_stream
  158. */
  159. #define DLOG_GROUP(group,what)
  160. /**
  161. \brief Adds a description for a custom log group
  162. \note This macro must be used in a CPP file in file scope only.
  163. \param group logging group, without quotes
  164. \param descr a short static description of what gets logged in the specified log group
  165. */
  166. #define DLOG_GROUP_DESCR(group,descr)
  167. /**
  168. \brief Unconditionally aborts the program in debug/internal builds.
  169. A DCRASH can not be disabled by the user.
  170. \param msg custom message stream, see \ref debug_stream
  171. */
  172. #define DCRASH(msg)
  173. /**
  174. \brief Unconditional program exit that is active in release builds as well.
  175. \note In a release build the crash message will not include the file name or
  176. line number where the DCRASH_RELEASE was specified.
  177. \param msg custom message stream, see \ref debug_stream
  178. */
  179. #define DCRASH_RELEASE(msg)
  180. /**
  181. \brief Unconditional assert.
  182. Basically makes sense only as default clause in switch statements to make
  183. sure that no case is missed, e.g.
  184. \code
  185. switch(n)
  186. {
  187. case MY_DEF_VAL_A:
  188. // ...
  189. break;
  190. case MY_DEF_VAL_B:
  191. // ...
  192. break;
  193. default:
  194. DFAIL();
  195. }
  196. \endcode
  197. Gets removed in release builds.
  198. */
  199. #define DFAIL()
  200. /**
  201. \brief Function macro, determines if logging is active for current file or not.
  202. This function macro can be safely used without any #ifdefs:
  203. \code
  204. if (D_ISLOG())
  205. {
  206. // do some computationally expensive logging here...
  207. }
  208. \endcode
  209. In release builds this macro expands to \a false effectively removing
  210. the whole section.
  211. \return true if logging is active, false if not
  212. */
  213. #define D_ISLOG()
  214. /**
  215. \brief Function macro, determines if logging is active for the specified log group or not.
  216. Works just like \ref D_ISLOG but instead of using the current file as a logging group
  217. the logging group is explicitly specified.
  218. \param group logging group, without quotes
  219. \return true if logging is active, false if not
  220. */
  221. #define D_ISLOG_GROUP(group)
  222. ///@}
  223. #elif defined(_DEBUG) || defined(_INTERNAL)
  224. #define DASSERT(expr) \
  225. ((void)( Debug::SkipNext() || \
  226. (expr) || \
  227. Debug::AssertBegin(__FILE__,__LINE__,#expr).AssertDone() ))
  228. #define DASSERT_MSG(expr,msg) \
  229. ((void)( Debug::SkipNext() || \
  230. (expr) || \
  231. ( Debug::AssertBegin(__FILE__,__LINE__,#expr) << ": " << msg ).AssertDone() ))
  232. #define DCHECK(expr) \
  233. ( (expr) || \
  234. Debug::SkipNext() || \
  235. Debug::CheckBegin(__FILE__,__LINE__,#expr).CheckDone() )
  236. #define DCHECK_MSG(expr,msg) \
  237. ( (expr) || \
  238. Debug::SkipNext() || \
  239. ( Debug::CheckBegin(__FILE__,__LINE__,#expr) << ": " << msg ).CheckDone() )
  240. #define DFAIL_IF(cond) \
  241. if (!DCHECK(!(cond)))
  242. #define DFAIL_IF_MSG(cond,msg) \
  243. if (!DCHECK_MSG(!(cond),msg))
  244. #define DLOG(what) \
  245. ((void)( Debug::SkipNext() || \
  246. ( Debug::LogBegin(__FILE__) << what ).LogDone() ))
  247. #define DLOG_DESCR(descr) \
  248. static Debug::LogDescription _LogDescr_FILE(__FILE__,descr);
  249. #define DLOG_GROUP(group,what) \
  250. ((void)( Debug::SkipNext() || \
  251. ( Debug::LogBegin(#group) << what ).LogDone() ))
  252. #define DLOG_GROUP_DESCR(group,descr) \
  253. static Debug::LogDescription(#group,descr) _LogDescr_Grp_##group
  254. #define DCRASH(msg) \
  255. (Debug::SkipNext() || (Debug::CrashBegin(__FILE__,__LINE__) << msg).CrashDone(false))
  256. #define DCRASH_RELEASE(msg) \
  257. (Debug::SkipNext(),(Debug::CrashBegin(__FILE__,__LINE__) << msg).CrashDone(true))
  258. #define DFAIL() \
  259. Debug::AssertBegin(__FILE__,__LINE__,NULL).AssertDone()
  260. #define D_ISLOG() \
  261. Debug::IsLogEnabled(__FILE__)
  262. #define D_ISLOG_GROUP(group) \
  263. Debug::IsLogEnabled(#group)
  264. #else
  265. #define DASSERT(expr) ((void)0)
  266. #define DASSERT_MSG(expr,msg) ((void)0)
  267. #define DCHECK(expr) (expr)
  268. #define DCHECK_MSG(expr,msg) (expr)
  269. #define DFAIL_IF(cond) if (cond)
  270. #define DFAIL_IF_MSG(cond,msg) if (cond)
  271. #define DLOG(what) ((void)0)
  272. #define DLOG_DESCR(descr)
  273. #define DLOG_GROUP(group,what) ((void)0)
  274. #define DLOG_GROUP_DESCR(g,d)
  275. #define DCRASH(msg) ((void)0)
  276. #define DCRASH_RELEASE(msg) (Debug::SkipNext(),(Debug::CrashBegin(NULL,0) << msg).CrashDone(true))
  277. #define DFAIL() ((void)0)
  278. #define D_ISLOG() false
  279. #define D_ISLOG_GROUP(group) false
  280. #endif
  281. // put these helper templates in a namespace...
  282. namespace _Debug
  283. {
  284. template<bool> struct StaticAssertionFailed;
  285. template<> struct StaticAssertionFailed<true> {};
  286. template<int x> struct StaticAssertionTest {};
  287. #define DCTASSERT(expr) typedef ::_Debug::StaticAssertionTest< \
  288. sizeof(::_Debug::StaticAssertionFailed< (bool)(expr) >) \
  289. > DebugStaticAssertTypedef__;
  290. };
  291. // These are stolen from the WW3D Debug file. REALLY useful. :-)
  292. #define STRING_IT(a) #a
  293. #define TOKEN_IT(a) STRING_IT(,##a)
  294. /**
  295. The macro MESSAGE allows user to put:
  296. \code
  297. #pragma MESSAGE("Hello world")
  298. \endcode
  299. anywhere in a source file. The message:
  300. \code
  301. sourcefname.cpp (123) : Hello world
  302. \endcode
  303. would be printed if put in sourcefname.cpp on line 123 in compile window like an error.
  304. You can then use next/prev error hot keys to see where comment is. It is not an error and
  305. will be printed everytime it is compiled. Very useful to put comments in code that cannot
  306. be forgotten.
  307. */
  308. #define MESSAGE(a) message (__FILE__ "(" TOKEN_IT(__LINE__) ") : " a)
  309. #endif // DEBUG_MACRO_H