debug_debug.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236
  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_debug.h $
  20. // $Author: mhoffe $
  21. // $Revision: #1 $
  22. // $DateTime: 2003/07/03 11:55:26 $
  23. //
  24. // ©2003 Electronic Arts
  25. //
  26. // main Debug object (singleton)
  27. //////////////////////////////////////////////////////////////////////////////
  28. #ifdef _MSC_VER
  29. # pragma once
  30. #endif
  31. #ifndef DEBUG_DEBUG_H // Include guard
  32. #define DEBUG_DEBUG_H
  33. // this makes sure that whenever this header is included
  34. // the accompanying OBJ file is linked in as well
  35. #pragma comment(linker,"/include:___DebugIncludeInLink1")
  36. /**
  37. \class Debug debug.h <rts/debug.h>
  38. \brief Debug module main class (singleton).
  39. */
  40. class Debug
  41. {
  42. // necessary because all debug commands operate directly on this class
  43. friend class DebugCmdInterfaceDebug;
  44. // necessary because exception handler needs direct access
  45. friend class DebugExceptionhandler;
  46. public:
  47. enum
  48. {
  49. /// maximum number of times a check can be hit before it is turned off
  50. MAX_CHECK_HITS = 20
  51. };
  52. /**
  53. \brief HRESULT translator callback function type.
  54. See \ref Debug::AddHResultTranslator for more information.
  55. \param debug Debug instance where info can be written to
  56. \param hresult current HRESULT value
  57. \param user user value passed into AddHResultTranslator
  58. \return true if value translated and no more translators should be called,
  59. false if next translator should be tried
  60. */
  61. typedef bool (*HResultTranslator)(Debug &debug, long hresult, void *user);
  62. /**
  63. \class MemDump debug.h <rts/debug.h>
  64. \brief Helper class for performing a raw memory dump.
  65. Can be used directly in the output stream, e.g.
  66. \code
  67. DLOG( "This is 16 bytes of memory:\n" << Debug::MemDump::Raw(&somePointer,16) );
  68. \endcode
  69. */
  70. class MemDump
  71. {
  72. // necessary because Debug needs access to the following private members
  73. friend Debug;
  74. const unsigned char *m_startPtr; ///< start dumping with this address
  75. unsigned m_numItems; ///< dump the given number of items
  76. unsigned m_bytePerItem; ///< determines the number of bytes per item (1. 2 or 4)
  77. bool m_absAddr; ///< show absolute addresses (true) or relative addresses (false)
  78. bool m_withChars; ///< show printable characters on right side of dump (true) or not (false)
  79. // constructor is private on purpose so that nobody can
  80. // create instances of this class except the static functions
  81. // provided herein
  82. MemDump(const void *ptr, unsigned num, unsigned bpi, bool absAddr, bool withChars):
  83. m_startPtr((const unsigned char *)ptr), m_numItems(num),
  84. m_bytePerItem(bpi), m_absAddr(absAddr), m_withChars(withChars) {}
  85. public:
  86. /**
  87. Creates a memory dump descriptor.
  88. \param startPtr address to start dump from
  89. \param numItems number of items (usually bytes) to dump
  90. \param bytePerItem number of bytes per item (usually 1)
  91. */
  92. static MemDump Raw(const void *startPtr, unsigned numItems, unsigned bytePerItem=1)
  93. {
  94. return MemDump(startPtr,numItems,bytePerItem,true,false);
  95. }
  96. /**
  97. Creates a memory dump descriptor with relative addresses.
  98. \param startPtr address to start dump from
  99. \param numItems number of items (usually bytes) to dump
  100. \param bytePerItem number of bytes per item (usually 1)
  101. */
  102. static MemDump RawRel(const void *startPtr, unsigned numItems, unsigned bytePerItem=1)
  103. {
  104. return MemDump(startPtr,numItems,bytePerItem,false,false);
  105. }
  106. /**
  107. Creates a memory dump descriptor that dumps out ASCII chars as well.
  108. \param startPtr address to start dump from
  109. \param numItems number of items (usually bytes) to dump
  110. \param bytePerItem number of bytes per item (usually 1)
  111. */
  112. static MemDump Char(const void *startPtr, unsigned numItems, unsigned bytePerItem=1)
  113. {
  114. return MemDump(startPtr,numItems,bytePerItem,true,true);
  115. }
  116. /**
  117. Creates a memory dump descriptor with relative addresses that dumps out ASCII chars as well.
  118. \param startPtr address to start dump from
  119. \param numItems number of items (usually bytes) to dump
  120. \param bytePerItem number of bytes per item (usually 1)
  121. */
  122. static MemDump CharRel(const void *startPtr, unsigned numItems, unsigned bytePerItem=1)
  123. {
  124. return MemDump(startPtr,numItems,bytePerItem,false,true);
  125. }
  126. };
  127. /**
  128. \class HResult debug.h <rts/debug.h>
  129. \brief Helper class for writing HRESULTs to the debug stream.
  130. Can be used directly in the output stream, e.g.
  131. \code
  132. DLOG( "My HResult is: " << Debug::HResult(SomeHRESULTValue) << "\n" );
  133. \endcode
  134. The most interesting thing about HRESULTs is that custom HRESULT translators
  135. can be added or removed during runtime, see \ref Debug::AddHResultTranslator for more
  136. information.
  137. */
  138. class HResult
  139. {
  140. // necessary because Debug needs access to the following private members
  141. friend Debug;
  142. long m_hresult; ///< HRESULT value
  143. public:
  144. /**
  145. Creates a HRESULT descriptor.
  146. \param hresult HRESULT value (checked, Windows declares HRESULT as typedef long)
  147. */
  148. explicit HResult(long hresult): m_hresult(hresult) {}
  149. };
  150. /** \internal
  151. \brief Helper class for adding log group descriptions.
  152. */
  153. class LogDescription
  154. {
  155. // sorry, no copies or assignments
  156. LogDescription(const LogDescription&);
  157. LogDescription& operator=(const LogDescription&);
  158. public:
  159. /** \internal
  160. Adds a description for a logging file/group.
  161. \param fileOrGroup filename or logging group (see \ref Debug::LogBegin)
  162. \param description descriptive text for logging file/group
  163. */
  164. LogDescription(const char *fileOrGroup, const char *description);
  165. };
  166. /**
  167. \brief Switches integer output to hexadecimal format.
  168. */
  169. class Hex {};
  170. /// \internal Performs actual switch to hexadecimal format.
  171. Debug& operator<<(Hex &)
  172. {
  173. SetPrefixAndRadix("0x",16);
  174. return *this;
  175. }
  176. /**
  177. \brief Switches integer output to decimal format.
  178. */
  179. class Dec {};
  180. /// \internal Performs actuals switch to decimal format
  181. Debug& operator<<(Dec &)
  182. {
  183. SetPrefixAndRadix("",10);
  184. return *this;
  185. }
  186. /**
  187. \brief Switches integer output to binary format.
  188. */
  189. class Bin {};
  190. /// \internal Performs actuals switch to binary format
  191. Debug& operator<<(Bin &)
  192. {
  193. SetPrefixAndRadix("%",2);
  194. return *this;
  195. }
  196. /**
  197. \brief Sets output width for the next insertion.
  198. */
  199. class Width
  200. {
  201. // necessary because Debug needs access to the following private members
  202. friend Debug;
  203. int m_width; ///< output width
  204. public:
  205. /// \brief Sets new output width (next insertion only).
  206. explicit Width(int width): m_width(width) {}
  207. };
  208. /// \internal Performs actuals width switch
  209. Debug& operator<<(Width &w)
  210. {
  211. m_width=w.m_width;
  212. return *this;
  213. }
  214. /**
  215. \brief Sets new fill character.
  216. */
  217. class FillChar
  218. {
  219. // necessary because Debug needs access to the following private members
  220. friend Debug;
  221. char m_fill; ///< fill character
  222. public:
  223. /// \brief Sets new fill character.
  224. explicit FillChar(char ch=' '): m_fill(ch) {}
  225. };
  226. /// \internal Performs actuals setting of fill char
  227. Debug& operator<<(FillChar &c)
  228. {
  229. m_fillChar=c.m_fill;
  230. return *this;
  231. }
  232. /**
  233. \brief Repeats a given character N times.
  234. */
  235. class RepeatChar
  236. {
  237. // necessary because Debug needs access to the following private members
  238. friend Debug;
  239. char m_char; ///< character
  240. int m_count; ///< repeat count
  241. public:
  242. /// \brief Repeats a given character N times
  243. explicit RepeatChar(char ch, int count): m_char(ch), m_count(count) {}
  244. };
  245. /// \internal Performs actuals repeating of char
  246. Debug& operator<<(RepeatChar &c);
  247. /**
  248. \brief Old printf style formatting.
  249. \note Do not use this helper class for new code. It is mainly here
  250. to get the old code base adapted to the new debug module more quickly.
  251. */
  252. class Format
  253. {
  254. // necessary because Debug needs access to the following private members
  255. friend Debug;
  256. // no CC, AOp
  257. Format(const Format &);
  258. Format& operator=(const Format&);
  259. char m_buffer[512]; ///< this contains the string to write \note Fixed size buffer!
  260. public:
  261. /// \brief Old printf style formatting.
  262. explicit Format(const char *format, ...);
  263. };
  264. /// \internal Writes printf style formatted string to debug log.
  265. Debug& operator<<(const Format &f)
  266. {
  267. operator<<(f.m_buffer);
  268. return *this;
  269. }
  270. // this is necessary because LogDescription needs to call AddLogGroup
  271. friend class LogDescription;
  272. /** \internal
  273. \brief Performs logical cleanup.
  274. */
  275. ~Debug();
  276. /**
  277. \brief Installs exception handler for current thread.
  278. For the main thread this is already done, but for any additional
  279. threads being created this function must be called.
  280. */
  281. static void InstallExceptionHandler(void);
  282. /** \internal
  283. \brief Helper function for skipping over disabled asserts and logs.
  284. This function simply records the address it has been called from. If
  285. an assert or other function is disabled this function returns true,
  286. false otherwise.
  287. @todo_opt Change so that instead of returning true the call to this
  288. function is directly removed from the calling code
  289. \return true if next assert/log should be skipped, false otherwise
  290. */
  291. static bool SkipNext(void);
  292. /** \internal
  293. \brief Helper function which gets called if an assertion fails.
  294. Starts building the assert string which will then be send to the active
  295. output destinations. SkipNext must be called before calling this function
  296. since this function also associates the most recent SkipNext call with
  297. the current assertion.
  298. \param file file that contains DASSERT or DASSERT_MSG macro
  299. \param line line where assert macro can be found
  300. \param expr expression that triggered the assertion, NULL for 'general failure' (\ref DFAIL)
  301. \return reference to Debug instance
  302. */
  303. static Debug &AssertBegin(const char *file, int line, const char *expr);
  304. /** \internal
  305. \brief Displays assertion window.
  306. Depending on the user feedback (abort, retry, ignore) the program then
  307. either aborts or continues. This function is to be used as the final
  308. call in a debug message stream.
  309. \return false (always)
  310. */
  311. bool AssertDone(void);
  312. /** \internal
  313. \brief Helper function which gets called if a check fails.
  314. Starts building the assert string which will then be send to the active
  315. output destinations. SkipNext must be called before calling this function
  316. since this function also associates the most recent SkipNext call with
  317. the current check.
  318. \param file file that contains DCHECK or DCHECK_MSG macro
  319. \param line line where check macro can be found
  320. \param expr expression that triggered the assertion
  321. \return reference to Debug instance
  322. */
  323. static Debug &CheckBegin(const char *file, int line, const char *expr);
  324. /** \internal
  325. \brief Flushes current 'check' message.
  326. This function is to be used as the final call in a debug message stream.
  327. \return false (always)
  328. */
  329. bool CheckDone(void);
  330. /** \internal
  331. \brief Helper function which gets when writing data to the output log.
  332. Starts building the log string which will then be send to the active
  333. output destinations. SkipNext must be called before calling this function
  334. since this function also associates the most recent SkipNext call with
  335. the current log group.
  336. \param fileOrGroup current file or group the following log data is for
  337. \return reference to Debug instance
  338. */
  339. static Debug &LogBegin(const char *fileOrGroup);
  340. /** \internal
  341. \brief Flushes current 'log' message.
  342. This function is to be used as the final call in a debug message stream.
  343. \return false (always)
  344. */
  345. bool LogDone(void);
  346. /** \internal
  347. \brief Helper function which gets called on crash.
  348. Starts building the crash string which will then be send to the active
  349. output destinations.
  350. \param file file that contains DCRASH or DCRASH_RELEASE macro, if NULL
  351. then no file info is given (used by DCRASH_RELEASE in release
  352. builds)
  353. \param line line where crash macro can be found, 0 if no line info should
  354. be given
  355. \return reference to Debug instance
  356. */
  357. static Debug &CrashBegin(const char *file, int line);
  358. /** \internal
  359. \brief Exits program with a 'crash' message.
  360. This function is to be used as the final call in a debug message stream.
  361. \param die true if module should exit after displaying message, false if
  362. the user should have the choice
  363. \return false (always)
  364. */
  365. bool CrashDone(bool die);
  366. /** \internal
  367. \brief Write string to output log.
  368. \param str string to write
  369. \return *this
  370. */
  371. Debug& operator<<(const char *str);
  372. /** \internal
  373. \brief Define prefix and radix for integer output.
  374. \param prefix prefix to use (typically "" or "0x")
  375. \param radix radix to use (typically 10 or 16)
  376. */
  377. void SetPrefixAndRadix(const char *prefix, int radix);
  378. /** \internal
  379. \brief Write signed integer to output log.
  380. \param val signed integer
  381. \return *this
  382. */
  383. Debug& operator<<(int val);
  384. /** \internal
  385. \brief Write unsigned integer to output log.
  386. \param val unsigned integer
  387. \return *this
  388. */
  389. Debug& operator<<(unsigned val);
  390. /** \internal
  391. \brief Write signed long to output log.
  392. \param val signed long
  393. \return *this
  394. */
  395. Debug& operator<<(long val);
  396. /** \internal
  397. \brief Write unsigned long to output log.
  398. \param val unsigned long
  399. \return *this
  400. */
  401. Debug& operator<<(unsigned long val);
  402. /** \internal
  403. \brief Write boolean value to output log.
  404. \param val bool
  405. \return *this
  406. */
  407. Debug& operator<<(bool val);
  408. /** \internal
  409. \brief Write float value to output log.
  410. \param val float
  411. \return *this
  412. */
  413. Debug& operator<<(float val);
  414. /** \internal
  415. \brief Write double precision float to output log.
  416. \param val double
  417. \return *this
  418. */
  419. Debug& operator<<(double val);
  420. /** \internal
  421. \brief Write signed short integer to output log.
  422. \param val signed short integer
  423. \return *this
  424. */
  425. Debug& operator<<(short val);
  426. /** \internal
  427. \brief Write unsigned short integer to output log.
  428. \param val unsigned short integer
  429. \return *this
  430. */
  431. Debug& operator<<(unsigned short val);
  432. /** \internal
  433. \brief Write signed 64 bit integer to output log.
  434. \param val signed 64 bit integer
  435. \return *this
  436. */
  437. Debug& operator<<(__int64 val);
  438. /** \internal
  439. \brief Write unsigned 64 bit integer to output log.
  440. \param val unsigned 64 bit integer
  441. \return *this
  442. */
  443. Debug& operator<<(unsigned __int64 val);
  444. /** \internal
  445. \brief Write pointer address to output log.
  446. \param ptr pointer address
  447. \return *this
  448. */
  449. Debug& operator<<(const void *ptr);
  450. /** \internal
  451. \brief Write memory dump to output log.
  452. \param dump MemDump descriptor, defines what range of memory to dump
  453. \return *this
  454. */
  455. Debug& operator<<(const MemDump &dump);
  456. /** \internal
  457. \brief Write HRESULT value to output log.
  458. \param hres HResult descriptor
  459. \return *this
  460. */
  461. Debug& operator<<(HResult hres);
  462. /** \internal
  463. \brief Determines if a log file/group is active or not.
  464. \param fileOrGroup Name of source file or group to check for. If the
  465. string contains any forward or backslashes then anything
  466. before them is ignored. If the then remaining string
  467. contains any dots anything beyond the first dot is ignored
  468. as well.
  469. \return true if logging is enabled, false if not
  470. */
  471. static bool IsLogEnabled(const char *fileOrGroup);
  472. /**
  473. \brief Adds a HRESULT translator.
  474. A HRESULT translator is called whenever a HResult descriptor is passed into
  475. the Debug log stream. Such a translator can translate the numeric value
  476. into something more meaningful.
  477. Translators are differentiated by both function address and user pointer. There
  478. is however no harm in adding the same translator/user pointer pair twice.
  479. \param prio priority, translators with a higher priority get called first
  480. \param func translator address
  481. \param user optional user pointer which will be passed to the given translator
  482. \see RemoveHResultTranslator
  483. */
  484. static void AddHResultTranslator(unsigned prio, HResultTranslator func, void *user=0);
  485. /**
  486. \brief Removes a HRESULT translator.
  487. If the translator/user pointer pair does not exist nothing is done.
  488. \param func translator address
  489. \param user optional user pointer
  490. \see AddHResultTranslator
  491. */
  492. static void RemoveHResultTranslator(HResultTranslator func, void *user=0);
  493. /**
  494. \brief Registers a new I/O class factory function.
  495. This is typically used internally by the DEBUG_IMPLEMENT_IO_INTERFACE
  496. macro. If there is already an I/O class with the same name registered
  497. the new one overwrites the old.
  498. \param io_id name of I/O class as it should be registered with Debug module
  499. \param descr short class description
  500. \param func factory function
  501. \return true (so function can be used in static initializers)
  502. */
  503. static bool AddIOFactory(const char *io_id, const char *descr,
  504. DebugIOInterface* (*func)(void));
  505. /**
  506. \brief Adds a new command group.
  507. If the command group already exists the new command interface is added at
  508. the end of the list. A command issued for that group is first passed
  509. to the 'old' command interface. If that DebugCmdInterface::Execute call
  510. fails the command is passed on to the next interface within the same
  511. command group.
  512. The only exception is the 'help' command. Here all Execute functions are
  513. always called.
  514. Ownership of the interface pointer is passed to the Debug module i.e. the
  515. interface is destroyed when the Debug module shuts down (unless the
  516. interface is removed using RemoveCommands).
  517. \param cmdgroup command group this interface implements
  518. \param cmdif command group interface instance
  519. \return true (so function can be used in static initializers)
  520. */
  521. static bool AddCommands(const char *cmdgroup, DebugCmdInterface *cmdif);
  522. /**
  523. \brief Removes a command group.
  524. \param cmdif command group interface that will be removed
  525. */
  526. static void RemoveCommands(DebugCmdInterface *cmdif);
  527. /**
  528. \brief Issues a debug command.
  529. \param cmd command to execute
  530. */
  531. static void Command(const char *cmd);
  532. /**
  533. \brief Update method, must be called on a regular basis.
  534. Scans I/O classes for new command input and processes it.
  535. */
  536. static void Update(void);
  537. /** \internal
  538. \brief Simple recursive pattern matcher.
  539. \param str string to match
  540. \param pattern pattern, only wildcard valid is '*'
  541. \return true if string matches pattern, false if not
  542. */
  543. static bool SimpleMatch(const char *str, const char *pattern);
  544. /**
  545. \brief Tell debug module about build info.
  546. All these strings are free form and can be up to 63 chars long.
  547. \param version official version
  548. \param internalVersion internal version
  549. \param buildDate build date & time
  550. */
  551. static void SetBuildInfo(const char *version,
  552. const char *internalVersion,
  553. const char *buildDate);
  554. /**
  555. \brief Write build information into log.
  556. */
  557. void WriteBuildInfo(void);
  558. private:
  559. // no assignment, no copy constructor
  560. Debug(const Debug&);
  561. Debug& operator=(const Debug&);
  562. /** \internal
  563. Undocumented default constructor. Initializes debugging library.
  564. We can make this private as well so nobody accidently tries to create
  565. a Debug instance. Actually this function does not do anything -
  566. initialization is rather performed by PreStaticInit() and
  567. PostStaticInit().
  568. */
  569. Debug(void);
  570. /** \internal
  571. This function gets called before any static C++ symbols are
  572. initialized. Code herein must be extremely careful because all
  573. global C++ instances are not initialized yet.
  574. */
  575. static void PreStaticInit(void);
  576. /** \internal
  577. This function gets called after all static C++ symbols have
  578. been initialized.
  579. */
  580. static void PostStaticInit(void);
  581. /** \internal
  582. This function gets called if the program exists. Use this
  583. function for any cleanup purposes (not the destructor, it
  584. might get called too early).
  585. */
  586. static void StaticExit(void);
  587. /** \internal
  588. The only debug instance. Actually not used for anything
  589. except as magic first parameter for overloaded stream operators.
  590. */
  591. static Debug Instance;
  592. /** \internal
  593. Helper variable for putting PreStaticInit() into the MSVC
  594. startup list.
  595. */
  596. static void *PreStatic;
  597. /** \internal
  598. Helper variable for putting PostStaticInit() into the MSVC
  599. startup list.
  600. */
  601. static void *PostStatic;
  602. /// \internal HResult translator vector entry
  603. struct HResultTranslatorEntry
  604. {
  605. /// priority
  606. unsigned prio;
  607. /// translator function
  608. HResultTranslator func;
  609. /// user pointer
  610. void *user;
  611. };
  612. /// \internal HResult translator vector
  613. HResultTranslatorEntry *hrTranslators;
  614. /// \internal number of HResult translators
  615. unsigned numHrTranslators;
  616. /// \internal I/O class/factory list entry
  617. struct IOFactoryListEntry
  618. {
  619. /// pointer to next entry in list
  620. IOFactoryListEntry *next;
  621. /// I/O ID
  622. const char *ioID;
  623. /// I/O description
  624. const char *descr;
  625. /// factory function
  626. DebugIOInterface* (*factory)(void);
  627. /// I/O interface (may be NULL)
  628. DebugIOInterface *io;
  629. /// input buffer
  630. char *input;
  631. /// used size of input buffer
  632. unsigned inputUsed;
  633. /// allocated size of input buffer
  634. unsigned inputAlloc;
  635. };
  636. /** \internal
  637. First I/O factory list entry. A singly linked list is
  638. okay for this because looking up I/O IDs is not
  639. time critical.
  640. */
  641. IOFactoryListEntry *firstIOFactory;
  642. /// \internal command interface list entry
  643. struct CmdInterfaceListEntry
  644. {
  645. /// pointer to next entry in list
  646. CmdInterfaceListEntry *next;
  647. /// command group
  648. const char *group;
  649. /// interface pointer
  650. DebugCmdInterface *cmdif;
  651. };
  652. /** \internal
  653. First command interface list entry. A singly linked list is
  654. okay for this because looking up command groups is not
  655. time critical.
  656. */
  657. CmdInterfaceListEntry *firstCmdGroup;
  658. /// \internal current stack frame (used by SkipNext)
  659. static unsigned curStackFrame;
  660. /** \internal
  661. Bit mask for frame entry types. Implemented as a bit
  662. mask since it is also used for the inclusion/exclusion
  663. list where a single pattern can apply to more than
  664. one type.
  665. */
  666. enum
  667. {
  668. /// assert
  669. FrameTypeAssert = 0x00000001,
  670. /// check
  671. FrameTypeCheck = 0x00000002,
  672. /// log
  673. FrameTypeLog = 0x00000004
  674. };
  675. /** \internal
  676. List of possible statuses for a frame hash entry.
  677. */
  678. enum FrameStatus
  679. {
  680. /// unknown, must check
  681. Unknown = 0,
  682. /// skip this frame
  683. Skip,
  684. /// do not skip this frame
  685. NoSkip
  686. };
  687. /** \internal
  688. \brief Hash table entry for mapping stack frame addresses to
  689. asserts/checks/logs.
  690. */
  691. struct FrameHashEntry
  692. {
  693. /// pointer to next entry with same hash
  694. FrameHashEntry *next;
  695. /// frame address
  696. unsigned frameAddr;
  697. /// frame type (FrameTypeAssert, FrameTypeCheck, or FrameTypeLog)
  698. unsigned frameType;
  699. /// file (or group if log)
  700. const char *fileOrGroup;
  701. /// line number (undefined for logs)
  702. int line;
  703. /// number of times this frame has been hit
  704. int hits;
  705. /// frame status
  706. FrameStatus status;
  707. };
  708. /// \internal initial frame hash size (prime number)
  709. enum { FRAME_HASH_SIZE = 10007 };
  710. /// \internal frame hash pointers
  711. FrameHashEntry *frameHash[FRAME_HASH_SIZE];
  712. /// \internal number of FrameHashEntry structures to allocate at one time
  713. enum { FRAME_HASH_ALLOC_COUNT = 100 };
  714. /// \internal next unused FrameHashEntry structure
  715. FrameHashEntry *nextUnusedFrameHash;
  716. /// \internal number of available FrameHashEntry structures
  717. unsigned numAvailableFrameHash;
  718. /** \internal
  719. Look up given frame address.
  720. \param addr frame address
  721. \return FrameHashEntry found or 0 if nothing found
  722. */
  723. __forceinline FrameHashEntry *LookupFrame(unsigned addr)
  724. {
  725. for (FrameHashEntry *e=frameHash[addr%FRAME_HASH_SIZE];e;e=e->next)
  726. if (e->frameAddr==addr)
  727. return e;
  728. return 0;
  729. }
  730. /** \internal
  731. Add frame address entry (entry must not exist yet). If
  732. a log frame is added then a corresponding entry is added
  733. to the list of known log groups as well.
  734. \param addr frame address
  735. \param type frame type
  736. \param fileOrGroup file (or group name)
  737. \param line line number
  738. \return the entry just added
  739. */
  740. FrameHashEntry *AddFrameEntry(unsigned addr, unsigned type,
  741. const char *fileOrGroup, int line);
  742. /** \internal
  743. Updates the frames status variable depending on the current
  744. pattern list.
  745. \param entry entry that needs to be updated
  746. */
  747. void UpdateFrameStatus(FrameHashEntry &entry);
  748. /** \internal
  749. Combines LookupFrame, AddFrameEntry and UpdateFrameStatus.
  750. \param addr frame address
  751. \param type frame type
  752. \param fileOrGroup file (or group name)
  753. \param line line number
  754. \return the entry just added (or the already existing entry)
  755. */
  756. FrameHashEntry *GetFrameEntry(unsigned addr, unsigned type,
  757. const char *fileOrGroup, int line)
  758. {
  759. FrameHashEntry *e=LookupFrame(addr);
  760. if (!e)
  761. e=AddFrameEntry(addr,type,fileOrGroup,line);
  762. if (e->status==Unknown)
  763. UpdateFrameStatus(*e);
  764. return e;
  765. }
  766. /** \internal
  767. \brief List of known logs.
  768. A singly linked list is
  769. okay for this because looking up log groups happens only
  770. if a new stack frame entry is added (which happens only
  771. once for each log command).
  772. */
  773. struct KnownLogGroupList
  774. {
  775. /// next entry
  776. KnownLogGroupList *next;
  777. /// name of log group (dynamically allocated memory)
  778. char *nameGroup;
  779. /// log description (if any)
  780. const char *descr;
  781. };
  782. /// \internal first log group list entry
  783. KnownLogGroupList *firstLogGroup;
  784. /** \internal
  785. Adds a log group (and optionally description) to the list
  786. of known groups. If a group with that name already exists
  787. nothing is done. Takes care of stripping path and extension
  788. of the passed in group name (if it's a file name).
  789. Returns translated group name.
  790. \param fileOrGroup file or log group
  791. \param descr description, may be NULL
  792. \return translated log group name
  793. */
  794. const char *AddLogGroup(const char *fileOrGroup, const char *descr);
  795. /// \internal I/O buffers for all I/O string types
  796. struct
  797. {
  798. /// buffer
  799. char *buffer;
  800. /// used buffer size
  801. unsigned used;
  802. /// allocated buffer size
  803. unsigned alloc;
  804. /// has last character been CR?
  805. bool lastWasCR;
  806. } ioBuffer[DebugIOInterface::StringType::MAX];
  807. /// \internal current I/O string type we're writing
  808. DebugIOInterface::StringType curType;
  809. /// \internal current I/O string source (fixed size, careful!)
  810. char curSource[256];
  811. /// \internal used to enable/disable all asserts/checks/logs
  812. int disableAssertsEtc;
  813. /** \internal
  814. Starts new output stream with the given type and source.
  815. \param type string type
  816. \param fmt wsprintf format string
  817. */
  818. void StartOutput(DebugIOInterface::StringType type, const char *fmt, ...);
  819. /** \internal
  820. Adds the given string to the currently active output buffer.
  821. \param str string
  822. \param len string length
  823. */
  824. void AddOutput(const char *str, unsigned len);
  825. /** \internal
  826. Flushes current I/O buffer to all output handlers.
  827. \param defaultLog if true and no I/O class is active then data
  828. is written to default.log
  829. */
  830. void FlushOutput(bool defaultLog=true);
  831. /// \internal pointer to currently active frame
  832. FrameHashEntry *curFrameEntry;
  833. /// \internal pattern list entry
  834. struct PatternListEntry
  835. {
  836. /// next entry
  837. PatternListEntry *next;
  838. /// frame type(s)
  839. unsigned frameTypes;
  840. /// active (true) or inactive (false)?
  841. bool isActive;
  842. /// pattern itself (dynamic allocated memory)
  843. char *pattern;
  844. };
  845. /** \internal
  846. First pattern list list entry. A singly linked list is
  847. okay for this because checking patterns is a costly
  848. operation anyway and is therefore cached.
  849. */
  850. PatternListEntry *firstPatternEntry;
  851. /// \internal last pattern list entry for fast additions to list at end
  852. PatternListEntry *lastPatternEntry;
  853. /** \internal
  854. Adds a new pattern list entry. This function does not check if
  855. a matching pattern entry exists already.
  856. \param types frame type(s)
  857. \param isActive active (true) or inactive (false)?
  858. \param pattern pattern itself
  859. */
  860. void AddPatternEntry(unsigned types, bool isActive, const char *pattern);
  861. /** \internal
  862. Executes the given command.
  863. \param cmdstart start of command
  864. \param cmdend end of command (not including this character)
  865. */
  866. void ExecCommand(const char *cmdstart, const char *cmdend);
  867. /** \internal
  868. \brief Checks if main program is running windowed or not.
  869. If the decisison can not be made an windowed program is assumed.
  870. \return true if windowed, false if full screen
  871. */
  872. bool IsWindowed(void);
  873. /// \internal name of current command group
  874. char curCommandGroup[100];
  875. /// \internal if true then always flush after each line written
  876. bool alwaysFlush;
  877. /// \internal if true then put timestamps before each new line
  878. bool timeStamp;
  879. /// \internal the one and only stack walker
  880. DebugStackwalk m_stackWalk;
  881. /// \internal current integer prefix to use
  882. char m_prefix[16];
  883. /// \internal current integer radix to use
  884. int m_radix;
  885. /// \internal official version
  886. char m_version[64];
  887. /// \internal internal version
  888. char m_intVersion[64];
  889. /// \internal build date/time
  890. char m_buildDate[64];
  891. /// \internal output width
  892. int m_width;
  893. /// \internal fill char
  894. char m_fillChar;
  895. /// \internal <0 if fullscreen, >0 if windowed, ==0 if not checked yet
  896. char m_isWindowed;
  897. };
  898. /// \addtogroup debug_fn Debugging functions
  899. ///@{
  900. /**
  901. \brief Determines default commands to be executed at startup.
  902. This function returns a list of default commands which are executed on
  903. startup if no .dbgcmd file is read.
  904. Currently this function returns:
  905. \code
  906. "debug.io flat add"
  907. \endcode
  908. In order to provide a different set of commands simply put another
  909. version of DebugGetDefaultCommands in a CPP file. This is basically
  910. identical to having a .dbgcmd file in the current directory. For some
  911. situations (e.g. passing EXEs off to QA) it is however safer to have
  912. these startup commands build into the EXE itself rather than relying
  913. on QA having the right .dbgcmd file in place.
  914. As an example a new version of this function might return:
  915. \code
  916. "debug.io flat add\nio flat copy q:\logfiles\n"
  917. \endcode
  918. \return list of commands, separated by \\n
  919. \note This function is executed after all static variables have been initialized.
  920. */
  921. const char *DebugGetDefaultCommands(void);
  922. ///@} end of debug_fn group
  923. #endif // DEBUG_DEBUG_H