/* =========================================================================== ARX FATALIS GPL Source Code Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company. This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code'). Arx Fatalis Source Code is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Arx Fatalis Source Code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Arx Fatalis Source Code. If not, see . In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below. If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. =========================================================================== */ ////////////////////////////////////////////////////////////////////////////////////// // @@ @@@ @@@ @@ @@@@@ // // @@@ @@@@@@ @@@ @@ @@@@ @@@ @@@ // // @@@ @@@@@@@ @@@ @@@@ @@@@ @@ @@@@ // // @@@ @@ @@@@ @@@ @@@@@ @@@@@@ @@@ @@@ // // @@@@@ @@ @@@@ @@@ @@@@@ @@@@@@@ @@@ @ @@@ // // @@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@ @@@@@ @@ @@@@@@@ // // @@ @@@ @@ @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@ @@@@ // // @@@ @@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@@@@@@ @@@ @@@@ // // @@@ @@@@ @@@@@@@ @@@@@@ @@@ @@@@ @@@ @@@ @@@ @@@@ // // @@@@@@@@ @@@@@ @@@@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@@@ // // @@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@ @@@@ @@@ @@@@ @@@@@ // //@@@ @@@@ @@@@@ @@@ @@@@@@ @@ @@@ @@@@ @@@@@@@ @@@@@ @@@@@ // //@@@ @@@@@ @@@@@ @@@@ @@@ @@ @@ @@@@ @@@@@@@ @@@@@@@@@ // //@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ // //@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@ // //@@@ @@@ @@@ @@@@@ @@ @@@ // // @@@ @@@ @@ @@ STUDIOS // ////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// // ARX_Common ////////////////////////////////////////////////////////////////////////////////////// // // Description: // All preprocessor directives set for all the solution. // // Updates: (date) (person) (update) // // Code: Jean-Yves CORBEL // Xavier RICHTER // // Copyright (c) 1999-2010 ARKANE Studios SA. All rights reserved ///////////////////////////////////////////////////////////////////////////////////// //-----------------------------------------------------------------------------------// #include #include #include #include //#include #include #include #include /* static var initialize */ ArxDebug * ArxDebug::m_pInstance = NULL ; /* Convert wchar to char */ void ArxDebug::cpy_wstr(char * buf, const wchar_t * src, size_t max) { if (src) { while (max > 0 && *src != 0) { *buf++ = (char) src[0]; --max; src++; } } *buf = 0; } /* Get the callstack informations and create the log file with CreateLogFile function */ void ArxDebug::Assert(const wchar_t * _sMessage, const wchar_t * _sFile, unsigned int _iLine) { char msgbuf[8192]; char fn[MAX_PATH + 1], msg[MAX_PATH + 1], iFile[MAX_PATH + 1]; cpy_wstr(msg, _sMessage, MAX_PATH); cpy_wstr(iFile, _sFile, MAX_PATH); if (iFile[0] == 0) { strcpy(iFile, ""); } if (msg[0] == 0) { strcpy(msg, "?"); } fn[MAX_PATH] = 0; if (! GetModuleFileNameA(NULL, fn, MAX_PATH)) { strcpy(fn, ""); } sprintf(msgbuf, "Assertation failed!\n\nProgram: %s\nFile: %s, Line %u\n\nExpression: %s", fn, iFile, _iLine, msg); /*std::string stackTrace ; ArxStackLogger::StackLogger s ; s.GetStackTrace(stackTrace); CreateCrashFile(fn, msg, iFile, _iLine, stackTrace); */ } /* Use to create Log directory */ bool ArxDebug::CreateLogDirectory() { bool bReturn = true ; //Verify if the log folder exist, otherwise create him char * sLogReposiriry = "..\\Log"; if (CreateDirectoryA(sLogReposiriry, NULL) == 0) { DWORD iCodeError = GetLastError(); switch (iCodeError) { case ERROR_ALREADY_EXISTS : break ; case ERROR_PATH_NOT_FOUND : bReturn = false ; MessageBoxA(NULL, "Folder Path not found", "File ", MB_OK | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL); break ; default: bReturn = false ; MessageBoxA(NULL, "Folder Log cannot be create. May be you dont have the permission or enought space disk.", "File ", MB_OK | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL); } } return bReturn ; } /* Use to create the log file into the Log folder. */ /* void ArxDebug::CreateCrashFile(const char * _sFn , const char * _sMsg , const char * _sFile , unsigned int _iLine, const std::string & _sStackTrace) { DWORD nCode; //Create the message bow for ask if we want a report log std::ostringstream oss ; oss << "Executable : " << _sFn << "\nFile : " << _sFile << " Line : " << _iLine << "\nCause : " << _sMsg; std::string _sFileOss = oss.str().c_str(); oss << "\n Do you want to generate a report into your Log folder ? "; nCode = MessageBoxA(NULL, oss.str().c_str(), "Arx Runtime Assertation ", MB_YESNO | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL); if ((nCode == IDYES) && CreateLogDirectory()) { //Open an outpout stream and write inside std::ofstream fsFile ; std::ostringstream ossFileName ; ossFileName << "..\\Log\\CrashReport__" << time(NULL) << ".txt"; fsFile.open(ossFileName.str().c_str(), std::ios::out | std::ios::trunc); if (!fsFile) { MessageBoxA(NULL, "Crash report cannot be create. May be you don't have the permission or enough space disk.", "Crash Report ", MB_OK | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL); return ; } fsFile << __DATE__ << "\n\n" << _sFileOss << "\n\n ------------------------------------------ CallStack Log --------------------------------- \n\n" << _sStackTrace; fsFile.close(); } } */ /* Singleton Getter/Cleaner */ ArxDebug * ArxDebug::GetInstance(bool _bLogIntoFile /*= true*/) { if (!m_pInstance) { m_pInstance = new ArxDebug(_bLogIntoFile); } return m_pInstance; } void ArxDebug::CleanInstance() { if (m_pInstance) { delete m_pInstance ; } } /* Constructor & Destructor */ ArxDebug::ArxDebug(bool _bLogIntoFile /*= true*/) { m_bConsoleInitialize = false ; m_bOpenLogFile = false ; m_uiTabulation = 0 ; RedirectIOToConsole(); if (_bLogIntoFile) { StartLogSession(); } } ArxDebug::~ArxDebug() { CleanConsole(); EndLogSession(); m_pInstance = NULL ; m_uiTabulation = 0 ; } /* Create and Clean Console for log */ void ArxDebug::RedirectIOToConsole() { int hConHandle; long lStdHandle; FILE * fp; if ((m_bConsoleInitialize = CreateDebugConsole())) { freopen("CONOUT$", "wt", stdout); freopen("CONERR$", "wt", stderr); freopen("CONIN$", "r", stdin) ; } } bool ArxDebug::CreateDebugConsole() { CONSOLE_SCREEN_BUFFER_INFO coninfo; // allocate a console for this app if (!AllocConsole()) { MessageBoxA(NULL, "Cannot create Log Console ", "Log Console Error ", MB_OK | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL); return false ; } SetConsoleTitleA("Arx Fatalis Debug Window"); // set the screen buffer to be big enough to let us scroll text GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo); coninfo.dwSize.X = ARXCOMMON_MAX_CONSOLE_ROWS ; coninfo.dwSize.Y = ARXCOMMON_MAX_CONSOLE_LINES; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize); return true ; } void ArxDebug::CleanConsole() { if (m_bConsoleInitialize) { FreeConsole(); } } /* Log Functions */ void ArxDebug::StartLogSession() { if (CreateLogDirectory()) { unsigned int uiID = static_cast(time(NULL)); std::ostringstream ossFileName ; ossFileName << "..\\Log\\Log__" << uiID << ".txt"; m_fsFile.open(ossFileName.str().c_str(), std::ios::out | std::ios::app); if (m_fsFile) { m_bOpenLogFile = true ; } else { m_bOpenLogFile = false ; MessageBoxA(NULL, "Log file cannot be create. May be you dont have the permission or enought space disk.", "Log File ", MB_OK | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL); } } } /* Use to manage color inside the console */ void ArxDebug::LogTypeManager(ARX_DEBUG_LOG_TYPE eType) { HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); time_t timestamp; struct tm * t; timestamp = time(NULL); t = localtime(×tamp); switch (eType) { case eLogWarning : SetConsoleTextAttribute(hStdOut, ARXDEBUG_COLOR_WARNING); m_ossBuffer << "[Warning : " << t->tm_hour << "h " << t->tm_min << "m " << t->tm_sec << "s] : "; break; case eLogError : SetConsoleTextAttribute(hStdOut, ARXDEBUG_COLOR_ERROR); m_ossBuffer << "[Error : " << t->tm_hour << "h " << t->tm_min << "m " << t->tm_sec << "s] : "; break; case eLog : default: SetConsoleTextAttribute(hStdOut, ARXDEBUG_COLOR_DEFAULT); m_ossBuffer << "[Log : " << t->tm_hour << "h " << t->tm_min << "m " << t->tm_sec << "s] : "; } } /* Add tabulation for a better look */ void ArxDebug::AddTabulation(std::ostringstream & _ossBuffer) { for (unsigned int i = 0 ; i < m_uiTabulation ; ++i) { _ossBuffer << "\t"; } } /* Use to log a message */ void ArxDebug::Log(ARX_DEBUG_LOG_TYPE eType, const char * _sMessage, ...) { //Use to stack the message and the params char sBuffer[ARXCOMMON_BUFFERSIZE]; //Treat the ... Params va_list arg_ptr ; va_start(arg_ptr, _sMessage); _vsnprintf(sBuffer, ARXCOMMON_BUFFERSIZE, _sMessage, arg_ptr); va_end(arg_ptr) ; LogTypeManager(eType); //Use to Add the tabulation inside the oss AddTabulation(m_ossBuffer); m_ossBuffer << sBuffer << "\n"; //We want to write log inside a file if (m_bOpenLogFile) { m_fsFile << m_ossBuffer.str().c_str(); m_fsFile.flush(); } //Write the log on the console if (m_bConsoleInitialize) { std::cout << m_ossBuffer.str().c_str(); std::cout.flush(); } } /* Close the stream */ void ArxDebug::EndLogSession() { if (m_bOpenLogFile) { m_fsFile.close(); m_bOpenLogFile = false ; } } /* Add a new session into the log */ void ArxDebug::OpenTag(const char * _sTag) { ++m_uiTabulation; m_ossBuffer << "[Log : " << __TIME__ << "] :"; AddTabulation(m_ossBuffer); m_ossBuffer << " ---------------- " << _sTag << " ----------------" << "\n"; if (m_bOpenLogFile) { m_fsFile << m_ossBuffer.str().c_str(); m_fsFile.flush(); } //Write tag inside the console if (m_bConsoleInitialize) { std::cout << m_ossBuffer.str().c_str(); } } /* Close a tag */ void ArxDebug::CloseTag() { (m_uiTabulation == 0) ? m_uiTabulation : --m_uiTabulation; }