diff -r 000000000000 -r 638b9c697799 apicompatanamdw/compatanalysercmd/headeranalyser/src/ReportGenerator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apicompatanamdw/compatanalysercmd/headeranalyser/src/ReportGenerator.cpp Tue Jan 12 14:52:39 2010 +0530 @@ -0,0 +1,1164 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "CmdGlobals.h" +#ifdef __WIN__ +#pragma warning(disable:4786) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "ReportGeneratorConstants.h" +#include "CmdGlobals.h" +#include "ReportIssue.h" +#include "XMLModuleErrorHandler.h" +#include "HAException.h" +#include "Utils.h" +#include "Issues.h" +#include "BBCFileUtils.h" +using namespace std; + +extern vector > > HeaderInfoList; // vector>> + +XERCES_CPP_NAMESPACE_USE + + +const char* KXMLStyleSheet = "xml-stylesheet"; + +// Style sheet filename +const char* KXMLXSL = "type=\"text/xsl\" href=\"BBCResults.xsl\""; +// Base64 coding characters +const char* KBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"; + +#include "ReportGenerator.h" + +// ---------------------------------------------------------------------------- +// ReportGenerator::ReportGenerator +// ---------------------------------------------------------------------------- +// +ReportGenerator::ReportGenerator(string aOutputFile) +: +iOutputFile(aOutputFile), +iIssueId(0), +iDOMDocument(0), +iDOMRoot(0) +{ + // START -- Support for file checksum and comments + unsigned long crc; + iCrcTable = new unsigned long[256]; + for ( int i = 0; i <= 255 ; i++ ) + { + crc = i; + for ( int j = 8 ; j > 0; j-- ) + { + if ( crc & 1 ) + crc = ( crc >> 1 ) ^ 0xEDB88320L; + else + crc >>= 1; + } + iCrcTable[i] = crc; + } + // END -- Support for file checksum and comments +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::~ReportGenerator +// ---------------------------------------------------------------------------- +// +ReportGenerator::~ReportGenerator() +{ + // START -- Support for file checksum and comments + delete iCrcTable; + iCrcTable = NULL; + // END -- Support for file checksum and comments + if( iDOMDocument ) + { + iDOMDocument->release(); + } + for( issueMap::iterator i = iIssueMap.begin(); i != iIssueMap.end(); ++i ) + { + delete i->second; + i->second = 0; + } +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::setXSL +// ---------------------------------------------------------------------------- +// +void ReportGenerator::setXSL(string aXSLFilename, bool aIncludeInXML) +{ + iXSLFile = aXSLFilename; + iEmbedXSL = aIncludeInXML; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::setDTD +// ---------------------------------------------------------------------------- +// +void ReportGenerator::setDTD(string aDTDFilename, bool aIncludeInDTD) +{ + iDTDFile = aDTDFilename; + iEmbedDTD = aIncludeInDTD; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::startReport +// ---------------------------------------------------------------------------- +// +void ReportGenerator::startReport() +{ + initialiseDOM(); +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::finishReport +// ---------------------------------------------------------------------------- +// +void ReportGenerator::finishReport() +{ + DOMElement* issuelist = createIssueListNode(); + iDOMRoot->appendChild(issuelist); + dumpDOMToFile(); +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::loadStringTables +// ---------------------------------------------------------------------------- +// +void ReportGenerator::loadStringTables(string aFilename) +{ +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::setCmdLineParms +// ---------------------------------------------------------------------------- +// +void ReportGenerator::setCmdLineParms(map aParms) +{ + map::iterator begin = aParms.begin(); + map::iterator end = aParms.end(); + while (begin != end) + { + iParams.insert(*begin); + begin++; + } +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::getCmdLineParm +// ---------------------------------------------------------------------------- +// +string ReportGenerator::getCmdLineParm(string aParm) +{ + map::iterator begin = iParams.find(aParm); + if (begin != iParams.end()) + { + return (*begin).second; + } + else + { + return "Not specified"; + } +} + + +// ---------------------------------------------------------------------------- +// ReportGenerator::setVersions +// ---------------------------------------------------------------------------- +// +void ReportGenerator::setVersions(string aBaseline, string aCurrent) +{ + iBaselineVersion = aBaseline; + iCurrentVersion = aCurrent; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::addIssue +// ---------------------------------------------------------------------------- +// +int ReportGenerator::addIssue(ReportIssue* aIssue) +{ + aIssue->iId = iIssueId++; + + string key = "<"; + key += aIssue->HeaderFile(); + key += "><"; + key += aIssue->CompareFileName(); + key += ">"; + + issueMapIterator it = iIssueMap.find(key); + if (it != iIssueMap.end()) + { + bool lineInfoNeed = true; + // header entry is present in the report. append the issue to the header issue list + issueVector* v = it->second; + issueVector::iterator iv_it=v->begin(); + bool notAnalysed = false; + for (; iv_it != v->end(); ++iv_it) + { + ReportIssue* issue = iv_it->second; + + TIssueIdentity id = issue->IdentityId(); + TIssueType type = issue->TypeId(); + if( id == EIssueIdentityFile && type == EIssueTypeEmpty) + { + notAnalysed = true; + lineInfoNeed = issue->LineInfoNeeded(); + break; + } + } + if(lineInfoNeed == false) + { + aIssue->SetLineNumber(0); + } + if( v->insert(pair(aIssue,aIssue)).second == false ) + { + return -1; + } + } else + { + // header entry is not present in the report. create an entry for the header with this issue + issueVector* v = new issueVector(); + v->insert(pair(aIssue,aIssue)); + issueEntry entry(key,v); + iIssueMap.insert(entry); + } + + return iIssueId-1; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::addIssue +// ---------------------------------------------------------------------------- +// +int ReportGenerator::addIssue(const string& aFile, + const string& aFQName, const TIssueIdentity& aIdentityId, + const TIssueType& aTypeId, const TBCSeverity& aBCSeverityId, + const TSCSeverity& aSCSeverityId, const string& aIgnoreInformation, + int aLineNumber, const string& aCompareFileName, const string& aCompilationError, bool alineNoNeeded ) +{ + string fqName = aFQName; + int loc = fqName.find(__FUN_MANGLED__); + if(loc != -1) + { + fqName = fqName.substr(0,loc); + } + ReportIssue* issue = new ReportIssue(0, aFile, fqName, + aIdentityId, aTypeId, aBCSeverityId, aSCSeverityId, aIgnoreInformation, + aLineNumber, aCompareFileName, aCompilationError, alineNoNeeded ); + + /*return*/ + int ret = addIssue(issue); + if( ret == -1) + { + delete issue; + } + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::dumpXSLToFile +// ---------------------------------------------------------------------------- +// +void ReportGenerator::dumpXSLToFile() +{ +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::dumpDTDToFile +// ---------------------------------------------------------------------------- +// +void ReportGenerator::dumpDTDToFile() +{ +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::dumpDOMToFile +// ---------------------------------------------------------------------------- +// +void ReportGenerator::dumpDOMToFile() +{ + XMLCh* features = _X("Core"); + DOMImplementation* imp = DOMImplementationRegistry::getDOMImplementation(features); + _XX(features); + DOMWriter* writer = ((DOMImplementationLS*)imp)->createDOMWriter(); + + writer->setFeature( XMLUni::fgDOMWRTFormatPrettyPrint,true); + DOMErrorHandler* errorHandler = new XMLModuleErrorHandler(); + // Set error handler + writer->setErrorHandler(errorHandler); + XMLCh* tempfilename = XMLString::transcode(iOutputFile.c_str()); + XMLFormatTarget* ft = new LocalFileFormatTarget(tempfilename); + writer->writeNode(ft, *iDOMDocument); + XMLString::release(&tempfilename); + delete ft; + writer->release(); + delete errorHandler; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::generateVersionIdNodes +// ---------------------------------------------------------------------------- +// +void ReportGenerator::generateVersionIdNodes() +{ +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::initialiseDOM +// ---------------------------------------------------------------------------- +// +void ReportGenerator::initialiseDOM() +{ + XMLCh * features = _X("Core"); + DOMImplementation* imp = DOMImplementationRegistry::getDOMImplementation(features); + _XX(features); + if (imp != NULL) + { + try + { + XMLCh * repRoot = _X(NODE_REPORTROOT); + DOMDocument* doc = imp->createDocument(NULL, repRoot, NULL); + _XX(repRoot); + if( iDOMDocument ) + { + iDOMDocument->release(); + iDOMDocument = 0; + } + iDOMDocument = doc; + + XMLCh * stylesheet = XMLString::transcode(KXMLStyleSheet); + XMLCh * xsl = XMLString::transcode(KXMLXSL); + + // Style sheet is inserted to DOM document + iDOMDocument->insertBefore( + iDOMDocument->createProcessingInstruction( + stylesheet, + xsl + ), + iDOMDocument->getDocumentElement() + ); + XMLString::release(&stylesheet); + XMLString::release(&xsl); + + iDOMRoot = iDOMDocument->getDocumentElement(); + // Header node created + DOMElement* header = createHeaderNode(); + iDOMRoot->appendChild(header); + } catch (const XMLException& /*e*/) + { + throw HAException("Error initialising the DOM Document"); + } + } +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::uninitialiseDOM +// ---------------------------------------------------------------------------- +// +void ReportGenerator::uninitialiseDOM() +{ +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createOpenNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createOpenNode(const char* aNodeName) +{ + DOMElement* ret = NULL; + XMLCh* ch = XMLString::transcode(aNodeName); + ret = iDOMDocument->createElement(ch); + XMLString::release(&ch); + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createHeaderNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createHeaderNode() +{ + DOMElement* ret = NULL; + ret = createOpenNode(NODE_HEADER); + vector childvec; + + childvec.push_back(createSimpleTextNode(NODE_HEADER_BASELINEVERSION, iBaselineVersion.c_str())); + childvec.push_back(createSimpleTextNode(NODE_HEADER_CURRENTVERSION, iCurrentVersion.c_str())); + childvec.push_back(createTimestampNode()); + childvec.push_back(createSimpleTextNode(NODE_HEADER_HAVERSION, HEADER_ANALYSER_VERSION)); + childvec.push_back(createSimpleTextNode(NODE_HEADER_FORMATVERSION, HEADER_ANALYSER_REPORT_VERSION)); + childvec.push_back(createCmdLineNode()); + + appendChildrenToNode(ret, childvec); + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::removeRemovedSubClasses +// ---------------------------------------------------------------------------- +// +void ReportGenerator::removeRemovedSubClasses() +{ + issueMapIterator it = iIssueMap.begin(); + for (; it != iIssueMap.end();++it) + { + issueVector* iv = it->second; + issueVector::iterator iv_it=iv->begin(); + + for (; iv_it != iv->end(); ++iv_it) + { + ReportIssue* issue = iv_it->second; + + TIssueIdentity id = issue->IdentityId(); + TIssueType type = issue->TypeId(); + + //Do not process macros or other than issues type "removed" + if ( EIssueTypeRemoval == type && EIssueIdentityMacro != id ) + { + string fqname = issue->FQName(); + fqname += "::"; + + issueVector::iterator iv_it2=iv_it; + ++iv_it2; + + for (; iv_it2 != iv->end(); ++iv_it2) + { + ReportIssue* issue2 = iv_it2->second; + string fqname2 = issue2->FQName(); + + //If the issue is inside removed class it can be removed from list + if ( 0 == fqname2.compare(0, fqname.length(), fqname) ) + { + issueVector::iterator iv_it3 = iv_it2; + --iv_it2; + iv->erase(iv_it3); + } else //No more issues inside removed class so break + { + break; + } + } + } + } + + } +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::functionMapping +// ---------------------------------------------------------------------------- +// +TIssueIdentity ReportGenerator::functionMapping(const vector & ids) +{ + + TIssueIdentity ret = EIssueIdentityExportedFunction; + + if (ids.size() == 1) + { + ret = ids[0]; + } + else if (ids.size() == 3) + { + ret = EIssueIdentityExportedVirtualInlineFunction; + } + else + { + if ( (EIssueIdentityExportedFunction == ids[0] && EIssueIdentityVirtualFunction == ids[1]) || + (EIssueIdentityExportedFunction == ids[1] && EIssueIdentityVirtualFunction == ids[0]) ) + { + ret = EIssueIdentityExportedVirtualFunction; + } else if ( (EIssueIdentityExportedFunction == ids[0] && EIssueIdentityInlineFunction == ids[1]) || + (EIssueIdentityExportedFunction == ids[1] && EIssueIdentityInlineFunction == ids[0]) ) + { + ret = EIssueIdentityExportedInlineFunction; + } else if ( (EIssueIdentityInlineFunction == ids[0] && EIssueIdentityVirtualFunction == ids[1]) || + (EIssueIdentityInlineFunction == ids[1] && EIssueIdentityVirtualFunction == ids[0]) ) + { + ret = EIssueIdentityVirtualInlineFunction; + } + } + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::mergeFunctionIssues +// ---------------------------------------------------------------------------- +// +void ReportGenerator::mergeFunctionIssues() +{ + issueMapIterator it = iIssueMap.begin(); + for (; it != iIssueMap.end();++it) + { + issueVector* iv = it->second; + issueVector::iterator iv_it=iv->begin(); + + for (; iv_it != iv->end(); ++iv_it) + { + ReportIssue* issue = iv_it->second; + + TIssueIdentity id = issue->IdentityId(); + TIssueType type = issue->TypeId(); + + //Process functions only + if ( + EIssueIdentityExportedFunction == id || + EIssueIdentityInlineFunction == id || + EIssueIdentityVirtualFunction == id + ) + { + vector identities; + identities.reserve(3); + string fqname = issue->FQName(); + identities.push_back(issue->IdentityId()); + issueVector::iterator iv_it2=iv_it; + ++iv_it2; + + TBCSeverity bcseverity = issue->BCSeverity(); + TSCSeverity scseverity = issue->SCSeverity(); + + for (; iv_it2 != iv->end(); ++iv_it2) + { + ReportIssue* issue2 = iv_it2->second; + string fqname2 = issue2->FQName(); + TIssueType type2 = issue2->TypeId(); + + //If the issue has same type and it is for the same function + if ( (fqname2 == fqname) && (type2 == type) ) + { + if ( issue2->BCSeverity() < bcseverity ) + { + bcseverity = issue2->BCSeverity(); + } + if ( issue2->SCSeverity() < scseverity ) + { + scseverity = issue2->SCSeverity(); + } + identities.push_back(issue2->IdentityId()); + issueVector::iterator iv_it3 = iv_it2; + --iv_it2; + iv->erase(iv_it3); + } + } + if (identities.size() > 0) + { + issue->SetIdentityId( functionMapping(identities) ); + issue->SetBCSeverity(bcseverity); + issue->SetSCSeverity(scseverity); + } + } + } + + } +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::preprocessIssueList +// ---------------------------------------------------------------------------- +// +void ReportGenerator::preprocessIssueList() +{ + removeRemovedSubClasses(); + mergeFunctionIssues(); +} + + +// ---------------------------------------------------------------------------- +// ReportGenerator::createIssueListNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createIssueListNode() +{ + preprocessIssueList(); + + DOMElement* ret = NULL; + bool apiFound = false; + ret = createOpenNode(NODE_ISSUELIST); + issueMapIterator it = iIssueMap.begin(); + while (it != iIssueMap.end()) + { + apiFound = false; + issueVector* iv = it->second; + issueVector::const_iterator iv_it = iv->begin(); + + DOMElement* headerfilenode = createOpenNode(NODE_ISSUELIST_HEADERFILE); + DOMElement* filenamenode = createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_FILENAME, iv_it->second->HeaderFile().c_str()); + headerfilenode->appendChild(filenamenode); + + // Append compared file here, Check from first Report issue, what was compare file name + DOMElement* compareFileNameNode = createSimpleTextNode( + NODE_ISSUELIST_HEADERFILE_COMPARE_FILENAME, iv_it->second->CompareFileName().c_str()); + + headerfilenode->appendChild( compareFileNameNode ); + + // START -- Support for file checksum and comments + DOMElement* statusNode = createSimpleTextNode( NODE_ISSUELIST_HEADERFILE_STATUS, "" ); + headerfilenode->appendChild( statusNode ); + DOMElement* commentNode = createSimpleTextNode( NODE_ISSUELIST_HEADERFILE_COMMENT, "" ); + headerfilenode->appendChild( commentNode ); + + // If Global header list is found with API info, then fill those in report file. + for(unsigned int i = 0; i < HeaderInfoList.size(); i++ ) + { + if(stricmp (HeaderInfoList.at(i).first.c_str(), iv_it->second->CompareFileName().c_str()) == 0) + { + DOMElement* apiNode = createAPIAttributeNode( NODE_ISSUELIST_HEADERFILE_ISSUE_APISTRING, + HeaderInfoList.at(i).second.first.c_str(), HeaderInfoList.at(i).second.second.c_str() ); + headerfilenode->appendChild(apiNode); + apiFound = true; + } + else if (stricmp( HeaderInfoList.at(i).first.c_str(), iv_it->second->HeaderFile().c_str()) == 0) + { + DOMElement* apiNode = createAPIAttributeNode( NODE_ISSUELIST_HEADERFILE_ISSUE_APISTRING, + HeaderInfoList.at(i).second.first.c_str(), HeaderInfoList.at(i).second.second.c_str() ); + headerfilenode->appendChild(apiNode); + apiFound = true; + } + if( apiFound == true ) + break; + } + // Global list is present, but the header has not been found from the list, then add api info for the header as "Unknown" + if( apiFound == false && HeaderInfoList.size() > 0) + { + DOMElement* apiNode = createAPIAttributeNode( NODE_ISSUELIST_HEADERFILE_ISSUE_APISTRING, + NODE_ISSUELIST_HEADERFILE_APIINFO_UNKNOWN, NODE_ISSUELIST_HEADERFILE_APIINFO_UNKNOWN ); + headerfilenode->appendChild(apiNode); + } + //else no API info will be available for any header. + + char checksum[14]; + if ( strlen( iv_it->second->CompareFileName().c_str() ) > 0) + getFileCRC( iv_it->second->CompareFileName().c_str(), checksum ); + else + getFileCRC( iv_it->second->HeaderFile().c_str(), checksum ); + + // END -- Support for file checksum and comments + + //START -- Support for shortname tag + string fn; + string directory; + list > dirs; + + //select current filename to display if it is present, else select base filename + if ( strlen( iv_it->second->CompareFileName().c_str() ) > 0) + { + fn = iv_it->second->CompareFileName().c_str(); + dirs = BBCFileUtils::extractFilenames(getCmdLineParm("currentdir")); + } + else + { + fn = iv_it->second->HeaderFile().c_str(); + dirs = BBCFileUtils::extractFilenames(getCmdLineParm("baselinedir")); + } + + //select appropriate baseline/current dir from the list of baseline/current dirs + list >::iterator dirbegin = dirs.begin(); + int p; + for(; dirbegin != dirs.end(); dirbegin++) + { + p = toLowerCaseWin(fn).find(toLowerCaseWin(dirbegin->first),0); + if(p!= string::npos) + { + directory = dirbegin->first; + break; + } + } + + // remove baseline/current dir part of the filename + string shortfilename; + shortfilename.reserve(256); + shortfilename = removeBase(fn,directory); + + // remove any leading directory separators from the filename + shortfilename=trimLeadingDirSeparator(shortfilename); + shortfilename = toLowerCaseWin(shortfilename); + + //create the shortname node + DOMElement* shortNameNode = createSimpleTextNode( NODE_ISSUELIST_HEADERFILE_SHORTNAME,shortfilename.c_str() ); + //END -- Support for shortname tag + + vector issueids; + for (; iv_it != iv->end(); ++iv_it) + { + ReportIssue* issue = iv_it->second; + DOMElement* issuenode = createIssueNode(*issue); + headerfilenode->appendChild(issuenode); + + // START -- Support for file checksum and comments + string issueid; + char* text; + text = _X( issuenode->getElementsByTagName( _X( "typeid" ) )->item(0)->getTextContent() ); + issueid = text; + _XX( text ); + + text = _X( issuenode->getElementsByTagName( _X( "identityid" ) )->item(0)->getTextContent() ); + issueid += text; + _XX( text ); + + text = _X( issuenode->getElementsByTagName( _X( "cause" ) )->item(0)->getTextContent() ); + issueid += text; + _XX( text ); + + issueids.push_back( issueid ); + // END -- Support for file checksum and comments + } + + ret->appendChild(headerfilenode); + it++; + + // START -- Support for file checksum and comments + sort( issueids.begin(), issueids.end() ); + getIssuesCRC( issueids, &checksum[7] ); + DOMElement* checksumNode = createSimpleTextNode( NODE_ISSUELIST_HEADERFILE_CHECKSUM, checksum ); + headerfilenode->appendChild( checksumNode ); + // END -- Support for file checksum and comments + + //START -- Support for shortname tag + // insert the shortname node + headerfilenode->appendChild( shortNameNode ); + //END -- Support for shortname tag + } + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createHeaderFileNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createHeaderFileNode() +{ + DOMElement* ret = NULL; + ret = createOpenNode(NODE_ISSUELIST_HEADERFILE); + return ret; +} + +// START -- Support for file checksum and comments + +// ---------------------------------------------------------------------------- +// ReportGenerator::getIssuesCRC +// ---------------------------------------------------------------------------- +// +void ReportGenerator::getIssuesCRC( const vector& aIssueIdsVector, char* aCrcResult ) +{ + unsigned long crc = 0xFFFFFFFFL; + vector::const_iterator iter = aIssueIdsVector.begin(); + + for ( iter = aIssueIdsVector.begin(); iter != aIssueIdsVector.end(); iter++ ) + for ( unsigned char* p = (unsigned char*) (*iter).c_str(); *p != '\0'; p++ ) + crc = iCrcTable[ ( crc & 0xff ) ^ *p ] ^ ( crc >> 8 ); + crc ^= 0xFFFFFFFFL; + + // The checksum is base64-encoded into 6 characters before it is returned. + for ( int i = 0; i < 6; ++i ) + aCrcResult[i] = KBase64[ ( crc >> ( 30 - 6 * i ) ) & 0x3f ]; + aCrcResult[6] = '\0'; + + return; +} +// END -- Support for file checksum and comments + +// START -- Support for file checksum and comments + +// ---------------------------------------------------------------------------- +// ReportGenerator::getFileCRC +// ---------------------------------------------------------------------------- +// +void ReportGenerator::getFileCRC( const char* aFilename, char* aCrcResult ) +{ + unsigned long crc; + unsigned long previousCrc; + unsigned long length = 0; + unsigned char* buffer = new unsigned char[512]; + unsigned char* p; + int count; + filebuf file; + + // Calculate CRC for file; all sequences of whitespace and/or comments + // are replaced with _one_ space. + // States: + // 0 : "within star comment" : starts with "/*" and ends when + // the next "*/" is encountered + // 1 : "within line comment" : starts with "//" and ends when + // the next "/n" or "\r" is encountered + // 2 : "normal mode" : "normal" text + + if ( file.open( aFilename, ios::in ) == NULL ) + { + strcpy( aCrcResult, "*************"); + return; + } + + crc = 0xFFFFFFFFL; + previousCrc = 0xFFFFFFFFL; + int state = 2; + char previousChar = ' '; + char slashPreviousChar = ' '; + + for ( ; ; ) + { + count = (int) file.sgetn( (char*) buffer, 512 ); + if ( count == 0 ) + { + break; + } + + for ( p = buffer; count-- != 0; p++ ) + { + if ( state == 0 ) + { + if ( previousChar == '*' && *p == '/' ) + { + state = 2; + previousChar = slashPreviousChar; + *p = ' '; + } + } + else if ( state == 1 ) + { + if ( *p == '\r' || *p == '\n' ) + { + state = 2; + previousChar = slashPreviousChar; + *p = ' '; + } + } + + if ( state == 2 ) + { + if ( *p == '/' && previousChar != '/' ) + { + slashPreviousChar = previousChar; + } + + if ( previousChar == '/' && *p == '*' ) + { + state = 0; + crc = previousCrc; // previous char should not be included in CRC + --length; + *p = ' '; // do not allow /*/ to be interpreted as a comment + } + else if ( previousChar == '/' && *p == '/' ) + { + state = 1; + crc = previousCrc; // previous char should not be included in CRC + --length; + } + else { + if ( *p == '\t' || *p == '\r' || *p == '\n' ) + { + *p = ' '; + } + if ( *p != ' ' || previousChar != ' ' ) + { + previousCrc = crc; + crc = iCrcTable[ ( crc & 0xff ) ^ *p ] ^ ( crc >> 8 ); + ++length; + } + } + } + previousChar = *p; + } + } + crc ^= 0xFFFFFFFFL; + file.close(); + delete buffer; + + // The 42-bit checksum is made up of + // * bits 32-41 : length of file MOD 1024 (10 bits) + // * bits 0-31 : the CRC-32 value + // This checksum is base64-encoded into 7 characters (42 bits / 6 bits) before it is returned. + int val; + length &= 0x3ff; + + for ( int i = 0; i < 7; ++i ) + { + if ( i == 0 ) + val = length >> 4; + else if ( i == 1 ) + val = ( ( length << 2 ) | ( crc >> 30 ) ) & 0x3f; + else + val = ( crc >> ( 30 - 6 * ( i - 1 ) ) ) & 0x3f; + aCrcResult[i] = KBase64[val]; + } + aCrcResult[7] = '\0'; + + return; +} +// END -- Support for file checksum and comments + +// ---------------------------------------------------------------------------- +// ReportGenerator::createTimestampNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createTimestampNode() +{ + DOMElement* ret = NULL; + int second, minute, hour, day, month, year; + + time_t ttime; + time(&ttime); + struct tm* time = localtime(&ttime); + second = time->tm_sec; + minute = time->tm_min; + hour = time->tm_hour; + day = time->tm_mday; + month = time->tm_mon + 1; + year = time->tm_year + 1900; + + ret = createOpenNode(NODE_HEADER_TIMESTAMP); + vector childvec; + childvec.push_back(createSimpleTextNode(NODE_HEADER_TIMESTAMP_DAY, day)); + childvec.push_back(createSimpleTextNode(NODE_HEADER_TIMESTAMP_MONTH, month)); + childvec.push_back(createSimpleTextNode(NODE_HEADER_TIMESTAMP_YEAR, year)); + childvec.push_back(createSimpleTextNode(NODE_HEADER_TIMESTAMP_HOUR, hour)); + childvec.push_back(createSimpleTextNode(NODE_HEADER_TIMESTAMP_MINUTE, minute)); + childvec.push_back(createSimpleTextNode(NODE_HEADER_TIMESTAMP_SECOND, second)); + + appendChildrenToNode(ret, childvec); + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::appendChildrenToNode +// ---------------------------------------------------------------------------- +// +void ReportGenerator::appendChildrenToNode(DOMElement* aParent, const vector& aChildren) +{ + size_t count = aChildren.size(); + for (unsigned int i = 0; i < count; i++) + { + aParent->appendChild(aChildren.at(i)); + } +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createSimpleTextNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createSimpleTextNode(const char* aNodeName, const char* aNodeText) +{ + DOMElement* ret = NULL; + + XMLCh* ch = XMLString::transcode(aNodeName); + XMLCh* ch2 = XMLString::transcode(aNodeText); + ret = iDOMDocument->createElement(ch); + DOMText* tn = iDOMDocument->createTextNode(ch2); + ret->appendChild(tn); + XMLString::release(&ch); + XMLString::release(&ch2); + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createSimpleTextNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createSimpleTextNode(const char* aNodeName, const XMLCh* aNodeText) +{ + DOMElement* ret = NULL; + XMLCh* ch = XMLString::transcode(aNodeName); + ret = iDOMDocument->createElement(ch); + DOMText* tn = iDOMDocument->createTextNode(aNodeText); + ret->appendChild(tn); + XMLString::release(&ch); + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createSimpleTextNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createSimpleTextNode(const char* aNodeName, const int aInteger) +{ + DOMElement* ret = NULL; + XMLCh* ch = XMLString::transcode(aNodeName); + string temp; + itoa(aInteger, temp, 10); + XMLCh* ch2 = XMLString::transcode(temp.c_str()); + ret = iDOMDocument->createElement(ch); + DOMText* tn = iDOMDocument->createTextNode(ch2); + ret->appendChild(tn); + XMLString::release(&ch); + XMLString::release(&ch2); + return ret; +} +// ---------------------------------------------------------------------------- +// ReportGenerator::createAttributeNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createAPIAttributeNode(const char* aNodeName, const char* aNodeAPI,const char* aNodeCategory) +{ + DOMElement* ret = NULL; + + XMLCh* ch = XMLString::transcode(aNodeName); + XMLCh* apivalue = XMLString::transcode(aNodeAPI); + XMLCh* apiName = XMLString::transcode(NODE_ISSUELIST_HEADERFILE_ISSUE_APINAME); + XMLCh* apicategoryvalue = XMLString::transcode(aNodeCategory); + XMLCh* apicategoryname = XMLString::transcode(NODE_ISSUELIST_HEADERFILE_ISSUE_APICATEGORY); + + ret = iDOMDocument->createElement(ch); + ret->setAttribute(apiName,apivalue); + ret->setAttribute(apicategoryname,apicategoryvalue); + + + XMLString::release(&ch); + XMLString::release(&apivalue); + XMLString::release(&apiName); + XMLString::release(&apicategoryvalue); + XMLString::release(&apicategoryname); + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createCmdLineNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createCmdLineNode() +{ + DOMElement* ret = NULL; + ret = createOpenNode(NODE_HEADER_CMDLINE); + map::iterator begin = iParams.begin(); + while (begin != iParams.end()) + { + DOMElement* ParamNode = createParmNode((*begin).first.c_str(),(*begin).second.c_str()); + ret->appendChild(ParamNode); + begin++; + } + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createParmNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createParmNode(const char* aKey, const char* aValue) +{ + DOMElement* ret = NULL; + + // value ** + ret = createOpenNode(NODE_HEADER_CMDLINE_PARM); + + // + ret->appendChild(createSimpleTextNode(NODE_HEADER_CMDLINE_PARM_PNAME, aKey)); + // + ret->appendChild(createSimpleTextNode(NODE_HEADER_CMDLINE_PARM_PVALUE, aValue)); + + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createDocumentationUrlString +// ---------------------------------------------------------------------------- +// +string ReportGenerator::createDocumentationUrlString(string element) +{ + string ret; + if (getCmdLineParm(DOCURL) != "Not speciefied") + { + ret = getCmdLineParm(DOCURL) + element; + } + else + { + ret = ""; + } + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createIssueNode +// ---------------------------------------------------------------------------- +// +DOMElement* ReportGenerator::createIssueNode(ReportIssue& aIssue) +{ + // IssueNode field element to report file + DOMElement* ret = NULL; + + // create file name here + ret = createOpenNode(NODE_ISSUELIST_HEADERFILE_ISSUE); + + vector childvec; + + // issue identifier field + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_ISSUEID, aIssue.Id())); + + // issue type identifier field + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_TYPEID, aIssue.TypeId())); + + // issue identify ( entity ) identifier field + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_IDENTITYID, aIssue.IdentityId())); + + // identity description + childvec.push_back(createSimpleTextNode( NODE_ISSUELIST_HEADERFILE_ISSUE_IDENTITYDESCRIPTION, aIssue.IdentityDescription())); + + // issue description field + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_TYPESTRING, aIssue.TypeDescription())); + + // issue cause description a.k.a FQName + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_CAUSE, aIssue.FQName().c_str())); + + // issue documentation finder field + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_DOCUMENTATION, createDocumentationUrlString(aIssue.FQName()).c_str())); + + // issue ignore finder field + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_IGNOREINFORMATION, aIssue.IgnoreInformationDescription().c_str())); + + // issue linenumber field + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_LINENUMBER, aIssue.LineNumber())); + + // issue extrainformation field + //childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_EXTRAINFORMATION, aIssue.ExtraInformationDescription().c_str())); + + // binary compatibility severity sub field for issue + DOMElement* bcseverity = createOpenNode(NODE_ISSUELIST_HEADERFILE_ISSUE_SEVERITY); + bcseverity->appendChild(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_SEVERITY_TYPEID, aIssue.BCSeverity())); + bcseverity->appendChild(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_SEVERITY_TYPESTRING, aIssue.BCSeverityDescription())); + + // source compatibility severity sub field for issue + DOMElement* scseverity = createOpenNode(NODE_ISSUELIST_HEADERFILE_ISSUE_SCSEVERITY); + scseverity->appendChild(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_SEVERITY_TYPEID, aIssue.SCSeverity())); + scseverity->appendChild(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_SEVERITY_TYPESTRING, aIssue.SCSeverityDescription())); + + // if iisue type is compilation error, description of compilation error + if(aIssue.TypeId() == EIssueTypeCompilationError) + childvec.push_back(createSimpleTextNode(NODE_ISSUELIST_HEADERFILE_ISSUE_COMPILATION_ERROR, aIssue.CompilationError().c_str())); + + + appendChildrenToNode(ret, childvec); + ret->appendChild(bcseverity); + ret->appendChild(scseverity); + return ret; +} + +// ---------------------------------------------------------------------------- +// ReportGenerator::createSeverityNode +// ---------------------------------------------------------------------------- +// +//DOMElement* ReportGenerator::createSeverityNode(const int aId) +DOMElement* ReportGenerator::createSeverityNode() +{ + DOMElement* ret = NULL; + ret = createOpenNode(NODE_ISSUELIST_HEADERFILE_ISSUE_SEVERITY); + return ret; +} +