Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

260 lines
7.1 KiB

  1. //---------------------------------------------------------------------------
  2. // MCSDebug.cpp
  3. //
  4. // The classes declared in MCSDebug.h are defined in
  5. // this file.
  6. //
  7. // (c) Copyright 1995-1998, Mission Critical Software, Inc., All Rights Reserved
  8. //
  9. // Proprietary and confidential to Mission Critical Software, Inc.
  10. //---------------------------------------------------------------------------
  11. #ifdef __cplusplus /* C++ */
  12. #ifndef WIN16_VERSION /* Not WIN16_VERSION */
  13. #ifdef USE_STDAFX
  14. # include "stdafx.h"
  15. # include "rpc.h"
  16. #else
  17. # include <windows.h>
  18. #endif
  19. #include <time.h>
  20. #include <strstrea.h>
  21. #include "UString.hpp"
  22. #include "McsDebug.h"
  23. // -----------------
  24. // McsDebugException
  25. // -----------------
  26. McsDebugException::McsDebugException
  27. (const McsDebugException &t)
  28. : m_message (0), m_fileName (0), m_lineNum (t.m_lineNum) {
  29. if (t.m_message) {
  30. m_message = new char [UStrLen(t.m_message)+1];
  31. if (m_message) { UStrCpy (m_message, t.m_message); }
  32. }
  33. if (t.m_fileName) {
  34. m_fileName = new char [UStrLen(t.m_fileName)+1];
  35. if (m_fileName) { UStrCpy (m_fileName, t.m_fileName); }
  36. }
  37. }
  38. McsDebugException::McsDebugException
  39. (const char *messageIn,
  40. const char *fileNameIn,
  41. int lineNumIn)
  42. : m_lineNum (lineNumIn) {
  43. if (messageIn) {
  44. m_message = new char [UStrLen (messageIn)+1];
  45. if (m_message) { UStrCpy (m_message, messageIn); }
  46. }
  47. if (fileNameIn) {
  48. m_fileName = new char [UStrLen(fileNameIn)+1];
  49. UStrCpy (m_fileName, fileNameIn);
  50. }
  51. }
  52. McsDebugException& McsDebugException::operator=
  53. (const McsDebugException &t) {
  54. if (this != &t) {
  55. if (t.m_message) {
  56. m_message = new char [UStrLen(t.m_message)+1];
  57. if (m_message) { UStrCpy (m_message, t.m_message); }
  58. }
  59. if (t.m_fileName) {
  60. m_fileName = new char [UStrLen(t.m_fileName)+1];
  61. if (m_fileName) { UStrCpy (m_fileName, t.m_fileName); }
  62. }
  63. m_lineNum = t.m_lineNum;
  64. }
  65. return *this;
  66. }
  67. // ------------
  68. // McsVerifyLog
  69. // ------------
  70. static McsVerifyLog *pVerifyLog;
  71. static LONG verifyInitFlag;
  72. McsVerifyLog* McsVerifyLog::getLog (void) {
  73. // If pointer not initialized use the cheap
  74. // locking mechanism and set pointer to the
  75. // the static verifyLog object. This required
  76. // to gurantee the correct initialization of
  77. // the verify log class independent of any
  78. // static initialization order dependency.
  79. if (!pVerifyLog) {
  80. while (::InterlockedExchange
  81. (&verifyInitFlag, 1)) {
  82. ::Sleep (10);
  83. }
  84. if (!pVerifyLog) {
  85. static McsVerifyLog verifyLog;
  86. pVerifyLog = &verifyLog;
  87. }
  88. ::InterlockedExchange (&verifyInitFlag, 0);
  89. }
  90. return pVerifyLog;
  91. }
  92. void McsVerifyLog::changeLog (ostream *outStreamIn) {
  93. m_logSec.enter();
  94. m_log.changeLog (outStreamIn);
  95. delete m_outLog;
  96. m_outLog = 0;
  97. m_logSec.leave();
  98. }
  99. void McsVerifyLog::log (const char *messageIn,
  100. const char *fileNameIn,
  101. int lineNumIn) {
  102. m_logSec.enter();
  103. // If the log file has not been set, set it
  104. // to the module name log file.
  105. if (!m_log.isLogSet()) {
  106. m_outLog = new fstream (getLogFileName(),
  107. ios::app);
  108. m_log.changeLog (m_outLog);
  109. }
  110. // Format and write the message.
  111. formatMsg (messageIn, fileNameIn, lineNumIn);
  112. m_log.write (m_msgBuf);
  113. m_logSec.leave();
  114. }
  115. const char* McsVerifyLog::getLogFileName (void) {
  116. const char *MCS_LOG_ENV = "MCS_LOG";
  117. const char *DIR_SEP = "\\";
  118. const char *EXT = ".err";
  119. const char *DEFAULT_NAME = "MCSDEBUG";
  120. static char logFileName[MAX_PATH];
  121. // Get MCS_LOG_ENV, or temp directory path,
  122. // NULL means current directory.
  123. logFileName[0] = 0;
  124. char *mcs_log_path = getenv (MCS_LOG_ENV);
  125. bool isLogPath = false;
  126. if (mcs_log_path) {
  127. DWORD attrib = ::GetFileAttributesA (mcs_log_path);
  128. if ((attrib != 0xFFFFFFFF)
  129. && (attrib & FILE_ATTRIBUTE_DIRECTORY)) {
  130. UStrCpy (logFileName, mcs_log_path);
  131. isLogPath = true;
  132. }
  133. }
  134. if (!isLogPath) {
  135. ::GetTempPathA (MAX_PATH, logFileName);
  136. }
  137. // Get file name from the module name. If error
  138. // generate fixed filename.
  139. char fullFilePath [MAX_PATH];
  140. char fileName[MAX_PATH];
  141. if (::GetModuleFileNameA (NULL, fullFilePath,
  142. MAX_PATH)) {
  143. // Get file name out of the path
  144. _splitpath (fullFilePath, NULL, NULL, fileName,
  145. NULL);
  146. // Generate full path name with extension.
  147. int len = UStrLen (logFileName);
  148. if (len) {
  149. UStrCpy (logFileName + len, DIR_SEP);
  150. UStrCpy (logFileName + UStrLen (logFileName),
  151. fileName);
  152. } else {
  153. UStrCpy (logFileName, fileName);
  154. }
  155. } else {
  156. UStrCpy (logFileName, DEFAULT_NAME);
  157. }
  158. strcat (logFileName + UStrLen (logFileName), EXT);
  159. return logFileName;
  160. }
  161. void McsVerifyLog::formatMsg (const char *messageIn,
  162. const char *fileNameIn,
  163. int lineNumIn) {
  164. const char *TIME = "TIME : ";
  165. const char *MSG = "MSG : ";
  166. const char *FILE = "FILE : ";
  167. const char *LINE = "LINE : ";
  168. const char *SPACER = ", ";
  169. // Create stream buf object.
  170. strstream msgBufStream (m_msgBuf, MSG_BUF_LEN, ios::out);
  171. // Write time stamp.
  172. time_t cur;
  173. time (&cur);
  174. struct tm *curTm = localtime (&cur);
  175. if (curTm) {
  176. char *tstr = asctime (curTm);
  177. if (tstr) {
  178. msgBufStream << TIME << tstr << SPACER;
  179. }
  180. }
  181. // Write message.
  182. if (messageIn) {
  183. msgBufStream << MSG << messageIn << SPACER;
  184. }
  185. // Write file name.
  186. if (fileNameIn) {
  187. msgBufStream << FILE << fileNameIn << SPACER;
  188. }
  189. // Write line number.
  190. msgBufStream << LINE << lineNumIn << endl;
  191. }
  192. // ----------
  193. // McsTestLog
  194. // ----------
  195. static McsTestLog *pTestLog;
  196. static LONG testInitFlag;
  197. McsTestLog* McsTestLog::getLog (void) {
  198. // If pointer not initialized use the cheap
  199. // locking mechanism and set pointer to the
  200. // the static verifyLog object. This required
  201. // to gurantee the correct initialization of
  202. // the verify log class independent of any
  203. // static initialization order dependency.
  204. if (!pTestLog) {
  205. while (::InterlockedExchange
  206. (&testInitFlag, 1)) {
  207. ::Sleep (10);
  208. }
  209. if (!pTestLog) {
  210. static McsTestLog testLog;
  211. pTestLog = &testLog;
  212. }
  213. ::InterlockedExchange (&testInitFlag, 0);
  214. }
  215. return pTestLog;
  216. }
  217. bool McsTestLog::isTestMode (void) {
  218. const char *TEST_ENV = "MCS_TEST";
  219. const char *PRE_FIX = "MCS";
  220. // Check if tested.
  221. if (!m_isTested) {
  222. // If not tested lock, test again, and
  223. // initialize test mode flag.
  224. m_testSec.enter();
  225. if (!m_isTested) {
  226. m_isTested = true;
  227. m_isTestMode_ = getenv (TEST_ENV) != NULL;
  228. }
  229. m_testSec.leave();
  230. }
  231. return m_isTestMode_;
  232. }
  233. #endif /* Not WIN16_VERSION */
  234. #endif /* C++ */