/* "CodeWorker": a scripting language for parsing and generating text. Copyright (C) 1996-1997, 1999-2002 Cédric Lemaire This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA To contact the author: codeworker@free.fr */ #ifdef WIN32 #pragma warning(disable: 4503) #pragma warning (disable : 4786) #endif #include #include #include "ScpStream.h" #include "UtlException.h" #include "UtlTimer.h" #ifndef WIN32 # include "UtlString.h" // for Debian/gcc 2.95.4 #endif #include "CGRuntime.h" #include "DtaScript.h" #include "DtaProject.h" #include "ExprScriptFunction.h" #include "GrfFunction.h" #include "BNFClauseCall.h" #include "GrfQuantifyExecution.h" namespace CodeWorker { bool DtaQuantifyFunction::operator < (const DtaQuantifyFunction& function) const { return (_sName < function._sName); } bool DtaQuantifyFunction::operator > (const DtaQuantifyFunction& function) const { return (_sName > function._sName); } bool DtaQuantifyFunction::operator ==(const DtaQuantifyFunction& function) const { return (_sName == function._sName) && (_sFile == function._sFile) && (_iLocation == function._iLocation); } bool DtaQuantifyFunction::operator !=(const DtaQuantifyFunction& function) const { return !((*this) == function); } GrfQuantifyExecution::~GrfQuantifyExecution() { delete _pFilename; } void GrfQuantifyExecution::handleBeforeExecutionCBK(GrfCommand* pCommand, DtaScriptVariable& /*visibility*/) { incrementCounter(pCommand); } void GrfQuantifyExecution::handleAfterExecutionCBK(GrfCommand* /*pCommand*/, DtaScriptVariable& /*visibility*/) {} void GrfQuantifyExecution::handleAfterExceptionCBK(GrfCommand* /*pCommand*/, DtaScriptVariable& /*visibility*/, UtlException& /*exception*/) {} void GrfQuantifyExecution::handleStartingFunction(GrfFunction* pFunction) { GrfExecutionContext::handleStartingFunction(pFunction); pFunction->startTimer(); } void GrfQuantifyExecution::handleEndingFunction(GrfFunction* pFunction) { pFunction->stopTimer(); GrfExecutionContext::handleEndingFunction(pFunction); } void GrfQuantifyExecution::handleStartingBNFClause(BNFClauseCall* pBNFClause) { GrfExecutionContext::handleStartingBNFClause(pBNFClause); pBNFClause->startTimer(); } void GrfQuantifyExecution::handleEndingBNFClause(BNFClauseCall* pBNFClause) { pBNFClause->stopTimer(); GrfExecutionContext::handleEndingBNFClause(pBNFClause); } SEQUENCE_INTERRUPTION_LIST GrfQuantifyExecution::openSession(DtaScriptVariable& visibility) { SEQUENCE_INTERRUPTION_LIST result; CGRuntime::traceLine("-- quantify session --"); std::string sFilename; try { _listOfPredefinedFunctions = std::map(); _listOfUserFunctions = std::map >(); ExprScriptFunction::clearCounters(); _iCoveredCode = 0; _iTotalCode = 0; if (_pFilename != NULL) { sFilename = _pFilename->getValue(visibility); if (sFilename.size() < 5) throw UtlException("HTML file must have extension '.htm' or '.html'"); std::string sExtension = sFilename.substr(sFilename.size() - 5); if ((stricmp(sExtension.c_str(), ".html") != 0) && (stricmp(sExtension.c_str() + 1, ".htm") != 0)) throw UtlException("HTML file must have extension '.htm' or '.html'"); } UtlTimer myTimer; myTimer.start(); result = GrfBlock::executeInternal(visibility); myTimer.stop(); char tcMessage[80]; sprintf(tcMessage, "quantify execution time = %dms", myTimer.getTimeInMillis()); CGRuntime::traceLine(tcMessage); } catch(UtlException&/* exception*/) { CGRuntime::traceLine("-- quantify session interrupted by an exception --"); throw/* UtlException(exception)*/; } applyRecursively(recoverData); if (sFilename.empty()) displayResults(visibility); else generateHTMLFile(sFilename.c_str(), visibility); CGRuntime::traceLine("-- end of quantify session --"); return result; } void GrfQuantifyExecution::handleBeforeScriptExecutionCBK(GrfCommand* /*pCommand*/, DtaScriptVariable& /*visibility*/) {} void GrfQuantifyExecution::handleAfterScriptExecutionCBK(GrfCommand* pCommand, DtaScriptVariable& /*visibility*/) { pCommand->applyRecursively(recoverData); } void GrfQuantifyExecution::recoverData(GrfCommand* pCommand) { if (pCommand->getFunctionName() != NULL) { if (pCommand->isAPredefinedFunction()) getCurrentQuantify()->registerPredefinedFunction(pCommand); else getCurrentQuantify()->registerUserFunction((GrfFunction*) pCommand); } getCurrentQuantify()->registerCode(pCommand); } void GrfQuantifyExecution::registerCode(GrfCommand* pCommand) { if (getParsingFilePtr(pCommand) != NULL) { _iTotalCode++; if (getCounter(pCommand) > 0) _iCoveredCode++; _coveredLines[getParsingFilePtr(pCommand)][getFileLocation(pCommand)] = getCounter(pCommand); } } void GrfQuantifyExecution::registerUserFunction(GrfFunction* pFunction) { if (getParsingFilePtr(pFunction) != NULL) { std::map >::iterator iterateFile = _listOfUserFunctions.find(getParsingFilePtr(pFunction)); if (iterateFile != _listOfUserFunctions.end()) { std::map::iterator iterateName = iterateFile->second.find(pFunction->getFunctionName()); if (iterateName != iterateFile->second.end()) { iterateName->second._iCounter = getCounter(pFunction); iterateName->second._iTimeInMillis = getTimeInMillis(pFunction); } else { DtaQuantifyFunction& myFunction = iterateFile->second[pFunction->getFunctionName()]; myFunction._sName = pFunction->getFunctionName(); myFunction._sFile = getParsingFilePtr(pFunction); myFunction._iLocation = getFileLocation(pFunction); myFunction._iCounter = getCounter(pFunction); myFunction._iTimeInMillis = getTimeInMillis(pFunction); } } else { DtaQuantifyFunction& myFunction = _listOfUserFunctions[getParsingFilePtr(pFunction)][pFunction->getFunctionName()]; myFunction._sName = pFunction->getFunctionName(); myFunction._sFile = getParsingFilePtr(pFunction); myFunction._iLocation = getFileLocation(pFunction); myFunction._iCounter = getCounter(pFunction); myFunction._iTimeInMillis = getTimeInMillis(pFunction); } } } void GrfQuantifyExecution::registerPredefinedFunction(GrfCommand* pCommand) { _listOfPredefinedFunctions[pCommand->getFunctionName()] = _listOfPredefinedFunctions[pCommand->getFunctionName()] + getCounter(pCommand); } void GrfQuantifyExecution::displayResults(DtaScriptVariable& visibility) { if (!_listOfUserFunctions.empty()) { CGRuntime::traceLine("User defined functions:"); for (std::map >::iterator i = _listOfUserFunctions.begin(); i != _listOfUserFunctions.end(); i++) { std::string sCompleteFileName; std::ifstream* pFile = openInputFileFromIncludePath(i->first.c_str(), sCompleteFileName); for (std::map::iterator j = i->second.begin(); j != i->second.end(); j++) { CGRuntime::traceText(" " + j->second._sName + "(...) file \"" + j->second._sFile); if (pFile != NULL) { setLocation(*pFile, j->second._iLocation); char tcMessage[40]; sprintf(tcMessage, "\" at %d", getLineCount(*pFile)); CGRuntime::traceText(tcMessage); } char tcMessage[80]; sprintf(tcMessage, ": %d occurences in %dms", j->second._iCounter, j->second._iTimeInMillis); CGRuntime::traceLine(tcMessage); } if (pFile != NULL) { pFile->close(); delete pFile; } } } CGRuntime::traceLine("Predefined functions:"); for (std::map::iterator i = ExprScriptFunction::getFunctionRegister().begin(); i != ExprScriptFunction::getFunctionRegister().end(); i++) { if (*(i->second.pCounter) > 0) { CGRuntime::traceText(" " + i->first + "(...): "); char tcMessage[40]; sprintf(tcMessage, "%d occurrences", *(i->second.pCounter)); CGRuntime::traceLine(tcMessage); } } if (!_listOfPredefinedFunctions.empty()) { CGRuntime::traceLine("Procedures:"); for (std::map::iterator i = _listOfPredefinedFunctions.begin(); i != _listOfPredefinedFunctions.end(); i++) { CGRuntime::traceText(" " + i->first + "(...): "); char tcMessage[40]; sprintf(tcMessage, "%d occurrences", i->second); CGRuntime::traceLine(tcMessage); } } double dCoveredCode = getCoveredCode(); double dTotalCode = getTotalCode(); double dPercentCovered = floor(100.0 * dCoveredCode / dTotalCode); char tcMessage[80]; sprintf(tcMessage, "Covered source code: %d%%", (int) dPercentCovered); CGRuntime::traceLine(tcMessage); } void GrfQuantifyExecution::generateHTMLFile(const char* sFilename, DtaScriptVariable& visibility) { static const char* tColorArray[6][6]={{"#ff0000", "#0000ff", "#0000ff", "#0000ff", "#0000ff", "#0000ff"}, {"#0000ff", "#ff0000", "#ffff00", "#ffff00", "#00ff00", "#00ff00"}, {"#0000ff", "#ffff00", "#ff0000", "#ff8000", "#ffff00", "#ffff00"}, {"#0000ff", "#ffff00", "#ff8000", "#ff0000", "#ff8000", "#ff8000"}, {"#0000ff", "#00ff00", "#ffff00", "#ff8000", "#ff0000", "#ff00ff"}, {"#0000ff", "#00ff00", "#ffff00", "#ff8000", "#ff00ff", "#ff0000"}}; if ((sFilename != NULL) && (sFilename[0] != '\0')) { std::fstream* pHTMLFile = DtaScript::openOutputFile(sFilename, true); CGRuntime::traceLine("Generating HTML file \"" + std::string(sFilename) + "\""); (*pHTMLFile) << "" << std::endl; (*pHTMLFile) << "" << std::endl; (*pHTMLFile) << "Covered source code" << std::endl; (*pHTMLFile) << "" << std::endl; (*pHTMLFile) << "" << std::endl; // generates predefined functions occurences bool bInitialized = false; for (std::map::iterator i1 = ExprScriptFunction::getFunctionRegister().begin(); i1 != ExprScriptFunction::getFunctionRegister().end(); i1++) { if (*(i1->second.pCounter) > 0) { if (!bInitialized) { bInitialized = true; (*pHTMLFile) << "

