diff -r 000000000000 -r 638b9c697799 apicompatanamdw/compatanalysercmd/headeranalyser/src/Analyser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apicompatanamdw/compatanalysercmd/headeranalyser/src/Analyser.cpp Tue Jan 12 14:52:39 2010 +0530 @@ -0,0 +1,3419 @@ +/* +* 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 +#include + +#ifdef __WIN__ +#include +#include +#include +#else +#include +#endif +#include "Analyser.h" +#include "CPPParser.h" +#include "CommandLine.h" +#include "CommandFile.h" +#include "BBCFileUtils.h" +#include "HAException.h" +#include "BBCAnalyser.h" +#include "AnalyserParams.h" +#include "MacroAnalyser.h" +#include "Utils.h" +#include "PlatformData.h" + +const int KMaxDirLength=1024; + +boost::mutex m; +boost::mutex::scoped_lock lock(m,false); //for synchronizing creation & destruction of threads in gHeaderThreads + +boost::thread_group gComponentThreads; +boost::thread_group gHeaderThreads; + +boost::thread* gpComponentThreads[MAX_THREAD_COUNT]; +boost::thread* gpHeaderThreads[MAX_THREAD_COUNT2]; + +XERCES_CPP_NAMESPACE_USE +typedef pair stringpair; +//the total number of files to be processed +static int _total_files = 0; +//the number of files that have been processed +static int _current_files = 0; + +// make sure globbing is turned off when GCC is used +int _CRT_glob = 0; + +// Fill the headers having API Info in global vector, so that report generator can access it. +vector > HeaderInfoList; // vector>> + +// ---------------------------------------------------------------------------- +// Analyser::Analyser +// Constructor +// ---------------------------------------------------------------------------- +// +Analyser::Analyser(char** args, int argc) : iCPPParser(NULL) +{ + iCmdLine = new CommandLine(args, argc); + iUseBaselinePlatformData = false; + iUseCurrentPlatformData = false; + iUseForcedHeaders = true; + iBasePlatformData = 0; + iProductPlatformData = 0; +} + +// ---------------------------------------------------------------------------- +// Analyser::Analyser +// Constructor +// ---------------------------------------------------------------------------- +// +Analyser::Analyser() +{ + +} + +// ---------------------------------------------------------------------------- +// Analyser::Analyser +// Destructor +// ---------------------------------------------------------------------------- +// +Analyser::~Analyser() +{ + delete iCmdLine; + iCmdLine = NULL; + if (iCPPParser != NULL) + { + delete iCPPParser; + iCPPParser = NULL; + } + if (iBasePlatformData) + { + delete iBasePlatformData; + iBasePlatformData = 0; + } + if ( iProductPlatformData) + { + delete iProductPlatformData; + iProductPlatformData = 0; + } +} + +// ---------------------------------------------------------------------------- +// Analyser::validateHeaders +// validates header for include guards +// ---------------------------------------------------------------------------- +// +void Analyser::validateHeaders(vector >& aFiles, vector >& aUnsuccessful) +{ + int count = 0; + string input; + string files[2]; + bool exists[2]; + string guard[2]; + vector guards[2]; + + vector< pair >::iterator fileStart = aFiles.begin(); + vector< pair >::iterator fileEnd = aFiles.end(); + //vector used to temporarily hold file pairs with include guards + vector< pair > temp; + while(fileStart != fileEnd ) + { + files[0] = fileStart->first; + files[1] = fileStart->second; + for(int i=0; i<2; i++) + { + + //check for include guard in Base header + exists[i] = guardExists(files[i], guard[i]); + } + //if either Base or Current header in the PAIR do not have include guards + //add the file pair to RemovedFiles list. + if( !exists[0] || !exists[1] ) + aUnsuccessful.push_back(*fileStart); + else + { + if ( find(guards[0].begin(),guards[0].end(),guard[0]) == guards[0].end() && find(guards[1].begin(),guards[1].end(),guard[1]) == guards[1].end()) + { + guards[0].push_back(guard[0]); + guards[1].push_back(guard[1]); + temp.push_back(*fileStart); + } + else + { + aUnsuccessful.push_back(*fileStart); + } + } + + ++fileStart; + } + guards[0].clear(); + guards[1].clear(); + aFiles.clear(); + aFiles = temp; +} + +// ---------------------------------------------------------------------------- +// Analyser::guardExists +// guard Exists checs to see if the input file has include guards +// ---------------------------------------------------------------------------- +// +bool Analyser::guardExists(const string& aFile, string& aGuard) +{ + bool exists = false; + string guard(""); + string input(""); + string temp(""); + //macro used in the #ifndef line + pair macroOne; + //macro #defined subsequently + pair macroTwo; + int linenum = 0; + //linenum containing the #ifndef statement + int ifndefline = 0; + + ifstream fileRead(aFile.c_str(), ios::in); + if( !fileRead.is_open()) + throw HAException("Header file does not exist");; + while( !fileRead.eof() ) + { + linenum++; + temp = getLine(fileRead); + input = trimWhiteSpace(temp); + // Check if #ifndef are being used + // Get the MACRO string if they are present + if(input.substr(0,7) == "#ifndef") + { + macroOne = MacroAnalyser::FindMacro(input); + ifndefline = linenum; + } + // checks for the usage of #if (!defined ...) in include guard defns + else if (input.substr(0,3) == "#if") + { + string tempstr("!defined"); + //strip all braces from the Macro string + while(input.find("(") < input.length()) + { + replaceChar(input,'(',' '); + replaceChar(input,')',' '); + } + //get the actual MACRO string after required temp modifications + string::size_type index = input.find(tempstr); + if (index == string::npos) + continue; + index = index + tempstr.length(); + tempstr = input.substr( index ); + input = trimWhiteSpace(tempstr); + pair temppair(input, ""); + macroOne = temppair; + ifndefline = linenum; + } + // Check if #define is used + else if (input.substr(0, 7) == "#define") + { + macroTwo = MacroAnalyser::FindMacro(input); + //if macro strings used in both #ifndef and #define are same + //consider that include guard exists + //also verify that #define follows #if + if( macroTwo.first == macroOne.first && macroTwo.second == macroOne.second && ifndefline < linenum ) + { + exists = true; + aGuard = macroOne.first; + } + break; + } + // additional statement will be used for early termination of the loop + // in cases with no "include" guards + else if( input.substr(0, 8) == "#include") + { + exists = false; + break; + } + } + fileRead.close(); + return exists; +} + +// ---------------------------------------------------------------------------- +// Analyser::readParameters +// readParameters should be called so that first is called baseline command +// and after that current command, otherwise it doesn't work +// ---------------------------------------------------------------------------- +// +void Analyser::readParameters(basetype type, list >& files, string& forcedheaders) +{ + string headerset; + string dir; + string file; + string platform; + string forcedheadersfile; + string forcedheaders_file; + string version; + string versionstr; + BBCFileUtils* fileUtils = NULL; + static basetype first = type; + + if (first != EBase) + { + cout << "Error: Parameter read has been called in wrong order."; + exit(3); + } + + switch(type) + { + case EBase: + dir = BASELINEDIR; + file = BASELINE; + platform = BASELINEPLAT; + forcedheadersfile = BASEFORCEDHEADERSFILE; + version = BASELINEVERSION; + versionstr = "BASELINE"; + break; + case ECurrent: + dir = CURRENTDIR; + file = CURRENT; + platform = CURRENTPLAT; + forcedheadersfile = CURRENTFORCEDHEADERSFILE; + version = CURRENTVERSION; + versionstr = "CURRENT"; + break; + default: + cout << "Error: Unknown type (not baseline, nor current)."; + exit(3); + } + + // Query the baseline-related command line parameters + // since validation has passed, none of these should really + // cause an exception + try + { + if( iParams.parameterExists(BASEPLATFORMDATA)) + { + iUseBaselinePlatformData = true; + string pfdir(BBCFileUtils::getFullPath(iParams.getParameter(BASEPLATFORMDATA))); + if (!BBCFileUtils::isValidFilename(pfdir)) + { + throw HAException("Baseline platform data file '" + pfdir + "' is not valid."); + } + iParams.storeParameter(BASEPLATFORMDATA, pfdir); + } + if( iParams.parameterExists(CURRENTPLATFORMDATA)) + { + iUseCurrentPlatformData = true; + string pfdir(BBCFileUtils::getFullPath(iParams.getParameter(CURRENTPLATFORMDATA))); + if (!BBCFileUtils::isValidFilename(pfdir)) + { + throw HAException("Current platform data file '" + pfdir + "' is not valid."); + } + iParams.storeParameter(CURRENTPLATFORMDATA, pfdir); + } + if (iParams.parameterExists(TEMPDIR)) + { + string tempdir(BBCFileUtils::getFullPath(iParams.getParameter(TEMPDIR))); + iParams.storeParameter(TEMPDIR, tempdir); + if (!BBCFileUtils::isValidDirectory(tempdir)) + { + throw HAException("Temporary directory '" + tempdir + "' is not valid directory."); + } + } + if (iParams.parameterExists(REPORTFILE)) + { + string reportfile(BBCFileUtils::getFullPath(iParams.getParameter(REPORTFILE))); + iParams.storeParameter(REPORTFILE, reportfile); + if (rightmostDirSeparatorIndex(reportfile) == reportfile.length() - 1 || BBCFileUtils::isValidDirectory(reportfile)) + { + throw HAException("No filename given for report file."); + } + string reportdir = reportfile.substr(0, rightmostDirSeparatorIndex(reportfile)); + + if (reportdir.size() == ANALYSER_REPORT_DIR_SIZE) + { + reportdir += DIR_SEPARATOR; + } + if (!BBCFileUtils::isValidDirectory(reportdir)) + { + throw HAException("Directory for report file is non-existent."); + } + } + if (iParams.parameterExists(HEADERSET)) + { + iHeaderSetInUse = true; + } + if (iParams.parameterExists(USETHREAD)) + { + iUseThread = true; + } + if (iParams.parameterExists(dir)) + { + // START -- Support for multiple header directories + // Validate the ; separated header paths and store them + list > dirs = BBCFileUtils::extractFilenames(iParams.getParameter(dir)); + list >::iterator dirbegin = dirs.begin(); + string tempval = ""; + + for(; dirbegin != dirs.end(); dirbegin++) + { + if (dirbegin != dirs.begin()) + { + tempval += ";"; + } + string header = BBCFileUtils::getFullPath(dirbegin->first); + + if (header.length() != ANALYSER_HEADER_MAX_LENGTH && header.at(header.length() - 1) == DIR_SEPARATOR) + { + header.resize(header.length() - 1); + } + + if (!BBCFileUtils::isValidDirectory(header)) + { + string::size_type pos = rightmostDirSeparatorIndex(header); + string tempvar; + if (pos != header.length() - 1) + { + tempvar = header.substr(pos + 1); + header.resize(pos); + } + + if (header.size() == ANALYSER_HEADER_SIZE) + { + header += DIR_SEPARATOR; + } + + if (!BBCFileUtils::isValidDirectory(header) || tempvar.find_first_of("*?") == string::npos) + { + string errormsg; + errormsg = "Non-existent "; + if (type == EBase) + { + errormsg += "base"; + } else + { + errormsg += "current"; + } + errormsg += " directory '" + header + DIR_SEPARATOR + tempvar + "'.\n"; + throw HAException(errormsg); + } + } + if (header.at(header.length() - 1) == DIR_SEPARATOR) + { + header.resize(header.length() - 1); + } + tempval += header; + } + iParams.storeParameter(dir, tempval); + // END -- Support for multiple header directories + } + else + { + iParams.storeParameter(file, BBCFileUtils::getFullPath(iParams.getParameter(file))); + } + + // Location of baseline's platform headers + list > platformheaders = BBCFileUtils::extractFilenames(iParams.getParameter(platform)); + list >::iterator platformbegin = platformheaders.begin(); + string tempval = ""; + for(; platformbegin != platformheaders.end(); platformbegin++) + { + if (platformbegin != platformheaders.begin()) + { + tempval += ";"; + } + string header = BBCFileUtils::getFullPath(platformbegin->first); + + if (header.length() != ANALYSER_HEADER_MAX_LENGTH && header.at(header.length() - 1) == DIR_SEPARATOR) + { + header.resize(header.length() - 1); + } + + tempval += header; + } + iParams.storeParameter(platform, tempval); + + // Location of forced headers file (containing full names of headers that + // will be included to preprocessing and processing phases, e.g. e32base.h) + if (iParams.parameterExists(forcedheadersfile)) + { + // START -- Support for multiple forced headers + list > fheaders = BBCFileUtils::extractFilenames(iParams.getParameter(forcedheadersfile)); + list >::iterator fheadersbegin = fheaders.begin(); + string tempval = ""; + + //for each forced header, get the full path before storing it + for(; fheadersbegin != fheaders.end(); fheadersbegin++) + { + if (fheadersbegin != fheaders.begin()) + { + tempval += ";"; + } + tempval += BBCFileUtils::getFullPath(fheadersbegin->first); + } + iParams.storeParameter(forcedheadersfile, tempval); + forcedheaders = iParams.getParameter(forcedheadersfile); + // END -- Support for multiple forced headers + } + + if (!iParams.parameterExists(version)) + { + iParams.storeParameter(version, versionstr); + } + } catch (HAException& e) + { + cout << "Error: "<setTemp(iParams.getParameter(TEMPDIR)); + string wildcard; + list sets; + list discarddirs; + list foundfiles; + list completefilenames; // Filenames that are complete, i.e no wildcards used. + vector wildcardsinset; + + if (type == EBase) + { + // We are reading the parameters of the baseline platform + + if(iHeaderSetInUse) + { + // the files to be analysed are defined using 'set' parameter. + sets = fileUtils->extractFilenames(iParams.getParameter(HEADERSET)); + } + else + { + // 'set' parameter is absent. Use default file types in the files to be analysed. + sets = fileUtils->extractFilenames(WILDCARD_DEFAULT); + } + + sets = canonicalizeFilename(sets); + + for(list::iterator s = sets.begin(); s != sets.end(); ++s ) + { + if( s->first.find_first_of("*?") != string::npos ) + { + // Wildcard is used in filename. + std::string wc(s->first); + wildcardsinset.push_back(wc); + list tmpfiles(fileUtils->getFilesInDir(wc, "")); + files.insert(files.end(), tmpfiles.begin(), tmpfiles.end()); + } + else + { + completefilenames.push_back(*s); + } + } + + files.sort(LessStringPair);// Sort files + files.unique(); // Remove duplicates + + // Remove trailing directory separator from the filenames, that were found using the wildcard, + // to be able to build foundfiles list for later use. + list foundwithwildcard(files); + std::for_each(foundwithwildcard.begin(), foundwithwildcard.end(),RemoveTrailingDirSeparator()); + + // Find files given with complete filename + list tempcompletefiles(completefilenames); + list tmplist(fileUtils->getFilesInDir(tempcompletefiles, "",foundfiles)); + + // Add files found with wildcard to foundfiles + foundfiles.sort(LessStringPair); + foundfiles.merge(foundwithwildcard, LessStringPair); + foundfiles.unique(); // Remove duplicates + + // Merge all found files: + tmplist.sort( LessStringPair ); + files.merge(tmplist, LessStringPair); + files.unique(); // Remove duplicates + if (iParams.parameterExists(DISCARDDIRS)) + { + discarddirs = BBCFileUtils::extractFilenames(iParams.getParameter(DISCARDDIRS)); + } + } else if (type == ECurrent) + { + // We are reading the parameters of the current platform + // and the files to be analysed are defined using 'set' parameter. + wildcard = WILDCARD_ALLFILES; + files = fileUtils->getFilesInDir(wildcard, ""); + if (iParams.parameterExists(DISCARDDIRS)) + { + discarddirs = BBCFileUtils::extractFilenames(iParams.getParameter(DISCARDDIRS)); + } + } else + { + // No 'set' parameter used + wildcard = iParams.getParameter(BASELINE); + files = fileUtils->getFilesInDir(wildcard, ""); + if (iParams.parameterExists(DISCARDDIRS)) + { + discarddirs = BBCFileUtils::extractFilenames(iParams.getParameter(DISCARDDIRS)); + } + } + if (iParams.parameterExists(RECURSIVE)) + { + list > dirs = fileUtils->getDirsInDir("",discarddirs); + while(!dirs.empty()) + { + string dir = dirs.front().first; + dirs.pop_front(); + list > morefiles; + if (type == EBase) + { + // Read files which were given as complete names in the -set parameter: + morefiles = fileUtils->getFilesInDir(completefilenames, dir,foundfiles); + + // Read files which were given as wildcards in the -set parameter: + for( vector::iterator wc = wildcardsinset.begin(); wc != wildcardsinset.end(); ++wc) + { + list > tmpfiles = fileUtils->getFilesInDir(*wc, dir); + morefiles.insert(morefiles.end(), tmpfiles.begin(), tmpfiles.end()); + } + } + else + { + morefiles = fileUtils->getFilesInDir(wildcard, dir); + } + morefiles.sort(LessStringPair); + morefiles.unique(); + list >::const_iterator file = morefiles.begin(); + list >::const_iterator fileend = morefiles.end(); + for(; file != fileend; file++) + { + files.push_back(*file); + } + list > moredirs = fileUtils->getDirsInDir(dir,discarddirs); + while(!moredirs.empty()) + { + pair direntry = moredirs.front(); + moredirs.pop_front(); + dirs.push_back(direntry); + } + } + } + if (type == EBase) + { + list > notfound; + diffs(files, sets, notfound); + if (!notfound.empty()) + { + string errormessage = "Following files could not be found in baseline:\n"; + list >::iterator file = notfound.begin(); + list >::iterator fileend = notfound.end(); + for(; file != fileend; file++) + { + errormessage += file->first; + errormessage += "\n"; + } + //this case has now been redefined as a input error that can be handled + //the file is removed from the list to be analysed, and execution continues + //throw HAException(errormessage); + } + } + } + else + { + // baseline/current commandline parameters given + string file_val = iParams.getParameter(file); + string f = getFilenameWithoutDir(file_val); + iParams.storeParameter(file, f); + file_val.resize(file_val.length() - f.length() - 1); + iParams.storeParameter(dir, file_val); + fileUtils = new BBCFileUtils(iParams.getParameter(dir)); + fileUtils->setTemp(iParams.getParameter(TEMPDIR)); + pair tempvar(f, toLowerCaseWin(f)); + files.push_back(tempvar); + } + } catch (HAException& e) + { + // something went wrong. Make a clean exit + if (fileUtils != NULL) + { + delete fileUtils; + fileUtils = NULL; + } + cout << "Error: " << e.errorMessage() << "\n"; + exit(2); + } + + delete fileUtils; + fileUtils = NULL; + +} + +// ---------------------------------------------------------------------------- +// Analyser::processParameters +// processParameters +// ---------------------------------------------------------------------------- +// +int Analyser::processParameters() +{ + string err = ""; + + // Validate command-line parameters. + // If they are not sound and complete, break off with an error message. + try + { + err = iCmdLine->validateParameters(); + } catch (HAException& e) + { + cout << "ERROR: Bad parameters, quitting. Type ha -? for help.\n"; + cout << e.errorMessage(); + cout << "\n"; + return (2); + } + + if (err.size() > 0) + { + cout << "ERROR: Parameter validation fail. Type ha -? for help.\n"; + cout << err << "\n"; + return (2); + } + + map params = iCmdLine->getParameters(); + map::iterator begin = params.begin(); + map::iterator end = params.end(); + while (begin != end) + { + iParams.storeParameter((*begin).first,(*begin).second, true); + ++begin; + } + + // readParameters should be called so that first is called baseline command + // and after that current command, otherwise it doesn't work + + // Read base dependent parameters + readParameters(EBase, iFiles, iForcedBaselineHeaders); + // ..and current ones + readParameters(ECurrent, iFiles2, iForcedCurrentHeaders); + +#if defined(_DEBUG) || defined(DEBUG) + if(iParams.parameterExists(COMMANDLINETEST)) + { + map params = iParams.getGivenParameters(); + map::iterator begin = params.begin(); + map::iterator end = params.end(); + while (begin != end) + { + cout << "Param: '" << (*begin).first << "' Value: '" << (*begin).second << "'\n"; + begin++; + } + exit(100); + } +#endif + + return 0; +} + +// ---------------------------------------------------------------------------- +// Analyser::analyseTrees +// processParameters +// ---------------------------------------------------------------------------- +// +int Analyser::analyseTrees(DOMNode* baseline, DOMNode* current, const list< pair >& files, ReportGenerator& report) +{ + int ret = 0; + //print progress information for files which have compiled + list< pair >::const_iterator begin = files.begin(); + list< pair >::const_iterator end = files.end(); + + while (begin != end) + { + _current_files++; + cout << "\nAnalysing files (" << _current_files << "/" << _total_files << "): " << (*begin).first <<" => "<< (*begin).second << endl; + begin++; + } + + BBCAnalyser analyser(report); + ret = analyser.analyseTrees(baseline, current, files, iMacroFiles); + + return ret; +} + +// ---------------------------------------------------------------------------- +// Analyser::handleBundlesizeParam +// Get bundlesize value +// ---------------------------------------------------------------------------- +// +int Analyser::handleBundlesizeParam() +{ + int bundlesize=1; + + if (iParams.parameterExists(BUNDLESIZE)) + { + string tempstr = iParams.getParameter(BUNDLESIZE); + if (tempstr.length() > 0) + { + bundlesize = atoi(tempstr.c_str()); + if (bundlesize < 1) + { + bundlesize = 1; + } + else if (bundlesize > MAX_BUNDLESIZE) + { + bundlesize = MAX_BUNDLESIZE; + } + } + } + + if (bundlesize >= BUNDLESIZE_WARNING) + { + cout << "Note: Processing in large bundles, this may have a negative " + << "performance impact and/or produce unwanted artifacts.\n"; + } + return bundlesize; +} + +// ---------------------------------------------------------------------------- +// Analyser::getReplaceParam +// Get Replace parameter value +// ---------------------------------------------------------------------------- +// +string Analyser::getReplaceParam() +{ + string replace; + // File renames + if (iParams.parameterExists(FILEREPLACE)) + { + replace = iParams.getParameter(FILEREPLACE); + } else + { + replace = ""; + } + + return replace; +} + + + +PlatformHeaders::iterator FindHeaderPair(const string& ID, PlatformHeaders& pfHeaders) +{ + for( PlatformHeaders::iterator i = pfHeaders.begin(); i != pfHeaders.end(); ++i ) + { + if( i->first->ID() == ID ) + { + return i; + } + } + return pfHeaders.end(); +} +// ---------------------------------------------------------------------------- +// Analyzes one component at a time. +// +// +// ---------------------------------------------------------------------------- +// +void Analyser::AnalyzePlatforms(PlatformHeaders& pfHeaders, PlatformHeaders& unsuccessfulHdrs, ReportGenerator& report, int& issues, bool createThread) +{ + string epocRoot("epoc32"); + epocRoot += DIR_SEPARATOR + string("include"); + // START -- Support for multiple header directories + list > baseEpocRoot = BBCFileUtils::MergeDirs(iParams.getParameter(BASELINEDIR), epocRoot); + list > currEpocRoot = BBCFileUtils::MergeDirs(iParams.getParameter(CURRENTDIR), epocRoot); + // END -- Support for multiple header directories + for( PlatformHeaders::iterator pfHdr = pfHeaders.begin(); pfHdr != pfHeaders.end(); ++pfHdr ) + { + if( pfHdr->first->Status() == Header::HDR_STATUS_TO_BE_ANALYZED /*|| pfHdr->first->Status() == Header::HDR_STATUS_INVALID*/) + { + stringvector baseIncPaths; // This contains include paths needed to compile baseline headers + stringvector currIncPaths; // This contains include paths needed to compile product headers + + baseIncPaths.clear(); + currIncPaths.clear(); + + iBaseFilenames.clear(); + iCurrFilenames.clear(); + iBaseIncludes.clear(); + iCurrIncludes.clear(); + iInvalidFiles.clear(); + + // All headers in the (baseline platform) component: + FileList& baseCmpHeaders = pfHdr->first->GetComponent()->Headers(); + iBaseFilenames.reserve(baseCmpHeaders.size()); + iCurrFilenames.reserve(baseCmpHeaders.size()); + + // Make sure that the epoc32/include directory is always in include paths: + // START -- Support for multiple header directories + list >::iterator iter1 = baseEpocRoot.begin(); + for(; iter1 != baseEpocRoot.end(); iter1++) + { + if( iter1->second ) + { + baseIncPaths.push_back(iter1->first); + } + } + list >::iterator iter2 = currEpocRoot.begin(); + for(; iter2 != currEpocRoot.end(); iter2++) + { + if( iter2->second ) + { + currIncPaths.push_back(iter2->first); + } + } + // END -- Support for multiple header directories + + string forcedHeader; + char* base = new char[KMaxDirLength+1]; + getcwd(base, KMaxDirLength); + + vector< stringpair > tmpfiles; + vector< stringpair > invalid; + // Loop all the headers that are in the same component: + for( FileList::iterator bH = baseCmpHeaders.begin(); bH != baseCmpHeaders.end(); ++bH ) + { + Header* baseHdr = dynamic_cast(*bH); + + PlatformHeaders::iterator pairIter = FindHeaderPair(baseHdr->ID(), pfHeaders); + if(pairIter != pfHeaders.end() && pairIter->second != 0) + { + // If analysing in bundle, get the headers to be anaysed to validate for include guard before addition to bundle. + if( (pfHeaders.size() > 1) && baseHdr && (baseHdr->Status() == Header::HDR_STATUS_TO_BE_ANALYZED) ) + { + stringpair tmp(baseHdr->ID(), pairIter->second->ID()); + tmpfiles.push_back(tmp); + } + } + } + + if(tmpfiles.size()) + { + // If analysing in bundle, validate for include guard before addition to bundle. + validateHeaders(tmpfiles, invalid); + // Exclude "iInvalidFiles" from bundle analysis. Analyse them only singly. + if( invalid.size() ) + { + for( int i=0 ; i < invalid.size() ; i++ ) + { + + PlatformHeaders::iterator pairIter = FindHeaderPair(invalid[i].first, pfHeaders); + //No need to check if the invalid file exists in pfHeaders, as it already done above. + HeaderPair temp(pairIter->first, pairIter->second); + if(find(iInvalidFiles.begin(), iInvalidFiles.end(), temp) == iInvalidFiles.end()) + iInvalidFiles.push_back(temp); + pairIter->first->SetStatus(Header::HDR_STATUS_INVALID); + } + } + } + + for( FileList::iterator bH = baseCmpHeaders.begin(); bH != baseCmpHeaders.end(); ++bH ) + { + Header* baseHdr = dynamic_cast(*bH); + + PlatformHeaders::iterator pairIter = FindHeaderPair(baseHdr->ID(), pfHeaders); + if(pairIter != pfHeaders.end() && pairIter->second != 0) + { + + // If the status is "to be analyzed" , get this header to the bundle too + if( baseHdr && + (baseHdr->Status() == Header::HDR_STATUS_TO_BE_ANALYZED )) + { + // Find all additional includes that are needed in compilation of this header: + const vector& bIncs = iBasePlatformData->IncludesForHeader(baseHdr); + forcedHeader.clear(); + forcedHeader = baseHdr->CachedForcedInclude(); + // Find all include paths that are needed in compilation of this header: + const vector& bPaths = iBasePlatformData->IncludePathsForHeader(baseHdr); + + // Add include paths for baseline platform headers: + // START -- Support for multiple header directories + for( vector::const_iterator i = bPaths.begin(); i != bPaths.end(); ++i ) + { + list > fullIncPath = BBCFileUtils::MergeDirs(iParams.getParameter(BASELINEDIR), *i); + list >::iterator fulliterbegin = fullIncPath.begin(); + for(; fulliterbegin != fullIncPath.end(); fulliterbegin++) + { + if( find(baseIncPaths.begin(), baseIncPaths.end(), fulliterbegin->first) == baseIncPaths.end() ) + { + baseIncPaths.push_back(fulliterbegin->first); + } + } + } + + // Add additional include directives to header list: + for( vector::const_iterator i = bIncs.begin(); i != bIncs.end(); ++i ) + { + // Make sure the header exists, because we don't want to generate new compilation errors... + bool exists = false; + // Test that header exists by merging the header name with include paths: + for( stringvector::iterator ip = baseIncPaths.begin(); ip != baseIncPaths.end(); ++ip ) + { + list > fullIncPath = BBCFileUtils::MergeDirs( *ip, *i ); + list >::iterator fulliterbegin = fullIncPath.begin(); + for(; fulliterbegin != fullIncPath.end(); fulliterbegin++) + { + if( find(iBaseIncludes.begin(), iBaseIncludes.end(), fulliterbegin->first) == iBaseIncludes.end() ) + { + if( BBCFileUtils::FileExists(fulliterbegin->first) ) + { + iBaseIncludes.push_back(fulliterbegin->first); + exists = true; + break; + } + } + } + } + if( exists == false ) + { + // Try to find the included header from the same directory than the header itself is: + list > fullIncPath = + BBCFileUtils::MergeDirs(iParams.getParameter(BASELINEDIR), baseHdr->Path() + DIR_SEPARATOR + *i); + + list >::iterator fulliterbegin = fullIncPath.begin(); + for(; fulliterbegin != fullIncPath.end(); fulliterbegin++) + { + if( BBCFileUtils::FileExists(fulliterbegin->first) ) + { + iBaseIncludes.push_back(fulliterbegin->first); + } + } + } + } + // END -- Support for multiple header directories + + // Add this header to the list of headers that are needed for compilation: + if( find(iBaseIncludes.begin(), iBaseIncludes.end(), baseHdr->ID()) == iBaseIncludes.end()) + { + iBaseIncludes.push_back(baseHdr->ID()); + } + + // Add headers to the list of headers that are to be analyzed: + iBaseFilenames.push_back(baseHdr->ID()); + iCurrFilenames.push_back(pairIter->second->ID()); + baseHdr->SetStatus(Header::HDR_STATUS_READY); + + forcedHeader = DIR_SEPARATOR + forcedHeader; + forcedHeader = base + forcedHeader; + if( BBCFileUtils::isValidFilename(forcedHeader) ) + if( find(iBaseIncludes.begin(), iBaseIncludes.end(), forcedHeader) == iBaseIncludes.end()) + iBaseIncludes.insert(iBaseIncludes.begin(),forcedHeader); + + + // Then we need to find corresponding headers from the product (current) platform: + + Header* currHeader = pairIter->second; //Current header + + // Find additional includes and include paths for the current platform's header: + const vector& cIncs = iProductPlatformData->IncludesForHeader(currHeader, baseHdr); + forcedHeader.clear(); + forcedHeader =currHeader->CachedForcedInclude(); + const vector& cPaths =iProductPlatformData->IncludePathsForHeader(currHeader); + + // Add include paths to the list, if it does not exist there yet: + for( vector::const_iterator i = cPaths.begin(); i != cPaths.end(); ++i ) + { + // SART -- Support for multiple header directories + list > fullIncPath = BBCFileUtils::MergeDirs(iParams.getParameter(CURRENTDIR), *i); + list >::iterator fulliterbegin = fullIncPath.begin(); + for(; fulliterbegin != fullIncPath.end(); fulliterbegin++) + { + if( find(currIncPaths.begin(), currIncPaths.end(), fulliterbegin->first) == currIncPaths.end() ) + { + currIncPaths.push_back(fulliterbegin->first); + } + } + // END -- Support for multiple header directories + } + + // Add additional include directives to header list: + for( vector::const_iterator i = cIncs.begin(); i != cIncs.end(); ++i ) + { + bool exists = false; + // Make sure the header exists, because we don't want to generate new compilation errors... + for( stringvector::iterator ip = currIncPaths.begin(); ip != currIncPaths.end(); ++ip ) + { + // START -- Support for multiple header directories + list > fullIncPath = BBCFileUtils::MergeDirs( *ip, *i ); + list >::iterator fulliterbegin = fullIncPath.begin(); + for(; fulliterbegin != fullIncPath.end(); fulliterbegin++) + { + if( find(iCurrIncludes.begin(), iCurrIncludes.end(), fulliterbegin->first) == iCurrIncludes.end() ) + { + if( BBCFileUtils::FileExists(fulliterbegin->first) ) + { + iCurrIncludes.push_back(fulliterbegin->first); + exists = true; + break; + } + } + } + // END -- Support for multiple header directories + } + if( exists == false ) + { + // Try to find the included header from the same directory than the header itself is: + // START -- Support for multiple header directories + list > fullIncPath = + BBCFileUtils::MergeDirs(iParams.getParameter(CURRENTDIR), currHeader->Path() + DIR_SEPARATOR + *i); + list >::iterator fulliterbegin = fullIncPath.begin(); + for(; fulliterbegin != fullIncPath.end(); fulliterbegin++) + { + if( BBCFileUtils::FileExists(fulliterbegin->first) ) + { + iCurrIncludes.push_back(fulliterbegin->first); + } + } + // END -- Support for multiple header directories + } + } + // Add this header to the list: + if( find(iCurrIncludes.begin(), iCurrIncludes.end(), currHeader->ID()) == iCurrIncludes.end()) + { + iCurrIncludes.push_back(currHeader->ID()); + } + + forcedHeader = DIR_SEPARATOR + forcedHeader; + forcedHeader = base + forcedHeader; + if( BBCFileUtils::isValidFilename(forcedHeader) ) + if( find(iCurrIncludes.begin(), iCurrIncludes.end(), forcedHeader) == iCurrIncludes.end()) + iCurrIncludes.insert(iCurrIncludes.begin(),forcedHeader); + + } + } + } + // Build include paths for parser objects: + string bIP; + for( stringvector::iterator i = baseIncPaths.begin(); i != baseIncPaths.end(); ++i ) + { + if( i != baseIncPaths.begin() ) + bIP += ";"; + + bIP += *i; + } + + string cIP; + for( stringvector::iterator i = currIncPaths.begin(); i != currIncPaths.end(); ++i ) + { + if( i != currIncPaths.begin() ) + cIP += ";"; + + cIP += *i; + } + + // Construct parsers: + auto_ptr parser(new CPPParser(bIP)); + auto_ptr parser2(new CPPParser(cIP)); + + // Set temp directories for parsers + parser->setTemp(iParams.getParameter(TEMPDIR)); + parser2->setTemp(iParams.getParameter(TEMPDIR)); + + // Set forced headers + if(iUseForcedHeaders) + { + parser->setForcedHeaders(iForcedBaselineHeaders); + parser2->setForcedHeaders(iForcedCurrentHeaders); + } + + if (createThread) + { + //if the number of threads in this group has reached pre-defined max count, destroy all the threads in this group before creating one. + //boost::thread_group object does not destroy a thread when it goes to completion. if the threads are not destroyed lot of memory will be eaten up unneccessarily + if(gHeaderThreads.size() >= MAX_THREAD_COUNT) + { + + gHeaderThreads.join_all(); + int size = gHeaderThreads.size(); + for(int i=0;i~thread(); + } + } + + //create a copy of the Analyser object for the new thread + Analyser* obj = new Analyser(); + *obj = *this; + int size = gHeaderThreads.size(); + gpComponentThreads[size]=gHeaderThreads.create_thread(boost::bind(&Analyser::Wrapper,obj, boost::ref(report), boost::ref(issues), *(parser.get()), *(parser2.get()), boost::ref(pfHeaders), boost::ref(unsuccessfulHdrs))); + } + else //do not create different thread for the second time when AnalyzePlatforms is called recurssively + { + Wrapper(report, issues, *(parser.get()), *(parser2.get()), pfHeaders, unsuccessfulHdrs); + } + } + } + +} + +// ---------------------------------------------------------------------------- +// Analyser::InitializePlatforms +// +// +// ---------------------------------------------------------------------------- +// +void Analyser::InitializePlatforms(PlatformHeaders& pfHeaders, vector >& headers, + vector >& excludeheaders, vector >& resourcevector) +{ + if( iBasePlatformData ) + delete iBasePlatformData; + if( iProductPlatformData ) + delete iProductPlatformData; + + iBasePlatformData = new PlatformData(iParams.getParameter(BASELINEVERSION), + iParams.getParameter(BASELINEDIR)); + iProductPlatformData = new PlatformData(iParams.getParameter(CURRENTVERSION), + iParams.getParameter(CURRENTDIR)); + + if( iUseBaselinePlatformData ) + iBasePlatformData->Initialize(iParams.getParameter(BASEPLATFORMDATA)); + if( iUseCurrentPlatformData ) + iProductPlatformData->Initialize(iParams.getParameter(CURRENTPLATFORMDATA)); + + vector > updatedHdrs; + updatedHdrs.reserve(headers.size()); + + // Mark the platform header objects with status 'HDR_STATUS_TO_BE_ANALYZED': + vector >::const_iterator hdr = headers.begin(); + + for( ;hdr != headers.end(); ++hdr ) + { + pair headerInfo; + bool is_Resource = false; + int loc = -1; + pair resource; + Header* baseHdrObj = 0; + Header* currHdrObj = 0; + string hdrTest(hdr->first); + toLower(hdrTest); + + // Check whether the header is a resource file. If, so add it to resource vector instead of pfheaders. + if( (loc = int(hdrTest.find_last_of("."))) != string::npos && + hdrTest.substr(loc,string::npos) == RH_EXTENSION ) + { + is_Resource = true; + resource.first = hdrTest; + } + CFileMap::const_iterator bI = iBasePlatformData->HeadersById().find(hdrTest); + if( bI != iBasePlatformData->HeadersById().end() ) + { + baseHdrObj = dynamic_cast((*bI).second); + } + + hdrTest = hdr->second; + toLower(hdrTest); + if(is_Resource == true) + { + resource.second = hdrTest; + resourcevector.push_back(resource); + } + + CFileMap::const_iterator cI = iProductPlatformData->HeadersById().find(hdrTest); + if( cI != iProductPlatformData->HeadersById().end() ) + { + currHdrObj = dynamic_cast((*cI).second); + } + + if(baseHdrObj && baseHdrObj->Status()== Header::HDR_STATUS_IGNORE ) + { + excludeheaders.push_back(*hdr); + } + else if( baseHdrObj && currHdrObj ) + { + if( is_Resource == false) + { + pfHeaders.push_back(HeaderPair(baseHdrObj, currHdrObj)); + baseHdrObj->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED); + currHdrObj->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED); + } + + // get API info from current header + if(currHdrObj->APIinfo().first.size() > 0) + { + headerInfo.first = currHdrObj->ID(); + headerInfo.second.first = currHdrObj->APIinfo().first; // API NAME + headerInfo.second.second = currHdrObj->APIinfo().second; // API REL. CATEGORY + } + + } + else + { + // get API info from base header + if(baseHdrObj && baseHdrObj->APIinfo().first.size() > 0) + { + headerInfo.first = baseHdrObj->ID(); + headerInfo.second.first = baseHdrObj->APIinfo().first; // API NAME + headerInfo.second.second = baseHdrObj->APIinfo().second; // API REL. CATEGORY + + } + // get API info from current header + else if(currHdrObj && currHdrObj->APIinfo().first.size() > 0) + { + headerInfo.first = currHdrObj->ID(); + headerInfo.second.first = currHdrObj->APIinfo().first; // API NAME + headerInfo.second.second = currHdrObj->APIinfo().second; // API REL. CATEGORY + } + // No info found from platform data, so use common include paths and + // other common compile-time parameters for this header: + if( is_Resource == false) + updatedHdrs.push_back(*hdr); + } + // Fill the headers having API Info in global vector, so that report generator can access it. + if(headerInfo.first.size() > 0) + { + HeaderInfoList.push_back(headerInfo); + } + } + headers = updatedHdrs; +} + +// ---------------------------------------------------------------------------- +// Analyser::analyse +// Do the actual analyse of headers +// Create analysis report +// ---------------------------------------------------------------------------- +// +int Analyser::analyse() +{ + // Local variable instantiation + int ret = 0; + iHeaderSetInUse = false; + iUseForcedHeaders = true; + iUseThread = false; + string epocroot; + int bundlesize = 1; + unsigned int amount, amount2; + iOnlySystemIncludeRequired = false; + unsigned int excludedHeaderSize; + + if (processParameters() == 2) return 2; + + // Get the bundle size (as string) and convert it to an integer + bundlesize = handleBundlesizeParam(); + + // Get replace parameter for file renaming + string replace = getReplaceParam(); + + // Update the amount of found files + amount = (unsigned int)iFiles.size(); + // Update the amount of found files + amount2 = (unsigned int)iFiles2.size(); + + // Vector that holds the merge results and if it can't find baseline + // file from current file it will put empty string as current file + vector > mergeVector; + mergeVector.reserve(amount); + + // List holds files which were found in current but not in baseline. + // Full path + list addedFiles; + + // List holds files which were in baseline file list but + // weren't in current file list, ie they were removed. + // Contains full path with filename + list removedFiles; + try + { + // Merges baseline and current files into one vector + MergeFiles(iFiles, iFiles2, replace, mergeVector); + + // Finds removed files + fileDiffs(mergeVector, removedFiles); + } + catch (HAException e) + { + cout << "Error in processing file lists:\n" << e.errorMessage() << "\n"; + exit(4); + } + + // Mergemap now contains pairs of following type: + // baseline complex filename (w/ absolute path) -> current version complex filename (w/ absolute path) + _total_files = (unsigned int)mergeVector.size(); + + cout << "\nTotal baseline files: " << amount << "\nTotal current files: " << amount2 << "\nFile pairs found: " + << _total_files << "\n"; + + cout << "\nComparing " << _total_files << " matching files between\n " << iParams.getParameter(BASELINEDIR) + << " (Version " << iParams.getParameter(BASELINEVERSION) << ")\nand\n " << iParams.getParameter(CURRENTDIR) + << " (Version " << iParams.getParameter(CURRENTVERSION) << ")\n\n\n\n"; + + + ReportGenerator report(iParams.getParameter(REPORTFILE)); + report.setCmdLineParms(iParams.getGivenParameters()); + report.setVersions(iParams.getParameter(BASELINEVERSION),iParams.getParameter(CURRENTVERSION)); + report.setXSL("BBCResults.xsl",false); + + + report.startReport(); + // start the timer + time_t starttime; + time_t endtime; + starttime = time(NULL); + + PlatformHeaders pfHeaders; + pfHeaders.reserve(mergeVector.size()); + + // Vector that holds the the headers those should be excluded from analysis. + // These header files are mentioned in platform headers + vector > excludeHeaders; + excludeHeaders.reserve(mergeVector.size()); + + + // Headers that are found from platform data are inserted in pfHeaders. + // Others are left to mergeVector. + vector > resourceVector; + resourceVector.reserve(mergeVector.size()); + + if(mergeVector.size() > 0 ) + InitializePlatforms(pfHeaders, mergeVector,excludeHeaders,resourceVector); + excludedHeaderSize = int(excludeHeaders.size()); + + endtime = time(NULL); + time_t pfInitTime = endtime - starttime; + time_t originalStartTime = starttime; + starttime = time(NULL); + + //Now analyse Resource Header RH files using text parser + if(resourceVector.size()>0) + ParseAndCompareResourceFiles(resourceVector, report); + + // Process each removed filename from removedMap + list::iterator removedbegin = removedFiles.begin(); + list::iterator removedend = removedFiles.end(); + for(; removedbegin != removedend; removedbegin++) + { + string filename = *removedbegin; + report.addIssue(filename, "", EIssueIdentityFile, EIssueTypeRemoval, ESeverityBBCBreak, ESeveritySCBreak, "", 0, "",""); + } + + int issues = 0; + PlatformHeaders unsuccessfulHeaders; + vector > unsuccessfulHeaderNames; + vector > platformUnsuccessfulHeaderNames; + int compErrors = 0; + + //validate if the headers have include guards, + //move ones without guards for individual compilation + validateHeaders(mergeVector, unsuccessfulHeaderNames); + + boost::thread_group mainThreads; + int mergeVectorCompErrs = 0; + int unsuccessfulCompErrs = 0; + int platformUnsuccessfulCompErrs = 0; + + // Analyse headers that were not found from platform data: + if( mergeVector.size() > 0 ) + { + //create copy of Analyser object for the new thread + Analyser* obj1=new Analyser(); + *obj1=*this; + //analyse mergeVector in different thread + mainThreads.create_thread(boost::bind(&Analyser::AnalyseHeaders,obj1,boost::ref(mergeVector),bundlesize,boost::ref(report),boost::ref(issues),boost::ref(mergeVectorCompErrs))); + } + + // Compile unsuccessful headers one by one, because it is unlikely that they + // will be compiled successfully here either: + if( unsuccessfulHeaderNames.size() > 0 ) + { + //create copy of Analyser object for the new thread + Analyser* obj2 = new Analyser(); + *obj2=*this; + //analyse unsuccessfulHeaderNames in different thread + mainThreads.create_thread(boost::bind(&Analyser::AnalyseHeaders,obj2,boost::ref(unsuccessfulHeaderNames),1,boost::ref(report),boost::ref(issues),boost::ref(unsuccessfulCompErrs))); + } + + if(pfHeaders.size() > 0) + { + AnalyzePlatforms(pfHeaders, unsuccessfulHeaders, report, issues, iUseThread); + if (iUseThread) + { + gHeaderThreads.join_all(); // wait for all threads in gHeaderThreads to complete + gComponentThreads.join_all(); // wait for all threads in gComponentThreads to complete + + //destroy the thredas in gHeaderThreads + int size = gHeaderThreads.size(); + for (int i=0;i~thread(); + } + + //destroy the thredas in gComponentThreads + size=gComponentThreads.size(); + for (int i=0;i~thread(); + } + } + + for( PlatformHeaders::iterator i = unsuccessfulHeaders.begin(); i != unsuccessfulHeaders.end(); ++i ) + { + // Build list of headers that could not be compiled with platform data: + platformUnsuccessfulHeaderNames.push_back(pair(i->first->ID(), i->second->ID())); + } + + if(platformUnsuccessfulHeaderNames.size() >0) + AnalyseHeaders(platformUnsuccessfulHeaderNames, 1, report, issues, platformUnsuccessfulCompErrs); + } + + mainThreads.join_all(); // wait for all threads in mainThreads to complete + compErrors += mergeVectorCompErrs + unsuccessfulCompErrs + platformUnsuccessfulCompErrs; + report.finishReport(); + + // List number of files which had compilation errors and could not be compiled + if ( _current_files + excludedHeaderSize < _total_files ) + cout << "\n" << ( _total_files - (_current_files + excludedHeaderSize) ) <<" files out of " << _total_files << " had some issues and could not be analysed.\n" << endl; + + // Wrap up the run and print statistics + unsigned int count = _total_files * 2; + + endtime = time(NULL); + time_t runningtime = endtime - starttime; + double timedelta = 0.0; + if (count > 0) + { + timedelta = (double)runningtime/(double)count; + } + cout << "\n"; + cout << "---------------------------------------------" << endl; + cout << "Finished!" << endl; + cout << "Files processed: " << count << endl; + cout << "Total time: " << endtime - originalStartTime << " seconds." << endl; + cout << "Platform data initialization time: " << pfInitTime << " seconds.\n"; + cout << "Compilation and analysis time: " << (long)runningtime << " seconds (Average: "< 0 ) + cout << "No of excluded headers: " << excludedHeaderSize << endl; + cout << "---------------------------------------------" << endl; + + if (iNotRemovedFiles.size() != 0) + { + cout << iNotRemovedFiles.size() << "\n"; + list tempvar; + list::iterator removefile = iNotRemovedFiles.begin(); + list::iterator fileend = iNotRemovedFiles.end(); + for(; removefile != fileend; removefile++) + { + CPPParser::RemoveFile(*removefile, tempvar); + } + if (tempvar.size() != 0) + { + iNotRemovedFiles = tempvar; + } else + { + iNotRemovedFiles.clear(); + } + } + + if (ret == 0 && issues != 0) + { + ret = 1; + } + return ret; +} + +void Analyser::AnalyseHeaders(const vector >& headerList, int bundlesize, ReportGenerator& report, int& issues, int& compErrors) +{ + unsigned int processedcount = 1; + stringvector basefilenames; + stringvector curfilenames; + vector > unsuccessfulHeaders; + + vector >::const_iterator fnmapiter = headerList.begin(); + while (fnmapiter != headerList.end()) + { + // Push the pair's members to their respective vectors + // for bundle handling + basefilenames.push_back(fnmapiter->first); + curfilenames.push_back(fnmapiter->second); + + // If a bundle is full or the item is the last one to process, + // we parse the current file lists to xml files + if ((processedcount > 0 && (processedcount % bundlesize == 0)) || + processedcount == headerList.size()) + { + if (!AnalyseBundle(basefilenames,curfilenames,report, issues)) + { + //If there where parsing errors in a bundle, we try to compile each header + // one by one + stringvector::iterator basebegin = basefilenames.begin(); + stringvector::iterator baseend = basefilenames.end(); + stringvector::iterator currentbegin = curfilenames.begin(); + + if( basefilenames.size() == 1 || + bundlesize == 1 ) + + { + if( basebegin != baseend ) + { + if(!iUseForcedHeaders) + { + //Add compilation error to the report + string compilationError = iCompErrTxt; + report.addIssue((*basebegin), "", EIssueIdentityFile, EIssueTypeCompilationError, ESeverityBBCBreak, ESeveritySCBreak, "", 0, + (*currentbegin),compilationError); + issues++; + } + else + unsuccessfulHeaders.push_back(pair(*basebegin,*currentbegin)); + + compErrors++; + } + } + else + { + while(basebegin != baseend ) + { + stringvector basefilename; + stringvector curfilename; + basefilename.push_back(*basebegin); + curfilename.push_back(*currentbegin); + if (!AnalyseBundle(basefilename,curfilename,report, issues)) + { + if(!iUseForcedHeaders) + { + //Add compilation error to the report + string compilationError = iCompErrTxt; + report.addIssue((*basebegin), "", EIssueIdentityFile, EIssueTypeCompilationError, ESeverityBBCBreak, ESeveritySCBreak, "", 0, + (*currentbegin),compilationError); + issues++; + } + else + unsuccessfulHeaders.push_back(pair(*basebegin,*currentbegin)); + + compErrors++; + } + basebegin++; + currentbegin++; + } + } + } + basefilenames.clear(); + curfilenames.clear(); + } + + fnmapiter++; + processedcount++; + } + + if( compErrors > 0 && iUseForcedHeaders ) + { + iUseForcedHeaders = false; + issues = 0; + compErrors = 0; + AnalyseHeaders(unsuccessfulHeaders, 1, report, issues, compErrors); + iUseForcedHeaders = true; + } + + if (iNotRemovedFiles.size() != 0) + { + list tempvar; + list::iterator removefile = iNotRemovedFiles.begin(); + list::iterator fileend = iNotRemovedFiles.end(); + for(; removefile != fileend; removefile++) + { + CPPParser::RemoveFile(*removefile, tempvar); + } + if (tempvar.size() != 0) + { + iNotRemovedFiles = tempvar; + } + else + { + iNotRemovedFiles.clear(); + } + } + +} + +// ---------------------------------------------------------------------------- +// Analyser::AnalyseBundle +// ---------------------------------------------------------------------------- +// +//bool Analyser::AnalyseBundle(const stringvector& basefilenames, const stringvector& curfilenames, ReportGenerator& report, int& issues) +bool Analyser::AnalyseBundle(const stringvector& basefilenames, + const stringvector& curfilenames, + ReportGenerator& report, + int& issues, + CPPParser* baseParser, + CPPParser* currParser, + stringvector* basecompileset, + stringvector* currcompileset) +{ + auto_ptr baseAutoPtr; + auto_ptr currAutoPtr; + CPPParser* parser = 0; + CPPParser* parser2 = 0; + + if( baseParser ) + { + // This function does not own the pointer, so no auto_ptr used here. + parser = baseParser; + } + else + { + parser = new CPPParser(iParams.getParameter(BASELINEPLAT)); + // Set temp directory for parser + parser->setTemp(iParams.getParameter(TEMPDIR)); + // Set forced headers + if(iUseForcedHeaders) + parser->setForcedHeaders(iForcedBaselineHeaders); + // Wrap allocated memory to an auto_ptr to get it deallocated properly. + baseAutoPtr.reset(parser); + } + if( currParser ) + { + // This function does not own the pointer, so no auto_ptr used here. + parser2 = currParser; + } + else + { + parser2 = new CPPParser(iParams.getParameter(CURRENTPLAT)); + // Set temp directory for parser + parser2->setTemp(iParams.getParameter(TEMPDIR)); + // Set forced headers + if(iUseForcedHeaders) + parser2->setForcedHeaders(iForcedCurrentHeaders); + // Wrap allocated memory to an auto_ptr to get it deallocated properly. + currAutoPtr.reset(parser2); + } + + try + { + // Parse the filename vectors into XML and eventually into a DOM format + DOMNode* root = 0; + DOMNode* root2 = 0; + if(basecompileset && basecompileset->size() != 0 ) + { + root = parser->parse(*basecompileset, "base", iParams.getParameter(BASELINEDIR), iNotRemovedFiles); + } + else + { + root = parser->parse(basefilenames, "base", iParams.getParameter(BASELINEDIR), iNotRemovedFiles); + } + if(currcompileset && currcompileset->size() != 0 ) + { + root2 = parser2->parse(*currcompileset, "current", iParams.getParameter(CURRENTDIR), iNotRemovedFiles); + } + else + { + root2 = parser2->parse(curfilenames, "current", iParams.getParameter(CURRENTDIR), iNotRemovedFiles); + } + + MacroAnalyser macros(parser->getMacroFilename(), parser2->getMacroFilename(), basefilenames, curfilenames); + + macros.Analyse(iMacroFiles); + +#if !defined(_DEBUG) && !defined(DEBUG) + parser->RemoveFile(parser->getMacroFilename(), iNotRemovedFiles); + parser2->RemoveFile(parser2->getMacroFilename(), iNotRemovedFiles); + parser->RemoveFile(parser->getCompErrFile(), iNotRemovedFiles); + parser2->RemoveFile(parser2->getCompErrFile(), iNotRemovedFiles); +#endif + // Merged macros + // + list > mergedfiles; + stringvector::const_iterator basebegin = basefilenames.begin(); + stringvector::const_iterator baseend = basefilenames.end(); + stringvector::const_iterator currentbegin = curfilenames.begin(); + while(basebegin != baseend) + { + mergedfiles.push_back(pair(*basebegin,*currentbegin)); + basebegin++; + currentbegin++; + } + if(mergedfiles.size() > 0) + { + issues += analyseTrees(root, root2,mergedfiles,report); + } + + // Duplicated macros + // + // Base duplicates + map > >& duplicatedMacros = macros.getBaseDuplicates(); + map > >::iterator duplicatedbegin = duplicatedMacros.begin(); + map > >::iterator duplicatedend = duplicatedMacros.end(); + for(; duplicatedbegin != duplicatedend; duplicatedbegin++) + { + string filename = duplicatedbegin->first; + // Process each duplicated macro from duplicatedMacros + vector >::iterator duplicatedbegin2 = duplicatedbegin->second.begin(); + vector >::iterator duplicatedend2 = duplicatedbegin->second.end(); + for(; duplicatedbegin2 != duplicatedend2; duplicatedbegin2++) + { + string macroname = duplicatedbegin2->first; + int lineNo = atoi(duplicatedbegin2->second.c_str()); + report.addIssue(filename, macroname, EIssueIdentityMacro, EIssueTypeNotAnalysed, ESeverityInformative, ESeveritySCInformative, "", lineNo, "", ""); + issues++; + } + } + + // Current + map > >& currDuplicatedMacros = macros.getCurrentDuplicates(); + duplicatedbegin = currDuplicatedMacros.begin(); + duplicatedend = currDuplicatedMacros.end(); + for(; duplicatedbegin != duplicatedend; duplicatedbegin++) + { + string filename = duplicatedbegin->first; + // Process each duplicated macro from duplicatedMacros + vector >::iterator duplicatedbegin2 = duplicatedbegin->second.begin(); + vector >::iterator duplicatedend2 = duplicatedbegin->second.end(); + for(; duplicatedbegin2 != duplicatedend2; duplicatedbegin2++) + { + string macroname = duplicatedbegin2->first; + int lineNo = atoi(duplicatedbegin2->second.c_str()); + report.addIssue("", macroname, EIssueIdentityMacro, EIssueTypeNotAnalysed, ESeverityInformative, ESeveritySCInformative, "", lineNo, filename, ""); + issues++; + } + } + + // Removed macros + // + map > > >& removedMacros = macros.getRemoved(); + map > > >::iterator removedbegin = removedMacros.begin(); + map > > >::iterator removedend = removedMacros.end(); + for(; removedbegin != removedend; removedbegin++) + { + string basefilename = removedbegin->second.GetBase(); + string currentfilename = removedbegin->second.GetCurrent(); + // Process each removed macro from removedMacros + list >::iterator removedbegin2 = removedbegin->second.GetValue().begin(); + list >::iterator removedend2 = removedbegin->second.GetValue().end(); + for(; removedbegin2 != removedend2; removedbegin2++) + { + string macroname = removedbegin2->first; + //int lineNo = atoi(removedbegin2->second.c_str()); + // No need to pass the line no in removed case. + report.addIssue(basefilename, macroname, EIssueIdentityMacro, EIssueTypeRemoval, ESeverityPossibleBBCBreak, ESeveritySCBreak, "", 0, currentfilename, ""); + issues++; + } + } + + // Changed macros + // + map,string> > > >& changedMacros = macros.getChanged(); + map,string> > > >::iterator changedbegin = changedMacros.begin(); + map,string> > > >::iterator changedend = changedMacros.end(); + for(; changedbegin != changedend; changedbegin++) + { + string basefilename = changedbegin->second.GetBase(); + string currentfilename = changedbegin->second.GetCurrent(); + // Process each changed macro from changedMacros + map,string> >::iterator changedbegin2 = changedbegin->second.GetValue().begin(); + map,string> >::iterator changedend2 = changedbegin->second.GetValue().end(); + for(; changedbegin2 != changedend2; changedbegin2++) + { + string macroname = changedbegin2->first; + string newcode = changedbegin2->second.first.second; + int lineNo = atoi(changedbegin2->second.second.c_str()); + report.addIssue(basefilename, macroname, EIssueIdentityMacro, EIssueTypeChange, ESeverityPossibleBBCBreak, ESeveritySCNULL, newcode, lineNo, currentfilename, ""); + issues++; + } + } + + + //clear the last set of files with macros + iMacroFiles.clear(); + } catch (HAException e) + { +#if !defined(_DEBUG) && !defined(DEBUG) + parser->RemoveFile(parser->getMacroFilename(), iNotRemovedFiles); + parser2->RemoveFile(parser2->getMacroFilename(), iNotRemovedFiles); +#endif + + //header has failed compilation with gccxml. get the compilation error text. + if (parser2->getCompErrFile()!="") + { + iCompErrTxt = BBCFileUtils::getCompilationError(parser2->getCompErrFile()); + if (iCompErrTxt == "") + iCompErrTxt = BBCFileUtils::getCompilationError(parser->getCompErrFile()); + } + else + { + if(parser->getCompErrFile()!="") + iCompErrTxt = BBCFileUtils::getCompilationError(parser->getCompErrFile()); + } +#if !defined(_DEBUG) && !defined(DEBUG) + parser->RemoveFile(parser->getCompErrFile(), iNotRemovedFiles); + parser2->RemoveFile(parser2->getCompErrFile(), iNotRemovedFiles); +#endif + + + //delete parser; + //delete parser2; + return false; + } + //delete parser; + //delete parser2; + return true; +} + + +// ---------------------------------------------------------------------------- +// Analyser::processFileReplaces +// Process the file replaces +// ---------------------------------------------------------------------------- +// +pair Analyser::processFileReplaces(pair& aFile, const stringmap& aReplaceMap, list >& aCurrentFiles) +{ + string searched(aFile.second); + pair replacement(aFile); + // If there are items on replace map, then apply the + // replaces when necessary + if (aReplaceMap.size() > 0) + { + StringMapIterC fileMapIter = aReplaceMap.find(searched); + if (fileMapIter != aReplaceMap.end()) + { + string file = fileMapIter->second; + list >::const_iterator filereplace = FindFromList(toLowerCaseWin(file), aCurrentFiles, ERightValue, compareFiles); + if (filereplace != aCurrentFiles.end()) + { + replacement = *filereplace; + } + } + } + + return replacement; +} + + +// ---------------------------------------------------------------------------- +// Analyser::createReplaceMap +// +// ---------------------------------------------------------------------------- +// +void Analyser::createReplaceMap(const string& aReplaceList, stringmap& aReplaceMap) +{ + string originalfilename(""); + string replacementfilename(""); + string* name = &originalfilename; + bool original = true; + bool isstr = false; + for (size_t i = 0; i < aReplaceList.length(); i++) + { + char ch = aReplaceList.at(i); + if (ch == ' ' && isstr == false) + { + if (original == true) + { + original = false; + name = &replacementfilename; + } + else + { + // Pair separator found. + // Store the pair (original, replacement) + stringpair mappair(toLowerCaseWin(originalfilename), toLowerCaseWin(replacementfilename)); + aReplaceMap.insert(mappair); + replacementfilename.resize(0); + originalfilename.resize(0); + + original = true; + name = &originalfilename; + } + } else if (ch == '"') + { + if (isstr == true) + { + isstr = false; + } else + { + isstr = true; + } + } else + { + *name += ch; + } + } + if (original == true) + { + throw HAException("Syntax error: There has been given file name to replace but not file name for replace."); + } + if (originalfilename.length() > 0 && replacementfilename.length() > 0) + { + // Store the last pair in replacement list + stringpair mappair(toLowerCaseWin(originalfilename), toLowerCaseWin(replacementfilename)); + aReplaceMap.insert(mappair); + } +} + +// ---------------------------------------------------------------------------- +// Analyser::fileDiffs +// ---------------------------------------------------------------------------- +// +void Analyser::fileDiffs(vector >& aFiles, list& aMismatches) +{ + vector > ret; + ret.reserve(aFiles.size()); + vector >::iterator file = aFiles.begin(); + vector >::iterator fileend = aFiles.end(); + + for(;file != fileend; file++) + { + // START -- Support for multiple header directories + list > basedirs = BBCFileUtils::extractFilenames(iParams.getParameter(BASELINEDIR)); + list >::iterator basedirbegin = basedirs.begin(); + string basedir; + string basefile; + for(; basedirbegin != basedirs.end(); basedirbegin++) + { + // Find the base dir from the list of base dirs + basedir = basedirbegin->first; + basefile = basedir + DIR_SEPARATOR + file->first; + if (BBCFileUtils::FileExists(basefile)) + break; + } + + list > curdirs = BBCFileUtils::extractFilenames(iParams.getParameter(CURRENTDIR)); + list >::iterator curdirbegin = curdirs.begin(); + string curdir; + string curfile; + for(; curdirbegin != curdirs.end(); curdirbegin++) + { + // Find the current dir from the list of current dirs + curdir = curdirbegin->first; + curfile = curdir + DIR_SEPARATOR + file->second; + if (BBCFileUtils::FileExists(curfile)) + break; + } + // END -- Support for multiple header directories + + if (file->second == "") + { + // We hadn't find matching file from current list so we add it to removed list + aMismatches.push_back(basefile); + } else + { + pair tempvar(basefile, curfile); + ret.push_back(tempvar); + } + } + aFiles = ret; +} + +// ---------------------------------------------------------------------------- +// Analyser::getFilenameWithoutDir +// Return the file part of the filename, eg. retuns the rightmost part of +// the given string, up to a "\" // or "/" separator. +// ---------------------------------------------------------------------------- +// +string Analyser::getFilenameWithoutDir(const string& aFilename) +{ + string ret = aFilename; + string::size_type idx = rightmostDirSeparatorIndex(aFilename); + if (idx != string::npos) + { + ret = aFilename.substr(idx+1, aFilename.length() - idx); + } + return ret; +} + +// ---------------------------------------------------------------------------- +// Analyser::testFileAvailability +// ---------------------------------------------------------------------------- +// +#if 0 +void Analyser::testFileAvailability(stringmap map) +{ + stringmap::iterator begin = map.begin(); + stringmap::iterator end = map.end(); + + for(; begin!= end; begin++) + { + string file = (*begin).first; + + int isValid = ACCESS(file.c_str(), 0); + if (isValid == -1) + { + throw HAException("File: \"" + file + "\" not found"); + } + + file = (*begin).second; + + isValid = ACCESS(file.c_str(), 0); + if (isValid == -1) + { + throw HAException("File: \"" + file + "\" not found"); + } + } +} + +#endif + +// ---------------------------------------------------------------------------- +// Analyser::MergeFiles +// ---------------------------------------------------------------------------- +// +void Analyser::MergeFiles(const list >& aBasefiles, list >& aCurrentfiles, + const string& aReplaceList, vector >& aMatches) +{ + size_t asdf = aBasefiles.size(); + list >::const_iterator baseiter = aBasefiles.begin(); + list >::const_iterator baseend = aBasefiles.end(); + list > removedcurrentfiles; + list > mismatches; + if (!iParams.givenParameter(BASELINE)) + { + stringmap replaceMap; + if (aReplaceList.length() > 0) + { + createReplaceMap(aReplaceList, replaceMap); + stringmap::iterator begin = replaceMap.begin(); + stringmap::iterator end = replaceMap.end(); + } + for(; baseiter != baseend; baseiter++) + { + pair file = *baseiter; + file = processFileReplaces(file, replaceMap, aCurrentfiles); + pair tempvar; + //compareWholeString will be set to true, + //only if the file name with whole path of current file need to compare with base file. + //else by default will always be set to false. + list >::iterator current = FindFromList(file.second, aCurrentfiles, ERightValue, compareFiles, false,true); + if (current != aCurrentfiles.end()) + { + tempvar.first = baseiter->first.substr(1); + tempvar.second = current->first.substr(1); + aMatches.push_back(tempvar); + removedcurrentfiles.push_back(*current); + aCurrentfiles.erase(current); + } else + { + current = FindFromList(file.second, removedcurrentfiles, ERightValue, compareFiles, false); + if (current != removedcurrentfiles.end()) + { + tempvar.first = baseiter->first.substr(1); + tempvar.second = current->first.substr(1); + aMatches.push_back(tempvar); + } else + { + mismatches.push_back(file); + } + } + } + baseiter = mismatches.begin(); + baseend = mismatches.end(); + for(; baseiter != baseend; baseiter++) + { + string filename = BBCFileUtils::StripPath(baseiter->second); + pair file(filename, filename); // We don't need to put filename to lowercase as it's already in lowercase + file = processFileReplaces(file, replaceMap, aCurrentfiles); + string empty(""); + pair tempvar; + tempvar.first = baseiter->first.substr(1); + list >::iterator current = FindFromList(file.second, aCurrentfiles, ERightValue, compareFiles); + if (current != aCurrentfiles.end()) + { + tempvar.second = current->first.substr(1); + } else + { + tempvar.second = empty; + } + aMatches.push_back(tempvar); + } + } else + { + // START -- Support for multiple header directories + list > basedirs = BBCFileUtils::extractFilenames(iParams.getParameter(BASELINEDIR)); + list >::iterator basedirbegin = basedirs.begin(); + bool basefilefound = false; + string basefile; + for(; basedirbegin != basedirs.end(); basedirbegin++) + { + string basedir = basedirbegin->first; + basefile = basedir + DIR_SEPARATOR + aBasefiles.front().first; + + if (ACCESS(basefile.c_str(), 0) != -1) + { + basefilefound = true; + break; + } + } + list > curdirs = BBCFileUtils::extractFilenames(iParams.getParameter(CURRENTDIR)); + list >::iterator curdirbegin = curdirs.begin(); + bool curfilefound = false; + string curfile; + + for(; curdirbegin != curdirs.end(); curdirbegin++) + { + string curdir = curdirbegin->first; + curfile = curdir + DIR_SEPARATOR + aBasefiles.front().first; + if (ACCESS(curfile.c_str(), 0) != -1) + { + curfilefound = true; + break; + } + } + if (!basefilefound ) + { + throw HAException("File \"" + basefile + "\" not found"); + } + if (!curfilefound) + { + throw HAException("File \"" + curfile + "\" not found"); + } + pair tempvar(aBasefiles.front().first, aCurrentfiles.front().first); + aMatches.push_back(tempvar); + // END -- Support for multiple header directories + } +} + +// ---------------------------------------------------------------------------- +// AnalyserParams::diffs +// +// ---------------------------------------------------------------------------- +// +void Analyser::diffs( const list >& allfiles, + const list >& sets, + list >& result) +{ + result = sets; + list::iterator setiter = result.begin(); + while(setiter != result.end()) + { + if( setiter->first.find_first_of("*?") != string::npos ) + setiter = result.erase(setiter); + else + ++setiter; + } + + list >::const_iterator file = allfiles.begin(); + list >::const_iterator fileend = allfiles.end(); + for(; file != fileend; file++) + { + list >::iterator set = + FindFromList(file->second, result, ERightValue); + if (set == result.end()) + { + set = FindFromList(file->second, result, ERightValue, compareFiles); + } + + if (set != result.end()) + { + result.erase(set); + } + } + +} + +// ---------------------------------------------------------------------------- +// AnalyserParams::canonicalizeFilename +// Get the actual name of a file. +// ---------------------------------------------------------------------------- +// +list > Analyser::canonicalizeFilename(list >& sets) +{ + list > ret; + list >::iterator begin = sets.begin(); + list >::iterator end = sets.end(); + for(; begin != end; begin++) + { + if (begin->first.at(0) != DIR_SEPARATOR && begin->first.find(DIR_SEPARATOR) != string::npos) + { + string left = ""; + left += DIR_SEPARATOR; + left += begin->first; + string right = ""; + right += DIR_SEPARATOR; + right += begin->second; + ret.push_back(pair(left, right)); + } else + { + ret.push_back(*begin); + } + } + + return ret; +} + + +// ---------------------------------------------------------------------------- +// Analyser::Wrapper +// Wrapper function to analyse all files in a component in separate thread. +// +// ---------------------------------------------------------------------------- +// +void Analyser::Wrapper( ReportGenerator& report, + int& issues, + CPPParser baseParser, + CPPParser currParser, + PlatformHeaders& pfHeaders, + PlatformHeaders& unsuccessfulHdrs + ) +{ + stringvector tiBaseFilenames; // This contains also additional headers needed to compile baseline + stringvector tiCurrFilenames; // This contains also additional headers needed to compile product + PlatformHeaders tiInvalidFiles; // holds a list of files without include guards need to be compiled individually + stringvector tiBaseIncludes; // This contains also additional headers needed to compile baseline + stringvector tiCurrIncludes; // This contains also additional headers needed to compile product + + stringvector baseSysIncludes; // This contains headers needed to compile baseline for 3rd time analyzation of a single header. + stringvector curSysIncludes; // This contains headers needed to compile product for 3rd time analyzation of a single header. + + tiBaseFilenames.assign(iBaseFilenames.begin(),iBaseFilenames.end()); + tiCurrFilenames.assign(iCurrFilenames.begin(),iCurrFilenames.end()); + tiInvalidFiles.assign(iInvalidFiles.begin(),iInvalidFiles.end()); + tiBaseIncludes.assign(iBaseIncludes.begin(),iBaseIncludes.end()); + tiCurrIncludes.assign(iCurrIncludes.begin(),iCurrIncludes.end()); + + if (iOnlySystemIncludeRequired == true) + { + //tiBaseIncludes and tiCurrIncludes are required for 3rd time analyzation. + //This time parse each unsuccessful header with both system includes and paths. + baseSysIncludes.assign(tiBaseIncludes.begin(),tiBaseIncludes.end()); + curSysIncludes.assign(tiCurrIncludes.begin(),tiCurrIncludes.end()); + + // Clear these includes as for 2nd time parsing of each unsuccessful headres, + //as only system include paths arerequuired. + tiBaseIncludes.clear(); + tiCurrIncludes.clear(); + } + + + if( (tiBaseIncludes.size()>0 && tiCurrIncludes.size()>0)|| (tiBaseFilenames.size()>0 && tiCurrFilenames.size()>0) ) + { + if( AnalyseBundle(tiBaseFilenames, tiCurrFilenames, report, issues, &baseParser, &currParser, &tiBaseIncludes, &tiCurrIncludes)) + { + tiBaseFilenames.clear(); + tiCurrFilenames.clear(); + } + } + + if (iNotRemovedFiles.size() != 0) + { + list tempvar; + list::iterator removefile = iNotRemovedFiles.begin(); + list::iterator fileend = iNotRemovedFiles.end(); + for(; removefile != fileend; removefile++) + { + CPPParser::RemoveFile(*removefile, tempvar); + } + if (tempvar.size() != 0) + { + iNotRemovedFiles = tempvar; + } + else + { + iNotRemovedFiles.clear(); + } + } + + if(tiInvalidFiles.size() > 0) + { + // also add to this list, the set of headers + // without include guards + PlatformHeaders::iterator add = tiInvalidFiles.begin(); + for(; add != tiInvalidFiles.end(); ++add ) + { + tiBaseFilenames.push_back( add->first->ID() ); + tiCurrFilenames.push_back( add->second->ID() ); + } + } + + // if thread flag is set and there are gretaer number of files, create threads for analysing every PLATFORM_BUNDLESIZE number of files + if( iUseThread && tiBaseFilenames.size() >= PLATFORM_BUNDLESIZE ) + { + stringvector tmp; + int pcount = 0; + stringvector::iterator i = tiBaseFilenames.begin(); + for(; i != tiBaseFilenames.end(); ++i ) + { + pcount++; + PlatformHeaders::iterator h = FindHeaderPair(*i, pfHeaders); + if( h != pfHeaders.end() ) + { + tmp.push_back(*i); + } + if ((pcount % PLATFORM_BUNDLESIZE == 0 || pcount == tiBaseFilenames.size()) && tmp.size()>0) + { + while (lock.locked()) + { + #ifdef __WIN__ + Sleep(4000); + #else + usleep(4000*1000); + #endif + } + lock.lock(); + + if(gComponentThreads.size() >= MAX_THREAD_COUNT2) + { + gComponentThreads.join_all(); + int size = gComponentThreads.size(); + for (int i=0;i~thread(); + } + } + + //2nd time analyzation of each header in a different thread + Analyser* obj = new Analyser(); + *obj = *this; + int size = gComponentThreads.size(); + gpHeaderThreads[size]=gComponentThreads.create_thread(boost::bind(&Analyser::Wrapper2,obj,tmp, + boost::ref(pfHeaders), boost::ref(unsuccessfulHdrs), boost::ref(report), boost::ref(issues))); + lock.unlock(); + tmp.clear(); + + } + } + } + else // do not create different thread. analyse in the same thread. + { + stringvector::iterator i = tiBaseFilenames.begin(); + for(; i != tiBaseFilenames.end(); ++i ) + { + PlatformHeaders::iterator h = FindHeaderPair(*i, pfHeaders); + if( h != pfHeaders.end() ) + { + if(( pfHeaders.size() > 1 ) ) + { + PlatformHeaders tempHeaders; + tempHeaders.push_back(*h); + h->first->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED); + iOnlySystemIncludeRequired = true; + //2nd time analyzation of each header in same thread + AnalyzePlatforms( tempHeaders, unsuccessfulHdrs, report, issues, false ); + iOnlySystemIncludeRequired = false; + } + else + { + //The 3rd time parsing is required to check again each unsuccessful headers + //with system includes and paths from platform data + if(!AnalyseBundle(tiBaseFilenames, tiCurrFilenames, report, issues, &baseParser, &currParser, &baseSysIncludes, &curSysIncludes)) + { + if( FindHeaderPair(h->first->ID(), unsuccessfulHdrs ) == unsuccessfulHdrs.end() ) + { + unsuccessfulHdrs.push_back(*h); + } + } + if (iNotRemovedFiles.size() != 0) + { + list tempvar; + list::iterator removefile = iNotRemovedFiles.begin(); + list::iterator fileend = iNotRemovedFiles.end(); + for(; removefile != fileend; removefile++) + { + CPPParser::RemoveFile(*removefile, tempvar); + } + if (tempvar.size() != 0) + { + iNotRemovedFiles = tempvar; + } + else + { + iNotRemovedFiles.clear(); + } + } + } + } + } + } +} + +// ---------------------------------------------------------------------------- +// Analyser::Wrapper2 +// Wrapper function to analyse group of files in a component individually in different thread. +// +// ---------------------------------------------------------------------------- +// +void Analyser::Wrapper2(stringvector filenames, PlatformHeaders& pfHeaders, PlatformHeaders& unsuccessfulHdrs, ReportGenerator& report, int& issues) +{ + PlatformHeaders tempHeaders; + stringvector::iterator i = filenames.begin(); + for(; i != filenames.end(); ++i ) + { + PlatformHeaders::iterator h = FindHeaderPair(*i, pfHeaders); + if( h != pfHeaders.end() ) + { + tempHeaders.push_back(*h); + h->first->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED); + iOnlySystemIncludeRequired = true; + AnalyzePlatforms( tempHeaders, unsuccessfulHdrs, report, issues, false ); + iOnlySystemIncludeRequired = false; + } + } + + if (iNotRemovedFiles.size() != 0) + { + list tempvar; + list::iterator removefile = iNotRemovedFiles.begin(); + list::iterator fileend = iNotRemovedFiles.end(); + for(; removefile != fileend; removefile++) + { + CPPParser::RemoveFile(*removefile, tempvar); + } + if (tempvar.size() != 0) + { + iNotRemovedFiles = tempvar; + } + else + { + iNotRemovedFiles.clear(); + } + } +} + + + +void Analyser::ParseAndCompareResourceFiles(vector >& resourcevector, ReportGenerator& report) +{ + ResourceContent baseResource; + ResourceContent curResource; + + list > iBaseSystemheaders = BBCFileUtils::extractFilenames(iParams.getParameter(BASELINEPLAT)); + list > iCurSystemheaders = BBCFileUtils::extractFilenames(iParams.getParameter(CURRENTPLAT)); + + for(int outer = 0; outer< (int)resourcevector.size(); outer++) + { + list > baseSystemheaders; + list > curSystemheaders; + + baseSystemheaders = iBaseSystemheaders; + curSystemheaders = iCurSystemheaders; + pair files = resourcevector.at(outer); + vector bIncludes; + vector cIncludes; + + + baseResource.RHFileName = ""; + curResource.RHFileName = ""; + + baseResource.RHFileName = BBCFileUtils::TrimAll(files.first); + curResource.RHFileName = BBCFileUtils::TrimAll(files.second); + + pair fileAnalyzed; + fileAnalyzed.first = baseResource.RHFileName; + fileAnalyzed.second = curResource.RHFileName; + bool pairFound = false; + // check if the file is already analyzed or not. + for(int i = 0; i < (int)iRHFile_Analyzed.size(); i++ ) + { + pair filePair = iRHFile_Analyzed.at(i); + if(fileAnalyzed.first == filePair.first ) + { + pairFound = true; + break; + } + } + // File is not analyzed yet, so analyze it. + if(pairFound == false ) + { + iRHFile_Analyzed.push_back(fileAnalyzed); + + ifstream file(files.first.c_str()); + if(!file.is_open()) + { + cerr << "ERROR: Cannot open " << files.first << " for reading!" << endl; + exit(17); + } + + // baseline resource file parsing + getElementListFromRHFile(file,baseResource,bIncludes ); + file.close(); + + // handle #include .RH headers, get proper path from system includes + int basePos = (int)baseResource.RHFileName.find_last_of(DIR_SEPARATOR); + string basePath = baseResource.RHFileName.substr(0,basePos); + vector > includes; + bool isPresent = false; + pair bPath; + list >::iterator bHdr = baseSystemheaders.begin(); + for(;bHdr!= baseSystemheaders.end(); bHdr++) + { + bPath = *bHdr; + if(bPath.first == basePath) + { + isPresent = true; + break; + } + } + if(isPresent == false) + { + pair bPair; + bPair.first =basePath; + bPair.second =basePath; + baseSystemheaders.push_back(bPair); + } + + bHdr= baseSystemheaders.begin(); + for(int i = 0; i < (int)bIncludes.size(); i++) + { + for(;bHdr != baseSystemheaders.end(); bHdr++) + { + pair baseHeader = *bHdr; + pairbasePair; + if(BBCFileUtils::FileExists(baseHeader.first + DIR_SEPARATOR + bIncludes.at(i)) ) + { + basePair.first = baseHeader.first + DIR_SEPARATOR + bIncludes.at(i); + includes.push_back(basePair); + break; + } + } + } + + ifstream file2(files.second.c_str()); + if(!file2.is_open()) + { + cerr << "ERROR: Cannot open " << files.second << " for reading!" << endl; + exit(17); + } + // current resource file parsing + getElementListFromRHFile(file2,curResource, cIncludes ); + file2.close(); + + _current_files++; + cout << "\nAnalysing files (" << _current_files << "/" << _total_files << "): " << files.first <<" => "<< files.second << endl; + + // get current resource file's path and add to system include paths + // to get proper path for #include rh headers in current file + int cPos = (int)curResource.RHFileName.find_last_of(DIR_SEPARATOR); + string curPath = curResource.RHFileName.substr(0,cPos); + isPresent = false; + list >::iterator chdr= curSystemheaders.begin(); + pair cPath; + for(;chdr != curSystemheaders.end(); chdr++) + { + cPath = *chdr; + if(cPath.first == curPath) + { + isPresent = true; + break; + } + } + if(isPresent == false) + { + pair cPair; + cPair.first = curPath; + cPair.second = curPath; + curSystemheaders.push_back(cPair); + } + + + for(int out = 0; out < (int)includes.size(); out++) + { + int bLoc = (int)includes.at(out).first.find_last_of(DIR_SEPARATOR); + string bString = includes.at(out).first.substr(bLoc+1,string::npos); + bool includedHeaderPresent = false; + + for(int j = 0; j < (int)cIncludes.size(); j++) + { + bool fileMatched = false; + chdr= curSystemheaders.begin(); + for(;chdr != curSystemheaders.end(); chdr++) + { + pair curHeader = *chdr; + string curFile = curHeader.first + DIR_SEPARATOR + cIncludes.at(j); + int loc = (int)curFile.find_last_of(DIR_SEPARATOR); + string curTemp = curFile.substr(loc+1 ,string::npos); + if(bString == curTemp) + { + includedHeaderPresent = true; + if(BBCFileUtils::FileExists(curFile) ) + { + fileMatched = true; // current file found in curr dir + includes.at(out).second = curFile; + break; + } + } + } + + if ( fileMatched = false ) + { + // file does not exists in curdir + report.addIssue(baseResource.RHFileName, includes.at(out).first, EIssueIdentityFile, + EIssueTypeRemoval,ESeverityBBCBreak,ESeveritySCNULL, "", 0, curResource.RHFileName,""); + break; + } + } + if(includedHeaderPresent == false) + { + // add issue, as field is removed in current file. + report.addIssue(baseResource.RHFileName, bString, EIssueIdentityField, + EIssueTypeRemoval,ESeverityNULL,ESeveritySCBreak, "", 0, curResource.RHFileName,""); + } + } + + for(int l = 0; l < (int)includes.size(); l++ ) + { + pair pair = includes.at(l); + if(pair.first.size() > 0 && pair.second.size()>0) + { + resourcevector.push_back(pair); + } + } + + compareResources( baseResource, curResource, report); + } + + + baseResource.structList.clear(); + baseResource.enumList.clear(); + baseResource.macroList.clear(); + + curResource.structList.clear(); + curResource.enumList.clear(); + curResource.macroList.clear(); + + + }// end of one resource + cout<<"\n\n"<& includes ) +{ + string line; + EnumElement lEnum; + string tempData; + string elementVal; + + StructElement lStruct; + string structName; + + bool structInuse = false; + bool enumInuse = false; + bool macroInuse = false; + bool keyFound = false; + bool elementfound = false; + bool valueFound = false; + + bool comment = false; + bool ignoreLine = false; + + bool newLinecharFound = false; // for macros, newline character can be present + + long currentEnumVal = -1; + + char keywords [23][15] = {"short","long", "word", "len", "byte", "struct", "ltext","enum", "ltext8", "ltext16", "ltext32", "llink", "srlink","double", + "buf<1>","buf<2>","buf<4>","buf<8>","buf<16>","buf<32>","buf<64>","buf<128>","buf<256>"}; + + MacroElement macro; + int lineNo = 0; + + while(getline(RHFile,line)) + { + lineNo++; + pair enummember; + StructMember elementMember; + line = toLowerCase(trimWhiteSpace(line)); + + // Ignore all comment lines. e.g /*xxxxxxxxxx*/ Struct ABCD , start reading characterwise from struct + if(enumInuse == false && macroInuse == false && structInuse == false ) + { + if(line.find("/*") != -1 ) + { + if( line.find("*/") == -1) + { + comment = true; + continue; + } + else + { + int com = (int)line.find_last_of("*"); + line= line.substr(com +2, string::npos); + } + } + if(line.find("*/") != -1 ) + { + comment = false; + if(ignoreLine == true) + ignoreLine = false; + continue; + } + if(comment == true) + { + continue; + } + if(line.find("//") != -1 ) + { + int com = (int)line.find_first_of("//"); + bool wordFound = false; + line = line.substr(0,com); + for (int i = 0; i< (int)line.size(); i++ ) + { + // check '//' commentline starts after some key value e.g struct ABCD // xyz + if ( (int)line.at(i ) != 32 && (int)line.at(i) != 9 ) // 32 and 9 are for space and invalid character + { + wordFound = true; + break; + } + } + if(wordFound == false) + continue; + } + + } + + // Find any other header file is included in current file + // Then add it to file and check whether this is already analyzed or not. + // If not, then analyze it. + if(line.find ("#") != -1 && line.find("include") != -1 ) + { + int start = (int)line.find_first_of ("<"); + + int end; + if(start == -1) + { + start =(int) line.find_first_of("\""); + end = (int)line.find_last_of("\""); + } + else + { + end = (int)line.find(">"); + } + + if (start > 0 && end > 0 ) + { + line = line.substr(start + 1,(end - start) - 1); + line = BBCFileUtils::TrimAll(line); + int loc = (int)line.find(RH_EXTENSION); + // Include only .rh files + if(loc != -1) + includes.push_back(line); + } + } + + // Now check lines for key structure (struct, enum, #inlude and start reading characterwise unless the key structure end. + if (keyFound == false ) + { + tempData.clear(); + int enumloc = (int)line.find(KEY_ENUM); + // to get enum key word properly. After "enum" keyword, there might be no name present. + // For this case, following checks are needed. + if( enumloc!= -1) + { + enumInuse = true; + string prestring = line.substr(0,enumloc); + for(int i = 0; i< (int)prestring.size(); i++ ) + { + if( (int)prestring.at(i)!= 32 && (int)prestring.at(i) != 9 ) + { + enumInuse =false; + break; + } + } + if(enumInuse == true) + { + string postline = line.substr(enumloc+strlen(KEY_ENUM) ,string::npos); + if( postline.size() > 0 && (int)postline.at(0)!= 32 && (int)postline.at(0) != 9 ) + { + enumInuse =false; + break; + } + else + { + line = postline; + macroInuse = false; + structInuse = false; + lEnum.enumName = ""; + lEnum.enums.clear(); + } + } + } + if(line.find(KEY_MACRO) != -1) + { + macroInuse = true; + enumInuse = false; + structInuse = false; + macro.macroName = ""; + macro.macroVal = ""; + line = line.substr(strlen(KEY_MACRO),string::npos); + } + + if(line.find(KEY_STRUCT) != -1) + { + structInuse = true; + enumInuse = false; + macroInuse = false; + lStruct.structName = ""; + lStruct.members.clear(); + line = line.substr(strlen(KEY_STRUCT),string::npos); + } + } + + // If any of the key found, then following lines will be checked character wise. + if ( enumInuse == true || macroInuse == true || structInuse == true ) + { + keyFound = true; + + EnumMember enummember; + + string elementName; + string elementType; + string structElementVal; + + bool lineend = false; + int length = int(line.size()); + + for (int j = 0; j < length ; j++) + { + int temp = line.at(j); + //int templie = line.at(j); + switch (temp) + { + case 32: // For ' ' + case 9: //for Invalid space + { + if (structInuse == true && tempData.size() > 0) + { + if ( elementfound == true ) + { + for (int k = 0 ; k < 23 ; k++ ) + { + // got the type, will check with all possible data types.Else it will be member name. + int loc = int(line.find_first_of(keywords[k])); + string key(keywords[k]); + if (tempData == key ) + { + elementType.append(keywords[k]); + tempData.clear(); + break; + } + } + } + } + if (macroInuse == true && macro.macroName.size() <=0 && tempData.size() > 0) // can be macro name + { + macro.macroName = tempData; + macro.lineNo = lineNo; + tempData.clear(); + } + } + break; + case 59://For ';' + { + if ( structInuse == true && elementfound == true && tempData.size() > 0) + { + elementName.append(tempData); + elementMember.elementName = elementName; + elementMember.elementType = elementType; + elementMember.lineNo = lineNo; + if (valueFound == true) + { + elementMember.elementValue= structElementVal; + valueFound = false; + } + lStruct.members.push_back (elementMember); + tempData.clear(); + } + + if(macroInuse ==false) + break; + + } + + case 44://For ',' + { + if(macroInuse ==false) + { + if ( enumInuse == true && elementfound == true && tempData.size() > 0) + { + if (valueFound == true) + { + enummember.enumVal = elementVal.c_str(); + char *p; + // convert enumVal to long , so that can be incremented if required. + currentEnumVal = strtol(enummember.enumVal.c_str(),&p,0); + valueFound = false; + } + else + { + currentEnumVal += 1; + string p; + // convert long to string + enummember.enumVal = ltoa(currentEnumVal,p,0); + } + enummember.enumMemName.append(tempData); + enummember.lineNo = lineNo; + + lEnum.enums.push_back(enummember); + + tempData.clear(); + elementVal.clear(); + } + break; + } + } + + case 61: //For '=' + { + if(macroInuse == false) + { + valueFound = true; + break; + } + } + //break; + + case 123: //For '{' + { + if(macroInuse ==false) + { + if(tempData.size() > 0 ) + { + if(structInuse == true) + { + lStruct.structName.assign(tempData); + lStruct.lineNo = lineNo; + } + else + { + lEnum.enumName.assign(tempData); + lEnum.lineNo = lineNo; + } + } + tempData.clear(); + elementfound = true; + + break; + } + } + case 125: //For '}' + { + if(macroInuse ==false) + { + if(structInuse == true) + { + structInuse = false; + if(tempData.size() > 0) // if some inline macro is present + { + elementMember.elementName = tempData ; + elementMember.elementType = ""; + elementMember.lineNo = lineNo; + lStruct.members.push_back(elementMember); + } + resource.structList.push_back(lStruct); + } + else if ( enumInuse == true ) + { + if (elementfound == true && tempData.size() > 0) + { + if (valueFound == true) + { + enummember.enumVal = elementVal.c_str(); + char *p; + // convert enumVal to long , so that can be incremented if required. + currentEnumVal = strtol(enummember.enumVal.c_str(),&p,0); + valueFound = false; + } + else + { + currentEnumVal += 1; + string p; + // convert long to string + enummember.enumVal = ltoa(currentEnumVal,p,0); + } + + enummember.lineNo = lineNo; + + enummember.enumMemName.append(tempData); + + lEnum.enums.push_back(enummember); + } + currentEnumVal = -1; + elementVal.clear(); + enumInuse = false; + resource.enumList.push_back(lEnum); + } + keyFound = false; + elementfound = false; + tempData.clear(); + + break; + } + } + default: + { + // followings are to ignore any comment line in between. + if( j+1 0) // can be macro name + { + newLinecharFound = true; // new line character found + if ( macro.macroName.size() <=0) + { + macro.macroName = tempData; + macro.lineNo = lineNo; + } + else + { + macro.macroVal.append(tempData); + } + tempData.clear(); + + } + // Check macro definition ended after newlines + if( (int) line.at(j)!= 92 && j+1 >= length && macroInuse == true && newLinecharFound == true ) + { + newLinecharFound =false; + //macroInuse = false; + //macro.macroVal.append(tempData); + //tempData.clear(); + break; + } + if (enumInuse == true || macroInuse == true || structInuse == true) + { + if(valueFound == true) + { + if ( structInuse == true ) + structElementVal.push_back(line.at(j)); + else + elementVal.push_back(line.at(j)); + } + else + { + if( (int)line.at(j) != 92)// ignore newline character + tempData.push_back(line.at(j)); + } + } + } + + + } + break; + } + if (lineend == true) + break; + }// line end + + // Macro structure ended, fill the values. + if( macroInuse == true && newLinecharFound == false && tempData.size() > 0 ) + { + if(tempData.size()> 0 ) + { + macro.macroVal.append(tempData); + tempData.clear(); + } + keyFound = false; + macroInuse = false ; + resource.macroList.push_back(macro); + } + } + + }// End of all lines in resource file + +} + +void Analyser::compareResources(ResourceContent &baseResource, ResourceContent &curResource, ReportGenerator& report) +{ + int base_struct_no = (int)baseResource.structList.size(); + int cur_struct_no = (int)curResource.structList.size(); + + int base_enum_no = (int)baseResource.enumList.size(); + int cur_enum_no = (int)curResource.enumList.size(); + + int base_macro_no = (int)baseResource.macroList.size(); + int cur_macro_no = (int)curResource.macroList.size(); + + StructElement baseStruct; + StructElement curStruct; + + EnumElement baseEnum; + EnumElement curEnum; + + MacroElement baseMacro; + MacroElement curMacro; + + for(int i = 0; i < base_struct_no; i++ ) + { + baseStruct = baseResource.structList.at(i); + bool structFound = false; + for(int j = 0; j < cur_struct_no; j++ ) + { + curStruct = curResource.structList.at(j); + if(baseStruct.structName == curStruct.structName ) + { + int baseMemNo = (int)baseStruct.members.size(); + int curMemNo = (int)curStruct.members.size(); + + structFound = true; + + for( int bInner = 0; bInner < baseMemNo; bInner++ ) + { + bool memFound = false; + for ( int cInner = 0; cInner < curMemNo; cInner++ ) + { + if ( baseStruct.members.at(bInner).elementName == curStruct.members.at(cInner).elementName ) + { + memFound = true; + if(baseStruct.members.at(bInner).elementType == curStruct.members.at(cInner).elementType) + { + if(baseStruct.members.at(bInner).elementValue.size() > 0 + && (baseStruct.members.at(bInner).elementValue != curStruct.members.at(cInner).elementValue) ) + { + //add issue member value mismatch + string bVal = baseStruct.structName + "::" + baseStruct.members.at(bInner).elementName; + string cVal = curStruct.members.at(cInner).elementValue; + int lineNo = curStruct.members.at(cInner).lineNo; + report.addIssue(baseResource.RHFileName, bVal, EIssueIdentityStructMember, EIssueTypeChangeInInitialisation, + ESeverityNULL, ESeveritySCBreak, cVal, lineNo,curResource.RHFileName,""); + } + } + else + { + // add issue tyechange + string bType = baseStruct.structName + "::" + baseStruct.members.at(bInner).elementName; + string cType = curStruct.members.at(cInner).elementType; + int lineNo = curStruct.members.at(cInner).lineNo; + report.addIssue(baseResource.RHFileName, bType, EIssueIdentityStructMember, EIssueTypeChangeInType, + ESeverityNULL, ESeveritySCBreak, cType, lineNo,curResource.RHFileName,""); + } + + break; + + }// memeber name matched + }// loop thru all curr struct member + + if( memFound == false) + { + // Add Issue Member not found // baseStruct.members.at(bInner) + string bMember = baseStruct.structName + "::" + baseStruct.members.at(bInner).elementName; + int lineNo = curStruct.lineNo; + report.addIssue(baseResource.RHFileName, bMember, EIssueIdentityStructMember, EIssueTypeRemoval, + ESeverityNULL,ESeveritySCBreak, "", lineNo,curResource.RHFileName,""); + } + }// loop base struct member + + }// struct name match + }// loop curr structs + + if( structFound == false ) + { + //Add issue struct not found + report.addIssue(baseResource.RHFileName, baseStruct.structName, EIssueIdentityStruct, EIssueTypeRemoval, + ESeverityNULL, ESeveritySCBreak, "", 0,curResource.RHFileName,""); + } + }//loop base structs + + // --------------Enum Comparison ------------ + vectorbaseEnumNameEmptyMemberList; + vectorcurEnumNameEmptyMemberList; + vector bEnumList; + vector cEnumList; + + for( int b = 0; b < base_enum_no; b++) + { + baseEnum = baseResource.enumList.at(b); + + if(baseEnum.enumName.size()<=0) + { + for(int k = 0; k < (int)baseEnum.enums.size(); k++) + { + baseEnumNameEmptyMemberList.push_back(baseEnum.enums.at(k)); + } + } + else + { + bEnumList.push_back(baseEnum); + } + } + + for( int c = 0; c < cur_enum_no; c++) + { + curEnum = curResource.enumList.at(c); + + if(curEnum.enumName.size()<=0) + { + for(int k = 0; k < (int)curEnum.enums.size(); k++) + { + curEnumNameEmptyMemberList.push_back(curEnum.enums.at(k)); + } + } + else + { + cEnumList.push_back(curEnum); + } + } + + // Compare and report issue for enum list with name + for( int l = 0; l < (int) bEnumList.size(); l++) + { + baseEnum = bEnumList.at(l); + bool enumFound = false; + + for( int m = 0; m < (int)cEnumList.size(); m++ ) + { + curEnum = cEnumList.at(m); + if ( baseEnum.enumName == curEnum.enumName ) + { + int bMemNo = (int)baseEnum.enums.size(); + int cMemNo = (int)curEnum.enums.size(); + + enumFound = true; + + for ( int outer = 0; outer < bMemNo; outer++ ) + { + bool enumMemFound = false; + for( int inner = 0; inner < cMemNo; inner++ ) + { + if(baseEnum.enums.at(outer).enumMemName == curEnum.enums.at(inner).enumMemName ) + { + enumMemFound = true; + // member name found + if(baseEnum.enums.at(outer).enumVal.size() > 0 ) + { + if (baseEnum.enums.at(outer).enumVal != curEnum.enums.at(inner).enumVal ) + { + //add issue Member value changed + string baseEnumVal = baseEnum.enumName +"::" + baseEnum.enums.at(outer).enumMemName; + string curEnumVal = curEnum.enums.at(inner).enumVal; + int lineNo = curEnum.enums.at(inner).lineNo; + + report.addIssue(baseResource.RHFileName, baseEnumVal, EIssueIdentityEnumerationValue, EIssueTypeChangeInInitialisation, + ESeverityNULL, ESeveritySCBreak, curEnumVal, lineNo,curResource.RHFileName,""); + } + } + break; + } + } // loop cur mems + + if ( enumMemFound == false) + { + // Add Enum Member Missing + string bMemName = baseEnum.enumName +"::" + baseEnum.enums.at(outer).enumMemName; + int lineNo = curEnum.lineNo; + report.addIssue(baseResource.RHFileName, bMemName, EIssueIdentityEnumerationValue, EIssueTypeRemoval, + ESeverityNULL, ESeveritySCBreak, "", lineNo,curResource.RHFileName,""); + + } + }// loop base mems + + break; + }// enum name matched + }// loop cur enums + + if (enumFound == false ) + { + // Enum List missing + string bEnum = baseEnum.enumName; + string cEnum = curEnum.enumName; + report.addIssue(baseResource.RHFileName, bEnum, EIssueIdentityEnumerationValue, EIssueTypeRemoval, + ESeverityNULL, ESeveritySCBreak, cEnum, 0,curResource.RHFileName,""); + } + }//base enums + + // Now check for enum list with no enum name, in this case check member name and value + if(baseEnumNameEmptyMemberList.size() > 0) + { + EnumMember bEnumMem; + for(unsigned long i = 0; i < (unsigned long)baseEnumNameEmptyMemberList.size(); i++) + { + bEnumMem = baseEnumNameEmptyMemberList.at(i); + EnumMember cEnumMem; + bool enumMemFound = false; + for(unsigned long j = 0; j <(unsigned long) curEnumNameEmptyMemberList.size(); j++ ) + { + cEnumMem = curEnumNameEmptyMemberList.at(j); + if(bEnumMem.enumMemName == cEnumMem.enumMemName) + { + enumMemFound = true; + if(bEnumMem.enumVal != cEnumMem.enumVal ) + { + //add issue enum value changed + string baseEnumVal = "::" + bEnumMem.enumMemName; + string curEnumVal = cEnumMem.enumMemName; + int lineNo = cEnumMem.lineNo; + + report.addIssue(baseResource.RHFileName, baseEnumVal, EIssueIdentityEnumerationValue, EIssueTypeChangeInInitialisation, + ESeverityNULL, ESeveritySCBreak, curEnumVal, lineNo,curResource.RHFileName,""); + } + break; + } + } + if(enumMemFound == false) + { + // add issue enum mem mising + string bMemName = "::" + bEnumMem.enumMemName; + report.addIssue(baseResource.RHFileName, bMemName, EIssueIdentityEnumerationValue, EIssueTypeRemoval, + ESeverityNULL, ESeveritySCBreak, "", 0,curResource.RHFileName,""); + } + } + } + + + // --------------------- Macro Comparision -------------- + + for (int p = 0; p < base_macro_no; p++ ) + { + bool macroFound = false; + baseMacro = baseResource.macroList.at(p); + for (int q = 0; q < cur_macro_no; q++ ) + { + curMacro = curResource.macroList.at(q); + if(baseMacro.macroName == curMacro.macroName ) + { // check Macro value + macroFound = true; + if(baseMacro.macroVal != curMacro.macroVal ) + { + //add issue macro value mismatch + report.addIssue(baseResource.RHFileName, baseMacro.macroName, EIssueIdentityMacro, EIssueTypeChange, + ESeverityNULL, ESeveritySCBreak, curMacro.macroVal, curMacro.lineNo,curResource.RHFileName,""); + } + break; // macro name matched + } + + } + + if (macroFound == false ) + { + // add issue macro not found + report.addIssue(baseResource.RHFileName, baseMacro.macroName, EIssueIdentityMacro, EIssueTypeRemoval, + ESeverityNULL, ESeveritySCBreak, "", 0,curResource.RHFileName,""); + } + } + + + +} +