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.

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