Predefined functions:

" << std::endl; (*pHTMLFile) << "" << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; } (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; } } if (bInitialized) (*pHTMLFile) << "

Function name

Occurence

" << i1->first << "(...) " << "

" << *(i1->second.pCounter) << "

" << std::endl; // generates instructions occurrences if (!_listOfPredefinedFunctions.empty()) { (*pHTMLFile) << "

Procedures:

" << std::endl; (*pHTMLFile) << "" << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; for (std::map::iterator i2 = _listOfPredefinedFunctions.begin(); i2 != _listOfPredefinedFunctions.end(); i2++) { (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; } (*pHTMLFile) << "

Instruction name

Occurence

" << i2->first << "(...) " << "

" << i2->second << "

" << std::endl; } // generates by file for (std::map >::const_iterator i = _coveredLines.begin(); i != _coveredLines.end(); i++) { std::string sCompleteFileName; std::ifstream* pFile = openInputFileFromIncludePath(i->first.c_str(), sCompleteFileName); if (pFile != NULL) { (*pHTMLFile) << "

File \"" << i->first << "\":

" << std::endl; // generates predefined functions bInitialized = false; std::map >::iterator i3 = _listOfUserFunctions.find(i->first); if (i3 != _listOfUserFunctions.end()) { for (std::map::iterator i4 = i3->second.begin(); i4 != i3->second.end(); i4++) { if (!bInitialized) { bInitialized = true; (*pHTMLFile) << "" << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; } setLocation(*pFile, i4->second._iLocation); (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; (*pHTMLFile) << " " << std::endl; } } if (bInitialized) { (*pHTMLFile) << "

