mydebug.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. /*****************************************************************************\
  19. wdebug Neal Kettler
  20. MT-LEVEL
  21. MT-Safe
  22. The debugging module is pretty good for debugging and it has some message
  23. printing stuff as well. The basic idea is that you write a class that
  24. inherits from OutputDevice (several are provided) and assign that output
  25. device to a stream. There are seperate streams for debugging, information,
  26. warning, and error messages. Each one can have a seperate output device,
  27. or they can all have the same one. Debugging messages only get compiled
  28. in if your module defines 'DEBUG'. If you don't define debug, then not even
  29. the text of the debugging message gets into the binary. All the other
  30. output streams get printed regardless of whether DEBUG is defined.
  31. Sample usage:
  32. FileD debug_device("gameres.debug"); // create a file device
  33. MsgManager::setDebugStream(&debug_device);
  34. DBGMSG("This debug message #" << 1 << " you use C++ streams");
  35. Note that since these are defines you really don't need to put a semicolon
  36. at the end, and it can be bad in situations like this:
  37. if (x)
  38. DBGMSG("Stuff is broken");
  39. else
  40. DBGMSG("Stuff is NOT broken");
  41. This won't compile, read the code until you figure it out. Only then
  42. will you be ready to leave grasshopper.
  43. \*****************************************************************************/
  44. #ifndef MYDEBUG_HEADER
  45. #define MYDEBUG_HEADER
  46. #define USE_SEM
  47. #include "wstypes.h"
  48. #ifdef _WINDOWS
  49. #include <iostream.h>
  50. #include <strstrea.h>
  51. #else
  52. #include <iostream>
  53. #endif
  54. #ifdef USE_SEM
  55. #include "sem4.h"
  56. #else
  57. #include "critsec.h"
  58. #endif
  59. #include "odevice.h"
  60. #include "streamer.h"
  61. #include "xtime.h"
  62. #include "timezone.h" // MDC
  63. #include "filed.h"
  64. // This is needed because the streams return a pointer. Every time you
  65. // change the output device the old stream is deleted, and a new one
  66. // is created.
  67. // MDC: Changed from semaphores to critical sections because Windows doesn't provide
  68. // a good way of doing semaphores (I think)
  69. // MDC: Never mind, they seem to be working now! I'm leaving it in, though, so anyone can
  70. // flip a switch between the two.
  71. #ifdef USE_SEM
  72. extern Sem4 MyDebugLibSemaphore;
  73. #define MYDEBUGLOCK MyDebugLibSemaphore.Wait()
  74. #define MYDEBUGUNLOCK MyDebugLibSemaphore.Post()
  75. #else
  76. extern CritSec MyDebugLibSemaphore;
  77. #define MYDEBUGLOCK MyDebugLibSemaphore.lock()
  78. #define MYDEBUGUNLOCK MyDebugLibSemaphore.unlock()
  79. #endif
  80. // Print an information message
  81. #define PARANOIDMSG(X)\
  82. {\
  83. char timebuf[40]; \
  84. Xtime now; \
  85. now -= TimezoneOffset(); \
  86. now.FormatTime(timebuf, "mm/dd/yy hh:mm:ss"); \
  87. MYDEBUGLOCK; \
  88. if (MyMsgManager::paranoidStream()) \
  89. (*(MyMsgManager::paranoidStream())) << "HACK " << timebuf << " [" << \
  90. __FILE__ << " " << __LINE__ << "] " << X << endl; \
  91. MYDEBUGUNLOCK; \
  92. }
  93. // Just get a stream to the information device, no extra junk
  94. #define PARANOIDSTREAM(X)\
  95. {\
  96. MYDEBUGLOCK; \
  97. if (MyMsgManager::paranoidStream()) \
  98. (*(MyMsgManager::paranoidStream())) << X;\
  99. MYDEBUGUNLOCK; \
  100. }
  101. //#undef MYDEBUGLOCK
  102. //#undef MYDEBUGUNLOCK
  103. class MyMsgManager
  104. {
  105. protected:
  106. MyMsgManager();
  107. public:
  108. static int setAllStreams(OutputDevice *device);
  109. static int setParanoidStream(OutputDevice *device);
  110. static int ReplaceAllStreams(FileD *output_device, char *device_filename, char *copy_filename);
  111. static void enableParanoid(int flag);
  112. static ostream *paranoidStream(void);
  113. };
  114. #endif