User defined function

Occurence

Time in ms

" << i4->second._sName << "(...) at " << getLineCount(*pFile) << "

" << i4->second._iCounter << "

" << i4->second._iTimeInMillis << "

" << std::endl; setLocation(*pFile, 0); } // generates colored source std::map::const_iterator j; int iMaxCounter = 0; for (j = i->second.begin(); j != i->second.end(); j++) if (j->second > iMaxCounter) iMaxCounter = j->second; double dShare = ((double) iMaxCounter) / 6.0; std::string sEmptyFormat; char sSizeFormat[10]; sprintf(sSizeFormat, "%d", iMaxCounter); int iSizeFormat = strlen(sSizeFormat); for (int k = 0; k < iSizeFormat; k++) sEmptyFormat += " "; std::string sLine; int iPrecLocation = 0; j = i->second.begin(); while (readLine(*pFile, sLine)) { int iNextLocation = getLocation(*pFile); while ((j->first < iPrecLocation) && (j != i->second.end())) j++; int iNbLines = iMaxCounter + 1; while ((j->first < iNextLocation) && (j != i->second.end())) { if (iNbLines > j->second) iNbLines = j->second; j++; } (*pHTMLFile) << "
"; if ((iNbLines > iMaxCounter) || (iNbLines == 0)) (*pHTMLFile) << "  " << sEmptyFormat; else { char sLineCount[16]; sprintf(sLineCount, "%d", iNbLines); (*pHTMLFile) << "[" << (sEmptyFormat.c_str() + 6*strlen(sLineCount)) << sLineCount << "]"; } (*pHTMLFile) << "
"; if (iNbLines <= iMaxCounter) { (*pHTMLFile) << ""; else if (dShare < 1.0) (*pHTMLFile) << tColorArray[iMaxCounter - 1][iNbLines] << "\">"; else { int iIndex = (int) (((double) (iNbLines - 1)) / dShare); (*pHTMLFile) << tColorArray[5][iIndex] << "\">"; } int iFirstChar = 0; do { if (sLine[iFirstChar] == ' ') (*pHTMLFile) << " "; else if (sLine[iFirstChar] == '\t') (*pHTMLFile) << "    "; else break; iFirstChar++; } while (true); (*pHTMLFile) << (sLine.c_str() + iFirstChar) << "" << std::endl; } else { int iFirstChar = 0; do { if (sLine[iFirstChar] == ' ') (*pHTMLFile) << " "; else if (sLine[iFirstChar] == '\t') (*pHTMLFile) << "    "; else break; iFirstChar++; } while (true); (*pHTMLFile) << "" << (sLine.c_str() + iFirstChar) << "" << std::endl; } iPrecLocation = iNextLocation; } pFile->close(); delete pFile; } } double dPercentCovered = floor(100.0 * ((double) getCoveredCode()) / ((double) getTotalCode())); (*pHTMLFile) << "

Covered source code: " << dPercentCovered << "%

" << std::endl; (*pHTMLFile) << "" << std::endl; (*pHTMLFile) << "" << std::endl; pHTMLFile->close(); delete pHTMLFile; } } }