apicompatanamdw/compatanalysercmd/headeranalyser/src/Analyser.cpp
changeset 0 638b9c697799
child 3 ebe3f8f03b59
equal deleted inserted replaced
-1:000000000000 0:638b9c697799
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "CmdGlobals.h"
       
    20 #ifdef __WIN__
       
    21 #pragma warning(disable:4786)
       
    22 #endif
       
    23 #include <time.h>
       
    24 #include <map>
       
    25 #include <list>
       
    26 #include <algorithm>
       
    27 #include <assert.h>
       
    28 #include <fstream>
       
    29 #include <stdlib.h>
       
    30 #include <boost/thread.hpp>
       
    31 #include <boost/bind.hpp>
       
    32 
       
    33 #ifdef __WIN__
       
    34 #include <io.h>
       
    35 #include <direct.h>
       
    36 #include <windows.h>
       
    37 #else
       
    38 #include <unistd.h>
       
    39 #endif
       
    40 #include "Analyser.h"
       
    41 #include "CPPParser.h"
       
    42 #include "CommandLine.h"
       
    43 #include "CommandFile.h"
       
    44 #include "BBCFileUtils.h"
       
    45 #include "HAException.h"
       
    46 #include "BBCAnalyser.h"
       
    47 #include "AnalyserParams.h"
       
    48 #include "MacroAnalyser.h"
       
    49 #include "Utils.h"
       
    50 #include "PlatformData.h"
       
    51 
       
    52 const int KMaxDirLength=1024;
       
    53 
       
    54 boost::mutex m;
       
    55 boost::mutex::scoped_lock lock(m,false); //for synchronizing creation & destruction of threads in gHeaderThreads
       
    56 
       
    57 boost::thread_group gComponentThreads;
       
    58 boost::thread_group gHeaderThreads;
       
    59 
       
    60 boost::thread* gpComponentThreads[MAX_THREAD_COUNT];
       
    61 boost::thread* gpHeaderThreads[MAX_THREAD_COUNT2];
       
    62 
       
    63 XERCES_CPP_NAMESPACE_USE
       
    64 typedef pair<string,string> stringpair;
       
    65 //the total number of files to be processed
       
    66 static int _total_files = 0;
       
    67 //the number of files that have been processed
       
    68 static int _current_files = 0;
       
    69 
       
    70 // make sure globbing is turned off when GCC is used
       
    71 int _CRT_glob = 0;
       
    72 
       
    73 // Fill the headers having API Info in global vector, so that report generator can access it.
       
    74 vector<pair<string,stringpair> > HeaderInfoList; // vector<pair< headerfile name, pair<API name, API category>>>
       
    75 
       
    76 // ----------------------------------------------------------------------------
       
    77 // Analyser::Analyser
       
    78 // Constructor
       
    79 // ----------------------------------------------------------------------------
       
    80 //
       
    81 Analyser::Analyser(char** args, int argc) : iCPPParser(NULL)
       
    82 {
       
    83     iCmdLine = new CommandLine(args, argc);
       
    84     iUseBaselinePlatformData = false;   
       
    85     iUseCurrentPlatformData = false;
       
    86     iUseForcedHeaders = true;
       
    87     iBasePlatformData = 0;
       
    88     iProductPlatformData = 0;
       
    89 }
       
    90 
       
    91 // ----------------------------------------------------------------------------
       
    92 // Analyser::Analyser
       
    93 // Constructor
       
    94 // ----------------------------------------------------------------------------
       
    95 //
       
    96 Analyser::Analyser()
       
    97 {
       
    98     
       
    99 }
       
   100 
       
   101 // ----------------------------------------------------------------------------
       
   102 // Analyser::Analyser
       
   103 // Destructor
       
   104 // ----------------------------------------------------------------------------
       
   105 //
       
   106 Analyser::~Analyser()
       
   107 {
       
   108     delete iCmdLine;
       
   109     iCmdLine = NULL;
       
   110     if (iCPPParser != NULL)
       
   111     {
       
   112         delete iCPPParser;
       
   113         iCPPParser = NULL;
       
   114     }
       
   115     if (iBasePlatformData)
       
   116     {
       
   117       delete iBasePlatformData;
       
   118       iBasePlatformData = 0;
       
   119     }
       
   120     if ( iProductPlatformData)
       
   121     {
       
   122       delete iProductPlatformData;
       
   123       iProductPlatformData = 0;
       
   124     }
       
   125 }
       
   126 
       
   127 // ----------------------------------------------------------------------------
       
   128 // Analyser::validateHeaders
       
   129 // validates header for include guards
       
   130 // ----------------------------------------------------------------------------
       
   131 //
       
   132 void Analyser::validateHeaders(vector<pair<string, string> >& aFiles, vector<pair<string, string> >& aUnsuccessful)
       
   133 {
       
   134 	int count = 0;
       
   135 	string input;
       
   136 	string files[2];
       
   137 	bool exists[2];
       
   138 	string guard[2];
       
   139 	vector<string> guards[2];
       
   140 
       
   141 	vector< pair<string, string> >::iterator fileStart = aFiles.begin();
       
   142 	vector< pair<string, string> >::iterator fileEnd = aFiles.end();
       
   143 	//vector used to temporarily hold file pairs with include guards
       
   144 	vector< pair<string, string> > temp;
       
   145 	while(fileStart != fileEnd )
       
   146 	{
       
   147 		files[0] = fileStart->first;
       
   148 		files[1] = fileStart->second;
       
   149 		for(int i=0; i<2; i++)
       
   150 		{
       
   151 
       
   152 			//check for include guard in Base header
       
   153 			exists[i] = guardExists(files[i], guard[i]);
       
   154 		}
       
   155 		//if either Base or Current header in the PAIR do not have include guards
       
   156 		//add the file pair to RemovedFiles list.
       
   157 		if( !exists[0] || !exists[1] )
       
   158 			aUnsuccessful.push_back(*fileStart);
       
   159 		else 
       
   160 		{
       
   161 			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())
       
   162 			{
       
   163 				guards[0].push_back(guard[0]);
       
   164 				guards[1].push_back(guard[1]);
       
   165 				temp.push_back(*fileStart);			
       
   166 			}
       
   167 			else
       
   168 			{
       
   169 				aUnsuccessful.push_back(*fileStart);
       
   170 			}
       
   171 		}
       
   172 	
       
   173 		++fileStart;
       
   174 	}
       
   175 	guards[0].clear();
       
   176 	guards[1].clear();
       
   177 	aFiles.clear();
       
   178 	aFiles = temp;
       
   179 }
       
   180 
       
   181 // ----------------------------------------------------------------------------
       
   182 // Analyser::guardExists
       
   183 // guard Exists checs to see if the input file has include guards
       
   184 // ----------------------------------------------------------------------------
       
   185 //
       
   186 bool Analyser::guardExists(const string& aFile, string& aGuard)
       
   187 {
       
   188 	bool exists = false;
       
   189 	string guard("");
       
   190 	string input("");
       
   191 	string temp("");
       
   192 	//macro used in the #ifndef line
       
   193 	pair<string,string> macroOne;
       
   194 	//macro #defined subsequently
       
   195 	pair<string,string> macroTwo;
       
   196 	int linenum = 0;
       
   197 	//linenum containing the #ifndef statement
       
   198 	int ifndefline = 0;
       
   199 
       
   200 	ifstream fileRead(aFile.c_str(), ios::in);
       
   201 	if( !fileRead.is_open())
       
   202 		throw HAException("Header file does not exist");;
       
   203 	while( !fileRead.eof() )
       
   204 	{
       
   205 		linenum++;
       
   206 		temp = getLine(fileRead);
       
   207 		input = trimWhiteSpace(temp);
       
   208 		// Check if #ifndef are being used
       
   209 		// Get the MACRO string if they are present
       
   210 		if(input.substr(0,7) == "#ifndef") 
       
   211 		{
       
   212 			macroOne = MacroAnalyser::FindMacro(input);
       
   213 			ifndefline = linenum;
       
   214 		}
       
   215 		// checks for the usage of #if (!defined ...) in include guard defns
       
   216 		else if (input.substr(0,3) == "#if")
       
   217 		{
       
   218 			string tempstr("!defined");
       
   219 			//strip all braces from the Macro string
       
   220 			while(input.find("(") < input.length())
       
   221 			{
       
   222 				replaceChar(input,'(',' ');
       
   223 				replaceChar(input,')',' ');
       
   224 			}
       
   225 			//get the actual MACRO string after required temp modifications
       
   226 			string::size_type index = input.find(tempstr);
       
   227 			if (index == string::npos)
       
   228 			  continue;
       
   229 			index = index + tempstr.length();
       
   230 			tempstr = input.substr( index );
       
   231 			input = trimWhiteSpace(tempstr);
       
   232 			pair<string,string> temppair(input, "");
       
   233 			macroOne = temppair;
       
   234 			ifndefline = linenum;
       
   235 		}
       
   236 		// Check if #define is used 
       
   237 		else if (input.substr(0, 7) == "#define")
       
   238 		{
       
   239 			macroTwo = MacroAnalyser::FindMacro(input);
       
   240 			//if macro strings used in both #ifndef and #define are same
       
   241 			//consider that include guard exists
       
   242 			//also verify that #define follows #if
       
   243 			if( macroTwo.first == macroOne.first && macroTwo.second == macroOne.second && ifndefline < linenum )
       
   244 			{
       
   245 				exists = true;
       
   246 				aGuard = macroOne.first;
       
   247 			}
       
   248 			break;
       
   249 		}
       
   250 		// additional statement will be used for early termination of the loop
       
   251 		// in cases with no "include" guards
       
   252 		else if( input.substr(0, 8) == "#include") 
       
   253 		{
       
   254 			exists = false;
       
   255 			break;
       
   256 		}
       
   257 	}
       
   258 	fileRead.close();
       
   259 	return exists;
       
   260 }
       
   261 
       
   262 // ----------------------------------------------------------------------------
       
   263 // Analyser::readParameters
       
   264 // readParameters should be called so that first is called baseline command
       
   265 // and after that current command, otherwise it doesn't work
       
   266 // ----------------------------------------------------------------------------
       
   267 //
       
   268 void Analyser::readParameters(basetype type, list<pair<string, string> >& files, string& forcedheaders)
       
   269 {    
       
   270     string headerset;
       
   271     string dir;
       
   272     string file;
       
   273     string platform;
       
   274     string forcedheadersfile;
       
   275     string forcedheaders_file;
       
   276     string version;
       
   277     string versionstr;
       
   278     BBCFileUtils* fileUtils = NULL;
       
   279     static basetype first = type;
       
   280 
       
   281     if (first != EBase)
       
   282     {
       
   283         cout << "Error: Parameter read has been called in wrong order.";
       
   284         exit(3);
       
   285     }
       
   286 
       
   287     switch(type)
       
   288     {
       
   289     case EBase:
       
   290         dir = BASELINEDIR;
       
   291         file = BASELINE;
       
   292         platform = BASELINEPLAT;
       
   293         forcedheadersfile = BASEFORCEDHEADERSFILE;
       
   294         version = BASELINEVERSION;
       
   295         versionstr = "BASELINE";
       
   296         break;
       
   297     case ECurrent:
       
   298         dir = CURRENTDIR;
       
   299         file = CURRENT;
       
   300         platform = CURRENTPLAT;
       
   301         forcedheadersfile = CURRENTFORCEDHEADERSFILE;
       
   302         version = CURRENTVERSION;
       
   303         versionstr = "CURRENT";
       
   304         break;
       
   305     default:
       
   306         cout << "Error: Unknown type (not baseline, nor current).";
       
   307         exit(3);
       
   308     }
       
   309   
       
   310     // Query the baseline-related command line parameters
       
   311     // since validation has passed, none of these should really
       
   312     // cause an exception
       
   313     try
       
   314     {
       
   315         if( iParams.parameterExists(BASEPLATFORMDATA))
       
   316         {
       
   317             iUseBaselinePlatformData = true;
       
   318             string pfdir(BBCFileUtils::getFullPath(iParams.getParameter(BASEPLATFORMDATA)));
       
   319             if (!BBCFileUtils::isValidFilename(pfdir))
       
   320             {
       
   321                 throw HAException("Baseline platform data file '" + pfdir + "' is not valid.");
       
   322             }
       
   323             iParams.storeParameter(BASEPLATFORMDATA, pfdir);
       
   324         }
       
   325         if( iParams.parameterExists(CURRENTPLATFORMDATA))
       
   326         {
       
   327             iUseCurrentPlatformData = true;         
       
   328             string pfdir(BBCFileUtils::getFullPath(iParams.getParameter(CURRENTPLATFORMDATA)));
       
   329             if (!BBCFileUtils::isValidFilename(pfdir))
       
   330             {
       
   331                 throw HAException("Current platform data file '" + pfdir + "' is not valid.");
       
   332             }
       
   333             iParams.storeParameter(CURRENTPLATFORMDATA, pfdir);
       
   334         }
       
   335         if (iParams.parameterExists(TEMPDIR))
       
   336         {
       
   337             string tempdir(BBCFileUtils::getFullPath(iParams.getParameter(TEMPDIR)));
       
   338             iParams.storeParameter(TEMPDIR, tempdir);
       
   339             if (!BBCFileUtils::isValidDirectory(tempdir))
       
   340             {
       
   341                 throw HAException("Temporary directory '" + tempdir + "' is not valid directory.");
       
   342             }
       
   343         }
       
   344         if (iParams.parameterExists(REPORTFILE))
       
   345         {
       
   346             string reportfile(BBCFileUtils::getFullPath(iParams.getParameter(REPORTFILE)));
       
   347             iParams.storeParameter(REPORTFILE, reportfile);
       
   348             if (rightmostDirSeparatorIndex(reportfile) == reportfile.length() - 1 || BBCFileUtils::isValidDirectory(reportfile))
       
   349             {
       
   350                 throw HAException("No filename given for report file.");
       
   351             }
       
   352             string reportdir = reportfile.substr(0, rightmostDirSeparatorIndex(reportfile));
       
   353             
       
   354             if (reportdir.size() == ANALYSER_REPORT_DIR_SIZE)
       
   355             {
       
   356                 reportdir += DIR_SEPARATOR;
       
   357             }
       
   358             if (!BBCFileUtils::isValidDirectory(reportdir))
       
   359             {
       
   360                 throw HAException("Directory for report file is non-existent.");
       
   361             }
       
   362         }
       
   363         if (iParams.parameterExists(HEADERSET))
       
   364         {
       
   365             iHeaderSetInUse = true;
       
   366         }
       
   367 		if (iParams.parameterExists(USETHREAD))
       
   368         {
       
   369             iUseThread = true;
       
   370         }
       
   371         if (iParams.parameterExists(dir))
       
   372         {
       
   373             // START -- Support for multiple header directories
       
   374             // Validate the ; separated header paths and store them
       
   375             list<pair<string, string> > dirs = BBCFileUtils::extractFilenames(iParams.getParameter(dir));
       
   376             list<pair<string, string> >::iterator dirbegin = dirs.begin();
       
   377             string tempval = "";
       
   378         
       
   379             for(; dirbegin != dirs.end(); dirbegin++)
       
   380             {
       
   381                 if (dirbegin != dirs.begin())
       
   382                 {
       
   383                     tempval += ";";
       
   384                 }
       
   385                 string header = BBCFileUtils::getFullPath(dirbegin->first);
       
   386 
       
   387                if (header.length() != ANALYSER_HEADER_MAX_LENGTH && header.at(header.length() - 1) == DIR_SEPARATOR)
       
   388                 {
       
   389                     header.resize(header.length() - 1);
       
   390                 }
       
   391 
       
   392                 if (!BBCFileUtils::isValidDirectory(header))
       
   393                 {
       
   394                     string::size_type pos = rightmostDirSeparatorIndex(header);
       
   395                     string tempvar;
       
   396                     if (pos != header.length() - 1)
       
   397                     {
       
   398                         tempvar = header.substr(pos + 1);
       
   399                         header.resize(pos);
       
   400                     }
       
   401 
       
   402                     if (header.size() == ANALYSER_HEADER_SIZE)
       
   403                     {
       
   404                         header += DIR_SEPARATOR;
       
   405                     }
       
   406     
       
   407                     if (!BBCFileUtils::isValidDirectory(header) || tempvar.find_first_of("*?") == string::npos)
       
   408                     {
       
   409                         string errormsg;
       
   410                         errormsg = "Non-existent ";
       
   411                         if (type == EBase)
       
   412                         {
       
   413                             errormsg += "base";
       
   414                         } else
       
   415                         {
       
   416                             errormsg += "current";
       
   417                         }
       
   418                         errormsg += " directory '" + header + DIR_SEPARATOR + tempvar + "'.\n";
       
   419                         throw HAException(errormsg);
       
   420                     }
       
   421                 }
       
   422                 if (header.at(header.length() - 1) == DIR_SEPARATOR)
       
   423                 {
       
   424                     header.resize(header.length() - 1);
       
   425                 }
       
   426                 tempval += header;
       
   427             }
       
   428             iParams.storeParameter(dir, tempval);
       
   429             // END -- Support for multiple header directories
       
   430         }
       
   431         else
       
   432         {
       
   433             iParams.storeParameter(file, BBCFileUtils::getFullPath(iParams.getParameter(file)));
       
   434         }
       
   435         
       
   436         // Location of baseline's platform headers
       
   437         list<pair<string, string> > platformheaders = BBCFileUtils::extractFilenames(iParams.getParameter(platform));
       
   438         list<pair<string, string> >::iterator platformbegin = platformheaders.begin();
       
   439         string tempval = "";
       
   440         for(; platformbegin != platformheaders.end(); platformbegin++)
       
   441         {
       
   442             if (platformbegin != platformheaders.begin())
       
   443             {
       
   444                 tempval += ";";
       
   445             }
       
   446             string header = BBCFileUtils::getFullPath(platformbegin->first);
       
   447 
       
   448             if (header.length() != ANALYSER_HEADER_MAX_LENGTH && header.at(header.length() - 1) == DIR_SEPARATOR)
       
   449             {
       
   450                 header.resize(header.length() - 1);
       
   451             }
       
   452             
       
   453             tempval += header;
       
   454         }
       
   455         iParams.storeParameter(platform, tempval);
       
   456 
       
   457         // Location of forced headers file (containing full names of headers that 
       
   458         // will be included to preprocessing and processing phases, e.g. e32base.h)
       
   459         if (iParams.parameterExists(forcedheadersfile))
       
   460         {
       
   461             // START -- Support for multiple forced headers
       
   462             list<pair<string, string> > fheaders = BBCFileUtils::extractFilenames(iParams.getParameter(forcedheadersfile));
       
   463             list<pair<string, string> >::iterator fheadersbegin = fheaders.begin();
       
   464             string tempval = "";
       
   465             
       
   466             //for each forced header, get the full path before storing it
       
   467             for(; fheadersbegin != fheaders.end(); fheadersbegin++)
       
   468             {
       
   469                 if (fheadersbegin != fheaders.begin())
       
   470                 {
       
   471                     tempval += ";";
       
   472                 }
       
   473                 tempval += BBCFileUtils::getFullPath(fheadersbegin->first);
       
   474             }
       
   475             iParams.storeParameter(forcedheadersfile, tempval);
       
   476             forcedheaders = iParams.getParameter(forcedheadersfile);
       
   477             // END -- Support for multiple forced headers
       
   478         }
       
   479         
       
   480         if (!iParams.parameterExists(version))
       
   481         {
       
   482             iParams.storeParameter(version, versionstr);
       
   483         }
       
   484     } catch (HAException& e)
       
   485     {
       
   486         cout << "Error: "<<e.errorMessage()<<"\n";
       
   487         exit(2);
       
   488     }
       
   489 
       
   490     // Instantiate file utilities that generate the file lists based on 
       
   491     // commandline parameters. In this try/catch block, we're
       
   492     // handling the baseline files
       
   493     try
       
   494     {
       
   495         if (iParams.parameterExists(dir))
       
   496         {
       
   497             // baselinedir/currentdir commandline parameters given
       
   498             fileUtils = new BBCFileUtils(iParams.getParameter(dir));
       
   499             fileUtils->setTemp(iParams.getParameter(TEMPDIR));
       
   500             string wildcard;
       
   501             list<stringpair > sets;
       
   502             list<stringpair > discarddirs;
       
   503             list<stringpair > foundfiles;
       
   504             list<stringpair > completefilenames; // Filenames that are complete, i.e no wildcards used.
       
   505             vector<string> wildcardsinset;
       
   506             
       
   507             if (type == EBase)
       
   508             {                
       
   509                 // We are reading the parameters of the baseline platform               
       
   510                 
       
   511                 if(iHeaderSetInUse)
       
   512                 {
       
   513                     // the files to be analysed are defined using 'set' parameter.
       
   514                     sets = fileUtils->extractFilenames(iParams.getParameter(HEADERSET));   
       
   515                 }
       
   516                 else
       
   517                 {
       
   518                     // 'set' parameter is absent. Use default file types in the files to be analysed.
       
   519                     sets = fileUtils->extractFilenames(WILDCARD_DEFAULT);
       
   520                 }
       
   521                     
       
   522                 sets = canonicalizeFilename(sets);
       
   523                                 
       
   524                 for(list<stringpair >::iterator s = sets.begin(); s != sets.end(); ++s )
       
   525                 {
       
   526                     if( s->first.find_first_of("*?") != string::npos )
       
   527                     {
       
   528                         // Wildcard is used in filename.
       
   529                         std::string wc(s->first);
       
   530                         wildcardsinset.push_back(wc);
       
   531                         list<stringpair > tmpfiles(fileUtils->getFilesInDir(wc, ""));
       
   532                         files.insert(files.end(), tmpfiles.begin(), tmpfiles.end());
       
   533                     }                
       
   534                     else
       
   535                     {
       
   536                         completefilenames.push_back(*s);
       
   537                     }
       
   538                 }
       
   539                 
       
   540                 files.sort(LessStringPair);// Sort files 
       
   541                 files.unique(); // Remove duplicates
       
   542 
       
   543                 // Remove trailing directory separator from the filenames, that were found using the wildcard,
       
   544                 // to be able to build <code>foundfiles</code> list for later use.
       
   545                 list<stringpair> foundwithwildcard(files);
       
   546                 std::for_each(foundwithwildcard.begin(), foundwithwildcard.end(),RemoveTrailingDirSeparator<stringpair>());
       
   547 
       
   548                 // Find files given with complete filename
       
   549                 list<stringpair> tempcompletefiles(completefilenames);
       
   550                 list<stringpair > tmplist(fileUtils->getFilesInDir(tempcompletefiles, "",foundfiles));
       
   551 
       
   552                 // Add files found with wildcard to <code>foundfiles</code>
       
   553                 foundfiles.sort(LessStringPair);                
       
   554                 foundfiles.merge(foundwithwildcard, LessStringPair);
       
   555                 foundfiles.unique(); // Remove duplicates
       
   556 
       
   557                 // Merge all found files:
       
   558                 tmplist.sort( LessStringPair );                
       
   559                 files.merge(tmplist, LessStringPair);
       
   560                 files.unique(); // Remove duplicates                
       
   561                 if (iParams.parameterExists(DISCARDDIRS))
       
   562                 {
       
   563                     discarddirs = BBCFileUtils::extractFilenames(iParams.getParameter(DISCARDDIRS));
       
   564                 }
       
   565             } else if (type == ECurrent)
       
   566             {
       
   567                 // We are reading the parameters of the current platform 
       
   568                 // and the files to be analysed are defined using 'set' parameter.
       
   569                 wildcard = WILDCARD_ALLFILES;
       
   570                 files = fileUtils->getFilesInDir(wildcard, "");
       
   571                 if (iParams.parameterExists(DISCARDDIRS))
       
   572                 {
       
   573                     discarddirs = BBCFileUtils::extractFilenames(iParams.getParameter(DISCARDDIRS));
       
   574                 }
       
   575             } else
       
   576             {
       
   577                 // No 'set' parameter used
       
   578                 wildcard = iParams.getParameter(BASELINE);
       
   579                 files = fileUtils->getFilesInDir(wildcard, "");
       
   580                 if (iParams.parameterExists(DISCARDDIRS))
       
   581                 {
       
   582                     discarddirs = BBCFileUtils::extractFilenames(iParams.getParameter(DISCARDDIRS));
       
   583                 }
       
   584             }
       
   585             if (iParams.parameterExists(RECURSIVE))
       
   586             {
       
   587                 list<pair<string, string> > dirs = fileUtils->getDirsInDir("",discarddirs);
       
   588                 while(!dirs.empty())
       
   589                 {
       
   590                     string dir = dirs.front().first;
       
   591                     dirs.pop_front();
       
   592                     list<pair<string, string> > morefiles;
       
   593                     if (type == EBase)
       
   594                     {
       
   595                         // Read files which were given as complete names in the -set parameter:
       
   596                         morefiles = fileUtils->getFilesInDir(completefilenames, dir,foundfiles);
       
   597 
       
   598                         // Read files which were given as wildcards in the -set parameter:
       
   599                         for( vector<string>::iterator wc = wildcardsinset.begin(); wc != wildcardsinset.end(); ++wc)
       
   600                         {
       
   601                             list<pair<string, string> > tmpfiles = fileUtils->getFilesInDir(*wc, dir);
       
   602                             morefiles.insert(morefiles.end(), tmpfiles.begin(), tmpfiles.end());
       
   603                         }
       
   604                     } 
       
   605                     else
       
   606                     {
       
   607                         morefiles = fileUtils->getFilesInDir(wildcard, dir);
       
   608                     }
       
   609                     morefiles.sort(LessStringPair);
       
   610                     morefiles.unique();
       
   611                     list<pair<string, string> >::const_iterator file = morefiles.begin();
       
   612                     list<pair<string, string> >::const_iterator fileend = morefiles.end();
       
   613                     for(; file != fileend; file++)
       
   614                     {
       
   615                         files.push_back(*file);
       
   616                     }
       
   617                     list<pair<string, string> > moredirs = fileUtils->getDirsInDir(dir,discarddirs);
       
   618                     while(!moredirs.empty())
       
   619                     {
       
   620                         pair<string, string> direntry = moredirs.front();
       
   621                         moredirs.pop_front();
       
   622                         dirs.push_back(direntry);
       
   623                     }
       
   624                 }
       
   625             }
       
   626             if (type == EBase)
       
   627             {
       
   628                 list<pair<string, string> > notfound;
       
   629                 diffs(files, sets, notfound);
       
   630                 if (!notfound.empty())
       
   631                 {
       
   632                     string errormessage = "Following files could not be found in baseline:\n";
       
   633                     list<pair<string, string> >::iterator file = notfound.begin();
       
   634                     list<pair<string, string> >::iterator fileend = notfound.end();
       
   635                     for(; file != fileend; file++)
       
   636                     {
       
   637                         errormessage += file->first;
       
   638                         errormessage += "\n";
       
   639                     }
       
   640 					//this case has now been redefined as a input error that can be handled
       
   641 					//the file is removed from the list to be analysed, and execution continues
       
   642                     //throw HAException(errormessage);
       
   643                 }
       
   644             }
       
   645         }
       
   646         else
       
   647         {
       
   648             // baseline/current commandline parameters given
       
   649             string file_val = iParams.getParameter(file);
       
   650             string f = getFilenameWithoutDir(file_val);
       
   651             iParams.storeParameter(file, f);
       
   652             file_val.resize(file_val.length() - f.length() - 1);
       
   653             iParams.storeParameter(dir, file_val);
       
   654             fileUtils = new BBCFileUtils(iParams.getParameter(dir));
       
   655             fileUtils->setTemp(iParams.getParameter(TEMPDIR));
       
   656             pair<string, string> tempvar(f, toLowerCaseWin(f));
       
   657             files.push_back(tempvar);
       
   658         }
       
   659     } catch (HAException& e)
       
   660     {
       
   661         // something went wrong. Make a clean exit
       
   662         if (fileUtils != NULL)
       
   663         {
       
   664             delete fileUtils;
       
   665             fileUtils = NULL;
       
   666         }
       
   667         cout << "Error: " << e.errorMessage() << "\n";
       
   668         exit(2);
       
   669     }
       
   670     
       
   671     delete fileUtils;
       
   672     fileUtils = NULL;
       
   673 
       
   674 }
       
   675 
       
   676 // ----------------------------------------------------------------------------
       
   677 // Analyser::processParameters
       
   678 // processParameters
       
   679 // ----------------------------------------------------------------------------
       
   680 //
       
   681 int Analyser::processParameters()
       
   682 {
       
   683     string err = "";
       
   684 
       
   685     // Validate command-line parameters.
       
   686     // If they are not sound and complete, break off with an error message.
       
   687     try
       
   688     {
       
   689         err = iCmdLine->validateParameters();
       
   690     } catch (HAException& e)
       
   691     {
       
   692         cout << "ERROR: Bad parameters, quitting. Type ha -? for help.\n";
       
   693         cout << e.errorMessage();
       
   694         cout << "\n";
       
   695         return (2);
       
   696     }
       
   697 
       
   698     if (err.size() > 0)
       
   699     {
       
   700         cout << "ERROR: Parameter validation fail. Type ha -? for help.\n";
       
   701         cout << err << "\n";
       
   702         return (2);
       
   703     }
       
   704     
       
   705     map<string, string> params = iCmdLine->getParameters();
       
   706     map<string, string>::iterator begin = params.begin();
       
   707     map<string, string>::iterator end = params.end();
       
   708     while (begin != end)
       
   709     {
       
   710         iParams.storeParameter((*begin).first,(*begin).second, true);
       
   711         ++begin;
       
   712     }
       
   713 
       
   714     // readParameters should be called so that first is called baseline command
       
   715     // and after that current command, otherwise it doesn't work
       
   716 
       
   717     // Read base dependent parameters
       
   718     readParameters(EBase, iFiles, iForcedBaselineHeaders);
       
   719     // ..and current ones
       
   720     readParameters(ECurrent, iFiles2, iForcedCurrentHeaders);
       
   721 
       
   722 #if defined(_DEBUG) || defined(DEBUG)
       
   723     if(iParams.parameterExists(COMMANDLINETEST))
       
   724     {
       
   725         map<string, string> params = iParams.getGivenParameters();
       
   726         map<string, string>::iterator begin = params.begin();
       
   727         map<string, string>::iterator end = params.end();
       
   728         while (begin != end)
       
   729         {
       
   730             cout << "Param: '" << (*begin).first << "' Value: '" << (*begin).second << "'\n";
       
   731             begin++;
       
   732         }
       
   733         exit(100);
       
   734     }
       
   735 #endif
       
   736 
       
   737     return 0;
       
   738 }
       
   739 
       
   740 // ----------------------------------------------------------------------------
       
   741 // Analyser::analyseTrees
       
   742 // processParameters
       
   743 // ----------------------------------------------------------------------------
       
   744 //
       
   745 int Analyser::analyseTrees(DOMNode* baseline, DOMNode* current, const list< pair<string,string> >& files, ReportGenerator& report)
       
   746 {
       
   747     int ret = 0;
       
   748     //print progress information for files which have compiled
       
   749     list< pair<string,string> >::const_iterator begin = files.begin();
       
   750     list< pair<string,string> >::const_iterator end = files.end();
       
   751     
       
   752     while (begin != end)
       
   753     {
       
   754         _current_files++;
       
   755 		cout << "\nAnalysing files (" << _current_files << "/" << _total_files << "): " << (*begin).first <<" => "<< (*begin).second << endl;
       
   756         begin++;
       
   757     }
       
   758 
       
   759     BBCAnalyser analyser(report);
       
   760     ret =  analyser.analyseTrees(baseline, current, files, iMacroFiles);
       
   761 
       
   762     return ret;
       
   763 }
       
   764 
       
   765 // ----------------------------------------------------------------------------
       
   766 // Analyser::handleBundlesizeParam
       
   767 // Get bundlesize value
       
   768 // ----------------------------------------------------------------------------
       
   769 //
       
   770 int Analyser::handleBundlesizeParam()
       
   771 {
       
   772     int bundlesize=1; 
       
   773 
       
   774     if (iParams.parameterExists(BUNDLESIZE))
       
   775     {
       
   776         string tempstr = iParams.getParameter(BUNDLESIZE);
       
   777         if (tempstr.length() > 0)
       
   778         {
       
   779             bundlesize = atoi(tempstr.c_str());
       
   780             if (bundlesize < 1)
       
   781             {
       
   782                 bundlesize = 1;
       
   783             } 
       
   784             else if (bundlesize > MAX_BUNDLESIZE)
       
   785             {
       
   786                 bundlesize = MAX_BUNDLESIZE;                
       
   787             }
       
   788         }
       
   789     }
       
   790 
       
   791     if (bundlesize >= BUNDLESIZE_WARNING)
       
   792     {
       
   793     cout << "Note: Processing in large bundles, this may have a negative "
       
   794          << "performance impact and/or produce unwanted artifacts.\n";
       
   795     }
       
   796     return bundlesize;
       
   797 }
       
   798 
       
   799 // ----------------------------------------------------------------------------
       
   800 // Analyser::getReplaceParam
       
   801 // Get Replace parameter value
       
   802 // ----------------------------------------------------------------------------
       
   803 //
       
   804 string Analyser::getReplaceParam()
       
   805 {
       
   806     string replace;
       
   807     // File renames
       
   808     if (iParams.parameterExists(FILEREPLACE))
       
   809     {
       
   810         replace = iParams.getParameter(FILEREPLACE);
       
   811     } else
       
   812     {
       
   813         replace = "";
       
   814     }
       
   815 
       
   816     return replace;
       
   817 }
       
   818 
       
   819 
       
   820 
       
   821 PlatformHeaders::iterator FindHeaderPair(const string& ID, PlatformHeaders& pfHeaders)
       
   822 {
       
   823     for( PlatformHeaders::iterator i = pfHeaders.begin(); i != pfHeaders.end(); ++i )
       
   824     {
       
   825         if( i->first->ID() == ID )
       
   826         {
       
   827             return i;
       
   828         }
       
   829     }
       
   830     return pfHeaders.end();
       
   831 }
       
   832 // ----------------------------------------------------------------------------
       
   833 // Analyzes one component at a time.
       
   834 // 
       
   835 // 
       
   836 // ----------------------------------------------------------------------------
       
   837 //
       
   838 void Analyser::AnalyzePlatforms(PlatformHeaders& pfHeaders, PlatformHeaders& unsuccessfulHdrs, ReportGenerator& report, int& issues, bool createThread)
       
   839 {
       
   840 	string epocRoot("epoc32");
       
   841 	epocRoot += DIR_SEPARATOR + string("include"); 
       
   842 	// START -- Support for multiple header directories       
       
   843 	list<pair<string, bool> > baseEpocRoot = BBCFileUtils::MergeDirs(iParams.getParameter(BASELINEDIR), epocRoot);
       
   844 	list<pair<string, bool> > currEpocRoot = BBCFileUtils::MergeDirs(iParams.getParameter(CURRENTDIR), epocRoot);
       
   845 	// END -- Support for multiple header directories
       
   846 	for( PlatformHeaders::iterator pfHdr = pfHeaders.begin(); pfHdr != pfHeaders.end(); ++pfHdr )
       
   847 	{        
       
   848 		if( pfHdr->first->Status() == Header::HDR_STATUS_TO_BE_ANALYZED /*|| pfHdr->first->Status() == Header::HDR_STATUS_INVALID*/)
       
   849 		{
       
   850 			stringvector baseIncPaths;  // This contains include paths needed to compile baseline headers
       
   851 			stringvector currIncPaths;  // This contains include paths needed to compile product headers
       
   852 
       
   853 			baseIncPaths.clear();
       
   854 			currIncPaths.clear();
       
   855 			
       
   856 			iBaseFilenames.clear();
       
   857 			iCurrFilenames.clear();
       
   858 			iBaseIncludes.clear();
       
   859 			iCurrIncludes.clear();
       
   860 			iInvalidFiles.clear();
       
   861 
       
   862 			// All headers in the (baseline platform) component:
       
   863 			FileList& baseCmpHeaders = pfHdr->first->GetComponent()->Headers();             
       
   864 			iBaseFilenames.reserve(baseCmpHeaders.size());
       
   865 			iCurrFilenames.reserve(baseCmpHeaders.size());
       
   866 
       
   867 			// Make sure that the epoc32/include directory is always in include paths:
       
   868 			// START -- Support for multiple header directories
       
   869 			list<pair<string, bool> >::iterator iter1 = baseEpocRoot.begin();
       
   870 			for(; iter1 != baseEpocRoot.end(); iter1++)
       
   871 			{
       
   872 				if( iter1->second )
       
   873 				{
       
   874 					baseIncPaths.push_back(iter1->first);
       
   875 				}  
       
   876 			}
       
   877 			list<pair<string, bool> >::iterator iter2 = currEpocRoot.begin();
       
   878 			for(; iter2 != currEpocRoot.end(); iter2++)
       
   879 			{         
       
   880 				if( iter2->second )
       
   881 				{
       
   882 					currIncPaths.push_back(iter2->first);
       
   883 				}
       
   884 			}
       
   885 			// END -- Support for multiple header directories
       
   886 			
       
   887 			string forcedHeader;
       
   888 			char* base = new char[KMaxDirLength+1];
       
   889 			getcwd(base, KMaxDirLength);
       
   890 
       
   891 			vector< stringpair > tmpfiles;	
       
   892 			vector< stringpair > invalid;
       
   893 			// Loop all the headers that are in the same component:
       
   894 			for( FileList::iterator bH = baseCmpHeaders.begin(); bH != baseCmpHeaders.end(); ++bH )
       
   895 			{
       
   896 				Header* baseHdr = dynamic_cast<Header*>(*bH);
       
   897 							
       
   898 				PlatformHeaders::iterator pairIter = FindHeaderPair(baseHdr->ID(), pfHeaders);
       
   899 				if(pairIter != pfHeaders.end() && pairIter->second != 0)
       
   900 				{
       
   901 					// If analysing in bundle, get the headers to be anaysed to validate for include guard before addition to bundle.
       
   902 					if( (pfHeaders.size() > 1) && baseHdr && (baseHdr->Status() == Header::HDR_STATUS_TO_BE_ANALYZED) )
       
   903 					{
       
   904 						stringpair tmp(baseHdr->ID(), pairIter->second->ID());
       
   905 						tmpfiles.push_back(tmp);
       
   906 					}
       
   907 				}
       
   908 			}
       
   909 			
       
   910 			if(tmpfiles.size())
       
   911 			{
       
   912 				// If analysing in bundle, validate for include guard before addition to bundle.
       
   913 				validateHeaders(tmpfiles, invalid);
       
   914 				// Exclude "iInvalidFiles" from bundle analysis. Analyse them only singly. 
       
   915 				if( invalid.size() )
       
   916 				{
       
   917 					for( int i=0 ; i < invalid.size() ; i++ )
       
   918 					{
       
   919 					
       
   920 						PlatformHeaders::iterator pairIter = FindHeaderPair(invalid[i].first, pfHeaders);
       
   921 						//No need to check if the invalid file exists in pfHeaders, as it already done above. 
       
   922 						HeaderPair temp(pairIter->first, pairIter->second);
       
   923 						if(find(iInvalidFiles.begin(), iInvalidFiles.end(), temp) == iInvalidFiles.end())
       
   924 							iInvalidFiles.push_back(temp);
       
   925 						pairIter->first->SetStatus(Header::HDR_STATUS_INVALID);	
       
   926 					}
       
   927 				}
       
   928 			}
       
   929 
       
   930 			for( FileList::iterator bH = baseCmpHeaders.begin(); bH != baseCmpHeaders.end(); ++bH )
       
   931 			{
       
   932 				Header* baseHdr = dynamic_cast<Header*>(*bH);
       
   933 							
       
   934 				PlatformHeaders::iterator pairIter = FindHeaderPair(baseHdr->ID(), pfHeaders);
       
   935 				if(pairIter != pfHeaders.end() && pairIter->second != 0)
       
   936 				{
       
   937 					
       
   938 					// If the status is "to be analyzed" , get this header to the bundle too
       
   939 					if( baseHdr && 
       
   940 						(baseHdr->Status() == Header::HDR_STATUS_TO_BE_ANALYZED ))
       
   941 					{                       
       
   942 						// Find all additional includes that are needed in compilation of this header:   
       
   943 						const vector<string>& bIncs = iBasePlatformData->IncludesForHeader(baseHdr);                    
       
   944 						forcedHeader.clear();
       
   945 						forcedHeader = baseHdr->CachedForcedInclude();
       
   946 						// Find all include paths that are needed in compilation of this header:
       
   947 						const vector<string>& bPaths = iBasePlatformData->IncludePathsForHeader(baseHdr);                    
       
   948 
       
   949 						// Add include paths for baseline platform headers:   
       
   950 						// START -- Support for multiple header directories                                     
       
   951 						for( vector<string>::const_iterator i = bPaths.begin(); i != bPaths.end(); ++i )
       
   952 						{
       
   953 							list<pair<string, bool> > fullIncPath = BBCFileUtils::MergeDirs(iParams.getParameter(BASELINEDIR), *i);
       
   954 							list<pair<string, bool> >::iterator fulliterbegin = fullIncPath.begin();
       
   955 							for(; fulliterbegin != fullIncPath.end(); fulliterbegin++)
       
   956 							{
       
   957 								if( find(baseIncPaths.begin(), baseIncPaths.end(), fulliterbegin->first) == baseIncPaths.end() )
       
   958 								{
       
   959 									baseIncPaths.push_back(fulliterbegin->first);
       
   960 								}
       
   961 							}
       
   962 						}                    
       
   963 
       
   964 						// Add additional include directives to header list:
       
   965 						for( vector<string>::const_iterator i = bIncs.begin(); i != bIncs.end(); ++i )
       
   966 						{                          
       
   967 							// Make sure the header exists, because we don't want to generate new compilation errors...
       
   968 							bool exists = false;
       
   969 							// Test that header exists by merging the header name with include paths:
       
   970 							for( stringvector::iterator ip = baseIncPaths.begin(); ip != baseIncPaths.end(); ++ip )
       
   971 							{
       
   972 								list<pair<string, bool> > fullIncPath = BBCFileUtils::MergeDirs( *ip, *i );
       
   973 								list<pair<string, bool> >::iterator fulliterbegin = fullIncPath.begin();
       
   974 								for(; fulliterbegin != fullIncPath.end(); fulliterbegin++)
       
   975 								{                           
       
   976 									if( find(iBaseIncludes.begin(), iBaseIncludes.end(), fulliterbegin->first) == iBaseIncludes.end() )
       
   977 									{
       
   978 										if( BBCFileUtils::FileExists(fulliterbegin->first) )
       
   979 										{                                    
       
   980 											iBaseIncludes.push_back(fulliterbegin->first);
       
   981 											exists = true;
       
   982 											break; 
       
   983 										}                                
       
   984 									}
       
   985 								}
       
   986 							}
       
   987 							if( exists == false )
       
   988 							{
       
   989 								// Try to find the included header from the same directory than the header itself is:
       
   990 								list<pair<string, bool> > fullIncPath = 
       
   991 									BBCFileUtils::MergeDirs(iParams.getParameter(BASELINEDIR), baseHdr->Path() + DIR_SEPARATOR + *i);                            
       
   992 
       
   993 								list<pair<string, bool> >::iterator fulliterbegin = fullIncPath.begin();
       
   994 								for(; fulliterbegin != fullIncPath.end(); fulliterbegin++)
       
   995 								{
       
   996 									if( BBCFileUtils::FileExists(fulliterbegin->first) )
       
   997 									{                         
       
   998 										iBaseIncludes.push_back(fulliterbegin->first);
       
   999 									} 
       
  1000 								}                           
       
  1001 							}
       
  1002 						}
       
  1003 						// END -- Support for multiple header directories
       
  1004 
       
  1005 						// Add this header to the list of headers that are needed for compilation:                    
       
  1006 						if( find(iBaseIncludes.begin(), iBaseIncludes.end(), baseHdr->ID()) == iBaseIncludes.end())
       
  1007 						{
       
  1008 							iBaseIncludes.push_back(baseHdr->ID());
       
  1009 						}
       
  1010 
       
  1011 						// Add headers to the list of headers that are to be analyzed:										
       
  1012 						iBaseFilenames.push_back(baseHdr->ID());
       
  1013 						iCurrFilenames.push_back(pairIter->second->ID());
       
  1014 						baseHdr->SetStatus(Header::HDR_STATUS_READY);
       
  1015        
       
  1016 						forcedHeader = DIR_SEPARATOR + forcedHeader;
       
  1017 						forcedHeader = base + forcedHeader;
       
  1018 						if( BBCFileUtils::isValidFilename(forcedHeader) )
       
  1019 							if( find(iBaseIncludes.begin(), iBaseIncludes.end(), forcedHeader) == iBaseIncludes.end())
       
  1020 								iBaseIncludes.insert(iBaseIncludes.begin(),forcedHeader);
       
  1021               
       
  1022               
       
  1023 						// Then we need to find corresponding headers from the product (current) platform:                                        
       
  1024 					
       
  1025 						Header* currHeader = pairIter->second; //Current header
       
  1026 
       
  1027 						// Find additional includes and include paths for the current platform's header:
       
  1028 						const vector<string>& cIncs = iProductPlatformData->IncludesForHeader(currHeader, baseHdr);                        
       
  1029 						forcedHeader.clear();
       
  1030 						forcedHeader =currHeader->CachedForcedInclude(); 
       
  1031 						const vector<string>& cPaths =iProductPlatformData->IncludePathsForHeader(currHeader);                        
       
  1032 
       
  1033 						// Add include paths to the list, if it does not exist there yet:
       
  1034 						for( vector<string>::const_iterator i = cPaths.begin(); i != cPaths.end(); ++i )
       
  1035 						{
       
  1036 							// SART -- Support for multiple header directories
       
  1037 							list<pair<string, bool> > fullIncPath = BBCFileUtils::MergeDirs(iParams.getParameter(CURRENTDIR), *i);
       
  1038 							list<pair<string, bool> >::iterator fulliterbegin = fullIncPath.begin();
       
  1039 							for(; fulliterbegin != fullIncPath.end(); fulliterbegin++)
       
  1040 							{
       
  1041 								if( find(currIncPaths.begin(), currIncPaths.end(), fulliterbegin->first) == currIncPaths.end() )
       
  1042 								{
       
  1043 									currIncPaths.push_back(fulliterbegin->first);
       
  1044 								}
       
  1045 							}
       
  1046 							// END -- Support for multiple header directories
       
  1047 						}
       
  1048 
       
  1049 						// Add additional include directives to header list:
       
  1050 						for( vector<string>::const_iterator i = cIncs.begin(); i != cIncs.end(); ++i )
       
  1051 						{
       
  1052 							bool exists = false;
       
  1053 							// Make sure the header exists, because we don't want to generate new compilation errors...
       
  1054 							for( stringvector::iterator ip = currIncPaths.begin(); ip != currIncPaths.end(); ++ip )
       
  1055 							{
       
  1056 								// START -- Support for multiple header directories
       
  1057 								list<pair<string, bool> > fullIncPath = BBCFileUtils::MergeDirs( *ip, *i );
       
  1058 								list<pair<string, bool> >::iterator fulliterbegin = fullIncPath.begin();
       
  1059 								for(; fulliterbegin != fullIncPath.end(); fulliterbegin++)
       
  1060 								{
       
  1061 									if( find(iCurrIncludes.begin(), iCurrIncludes.end(), fulliterbegin->first) == iCurrIncludes.end() )
       
  1062 									{                                        
       
  1063 										if( BBCFileUtils::FileExists(fulliterbegin->first) )
       
  1064 										{
       
  1065 											iCurrIncludes.push_back(fulliterbegin->first);
       
  1066 											exists = true;
       
  1067 											break;
       
  1068 										}                                    
       
  1069 									}
       
  1070 								}
       
  1071 								// END -- Support for multiple header directories
       
  1072 							}
       
  1073 							if( exists == false )
       
  1074 							{
       
  1075 								// Try to find the included header from the same directory than the header itself is:
       
  1076 								// START -- Support for multiple header directories
       
  1077 								list<pair<string, bool> > fullIncPath = 
       
  1078 									BBCFileUtils::MergeDirs(iParams.getParameter(CURRENTDIR), currHeader->Path() + DIR_SEPARATOR + *i);                            
       
  1079 								list<pair<string, bool> >::iterator fulliterbegin = fullIncPath.begin();
       
  1080 								for(; fulliterbegin != fullIncPath.end(); fulliterbegin++)
       
  1081 								{
       
  1082 									if( BBCFileUtils::FileExists(fulliterbegin->first) )
       
  1083 									{                                
       
  1084 										iCurrIncludes.push_back(fulliterbegin->first);
       
  1085 									}
       
  1086 								}
       
  1087 								// END -- Support for multiple header directories
       
  1088 							}
       
  1089 						}
       
  1090 							// Add this header to the list:                        
       
  1091 						if( find(iCurrIncludes.begin(), iCurrIncludes.end(), currHeader->ID()) == iCurrIncludes.end())
       
  1092 						{
       
  1093 							iCurrIncludes.push_back(currHeader->ID());                            
       
  1094 						}
       
  1095 					
       
  1096 						forcedHeader = DIR_SEPARATOR + forcedHeader;
       
  1097 						forcedHeader = base + forcedHeader;
       
  1098 						if( BBCFileUtils::isValidFilename(forcedHeader) )
       
  1099 							if( find(iCurrIncludes.begin(), iCurrIncludes.end(), forcedHeader) == iCurrIncludes.end())
       
  1100 								iCurrIncludes.insert(iCurrIncludes.begin(),forcedHeader);
       
  1101 									
       
  1102 					}
       
  1103 				}
       
  1104 			}
       
  1105 			// Build include paths for parser objects:
       
  1106 			string bIP;
       
  1107 			for( stringvector::iterator i = baseIncPaths.begin(); i != baseIncPaths.end(); ++i )
       
  1108 			{
       
  1109 				if( i != baseIncPaths.begin() )
       
  1110 					bIP += ";";
       
  1111 
       
  1112 				bIP += *i;
       
  1113 			}
       
  1114 
       
  1115 			string cIP;
       
  1116 			for( stringvector::iterator i = currIncPaths.begin(); i != currIncPaths.end(); ++i )
       
  1117 			{
       
  1118 				if( i != currIncPaths.begin() )
       
  1119 					cIP += ";";
       
  1120 
       
  1121 				cIP += *i;
       
  1122 			}
       
  1123 
       
  1124 			// Construct parsers:
       
  1125 			auto_ptr<CPPParser> parser(new CPPParser(bIP));
       
  1126 			auto_ptr<CPPParser> parser2(new CPPParser(cIP));
       
  1127 
       
  1128 			// Set temp directories for parsers
       
  1129 			parser->setTemp(iParams.getParameter(TEMPDIR));
       
  1130 			parser2->setTemp(iParams.getParameter(TEMPDIR));
       
  1131 
       
  1132 			// Set forced headers 
       
  1133 			if(iUseForcedHeaders)
       
  1134 			{
       
  1135 				parser->setForcedHeaders(iForcedBaselineHeaders);
       
  1136 				parser2->setForcedHeaders(iForcedCurrentHeaders);
       
  1137 			}
       
  1138 
       
  1139 			if (createThread)
       
  1140 			{		
       
  1141 				//if the number of threads in this group has reached pre-defined max count, destroy all the threads in this group before creating one.
       
  1142 				//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
       
  1143 				if(gHeaderThreads.size() >= MAX_THREAD_COUNT)
       
  1144 				{
       
  1145 				
       
  1146 					gHeaderThreads.join_all();
       
  1147 					int size = gHeaderThreads.size();
       
  1148 					for(int i=0;i<size;i++)
       
  1149 					{
       
  1150 						gHeaderThreads.remove_thread(gpComponentThreads[i]);
       
  1151 						gpComponentThreads[i]->~thread();	
       
  1152 					}
       
  1153 				}
       
  1154 						
       
  1155 				//create a copy of the Analyser object for the new thread
       
  1156 				Analyser* obj = new Analyser();
       
  1157 				*obj = *this;
       
  1158 				int size = gHeaderThreads.size();
       
  1159 				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)));				
       
  1160 			}
       
  1161 			else //do not create different thread for the second time when AnalyzePlatforms is called recurssively
       
  1162 			{
       
  1163 				Wrapper(report, issues, *(parser.get()), *(parser2.get()), pfHeaders, unsuccessfulHdrs);	
       
  1164 			}		
       
  1165 		}
       
  1166 	}
       
  1167 	
       
  1168 }
       
  1169 
       
  1170 // ----------------------------------------------------------------------------
       
  1171 // Analyser::InitializePlatforms
       
  1172 // 
       
  1173 // 
       
  1174 // ----------------------------------------------------------------------------
       
  1175 //
       
  1176 void Analyser::InitializePlatforms(PlatformHeaders& pfHeaders, vector<pair<string, string> >& headers, 
       
  1177 								   vector<pair<string, string> >& excludeheaders, vector<pair<string, string> >& resourcevector)
       
  1178 {
       
  1179 	if( iBasePlatformData )
       
  1180 		delete iBasePlatformData;
       
  1181 	if( iProductPlatformData )
       
  1182 		delete iProductPlatformData;
       
  1183 
       
  1184 	iBasePlatformData = new PlatformData(iParams.getParameter(BASELINEVERSION),
       
  1185 		iParams.getParameter(BASELINEDIR));
       
  1186 	iProductPlatformData = new PlatformData(iParams.getParameter(CURRENTVERSION),
       
  1187 		iParams.getParameter(CURRENTDIR));
       
  1188 
       
  1189 	if( iUseBaselinePlatformData )
       
  1190 		iBasePlatformData->Initialize(iParams.getParameter(BASEPLATFORMDATA));
       
  1191 	if( iUseCurrentPlatformData )
       
  1192 		iProductPlatformData->Initialize(iParams.getParameter(CURRENTPLATFORMDATA));
       
  1193 
       
  1194 	vector<pair<string, string> > updatedHdrs;
       
  1195 	updatedHdrs.reserve(headers.size());    
       
  1196 
       
  1197 	// Mark the platform header objects with status 'HDR_STATUS_TO_BE_ANALYZED':
       
  1198 	vector<pair<string, string> >::const_iterator hdr = headers.begin();
       
  1199 
       
  1200 	for( ;hdr != headers.end(); ++hdr )
       
  1201 	{
       
  1202 		pair<string,stringpair> headerInfo;
       
  1203 		bool is_Resource = false;
       
  1204 		int loc = -1;
       
  1205 		pair<string,string> resource;
       
  1206 		Header* baseHdrObj = 0;
       
  1207 		Header* currHdrObj = 0;        
       
  1208 		string hdrTest(hdr->first);
       
  1209 		toLower(hdrTest);
       
  1210 
       
  1211 		// Check whether the header is a resource file. If, so add it to resource vector instead of pfheaders.
       
  1212 		if( (loc = int(hdrTest.find_last_of("."))) != string::npos &&
       
  1213 			hdrTest.substr(loc,string::npos) == RH_EXTENSION )
       
  1214 		{
       
  1215 			is_Resource = true;
       
  1216 			resource.first = hdrTest;
       
  1217 		}
       
  1218 		CFileMap::const_iterator bI = iBasePlatformData->HeadersById().find(hdrTest);
       
  1219 		if( bI != iBasePlatformData->HeadersById().end() )
       
  1220 		{
       
  1221 			baseHdrObj = dynamic_cast<Header*>((*bI).second);
       
  1222 		}
       
  1223 
       
  1224 		hdrTest = hdr->second;
       
  1225 		toLower(hdrTest);
       
  1226 		if(is_Resource == true)
       
  1227 		{
       
  1228 			resource.second = hdrTest;
       
  1229 			resourcevector.push_back(resource);
       
  1230 		}
       
  1231 
       
  1232 		CFileMap::const_iterator cI = iProductPlatformData->HeadersById().find(hdrTest);
       
  1233 		if( cI != iProductPlatformData->HeadersById().end() )
       
  1234 		{
       
  1235 			currHdrObj = dynamic_cast<Header*>((*cI).second);
       
  1236 		}
       
  1237 
       
  1238 		if(baseHdrObj && baseHdrObj->Status()== Header::HDR_STATUS_IGNORE )
       
  1239 		{
       
  1240 			excludeheaders.push_back(*hdr);
       
  1241 		}
       
  1242 		else if( baseHdrObj && currHdrObj )
       
  1243 		{
       
  1244 			if( is_Resource == false)
       
  1245 			{
       
  1246 				pfHeaders.push_back(HeaderPair(baseHdrObj, currHdrObj));
       
  1247 				baseHdrObj->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED);
       
  1248 				currHdrObj->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED);
       
  1249 			}
       
  1250 
       
  1251 			// get API info from current header
       
  1252 			if(currHdrObj->APIinfo().first.size() > 0)
       
  1253 			{
       
  1254 				headerInfo.first = currHdrObj->ID();
       
  1255 				headerInfo.second.first = currHdrObj->APIinfo().first; // API NAME
       
  1256 				headerInfo.second.second = currHdrObj->APIinfo().second; // API REL. CATEGORY
       
  1257 			}
       
  1258 
       
  1259 		}
       
  1260 		else
       
  1261 		{
       
  1262 			// get API info from base header
       
  1263 			if(baseHdrObj && baseHdrObj->APIinfo().first.size() > 0)
       
  1264 			{
       
  1265 				headerInfo.first = baseHdrObj->ID();
       
  1266 				headerInfo.second.first = baseHdrObj->APIinfo().first; // API NAME
       
  1267 				headerInfo.second.second = baseHdrObj->APIinfo().second; // API REL. CATEGORY
       
  1268 
       
  1269 			}
       
  1270 			// get API info from current header
       
  1271 			else if(currHdrObj && currHdrObj->APIinfo().first.size() > 0)
       
  1272 			{
       
  1273 				headerInfo.first = currHdrObj->ID();
       
  1274 				headerInfo.second.first = currHdrObj->APIinfo().first; // API NAME
       
  1275 				headerInfo.second.second = currHdrObj->APIinfo().second; // API REL. CATEGORY
       
  1276 			}
       
  1277 			// No info found from platform data, so use common include paths and 
       
  1278 			// other common compile-time parameters for this header:
       
  1279 			if( is_Resource == false)
       
  1280 			updatedHdrs.push_back(*hdr);
       
  1281 		}
       
  1282 		// Fill the headers having API Info in global vector, so that report generator can access it.
       
  1283 		if(headerInfo.first.size() > 0)
       
  1284 		{
       
  1285 			HeaderInfoList.push_back(headerInfo);
       
  1286 		}
       
  1287 	}
       
  1288 	headers = updatedHdrs;
       
  1289 }
       
  1290 
       
  1291 // ----------------------------------------------------------------------------
       
  1292 // Analyser::analyse
       
  1293 // Do the actual analyse of headers
       
  1294 // Create analysis report
       
  1295 // ----------------------------------------------------------------------------
       
  1296 //
       
  1297 int Analyser::analyse()
       
  1298 {
       
  1299 	// Local variable instantiation
       
  1300 	int ret = 0;
       
  1301 	iHeaderSetInUse = false;
       
  1302 	iUseForcedHeaders = true;
       
  1303 	iUseThread = false;
       
  1304 	string epocroot;
       
  1305 	int bundlesize = 1;
       
  1306 	unsigned int amount, amount2;
       
  1307 	iOnlySystemIncludeRequired = false;
       
  1308 	unsigned int excludedHeaderSize;
       
  1309 
       
  1310 	if (processParameters() == 2) return 2;
       
  1311 
       
  1312 	// Get the bundle size (as string) and convert it to an integer
       
  1313 	bundlesize = handleBundlesizeParam();
       
  1314 
       
  1315 	// Get replace parameter for file renaming
       
  1316 	string replace = getReplaceParam();
       
  1317 
       
  1318 	// Update the amount of found files
       
  1319 	amount = (unsigned int)iFiles.size();
       
  1320 	// Update the amount of found files
       
  1321 	amount2 = (unsigned int)iFiles2.size();
       
  1322 
       
  1323 	// Vector that holds the merge results and if it can't find baseline
       
  1324 	// file from current file it will put empty string as current file
       
  1325 	vector<pair<string,string> > mergeVector;
       
  1326 	mergeVector.reserve(amount);
       
  1327 
       
  1328 	// List holds files which were found in current but not in baseline.
       
  1329 	// Full path
       
  1330 	list<string> addedFiles;
       
  1331 
       
  1332 	// List holds files which were in baseline file list but
       
  1333 	// weren't in current file list, ie they were removed.
       
  1334 	// Contains full path with filename
       
  1335 	list<string> removedFiles;
       
  1336 	try
       
  1337 	{
       
  1338 		// Merges baseline and current files into one vector
       
  1339 		MergeFiles(iFiles, iFiles2, replace, mergeVector);
       
  1340 
       
  1341 		// Finds removed files
       
  1342 		fileDiffs(mergeVector, removedFiles);
       
  1343 	}
       
  1344 	catch (HAException e)
       
  1345 	{
       
  1346 		cout << "Error in processing file lists:\n" << e.errorMessage() << "\n";
       
  1347 		exit(4);
       
  1348 	}
       
  1349 
       
  1350 	// Mergemap now contains pairs of following type:
       
  1351 	// baseline complex filename (w/ absolute path) -> current version complex filename (w/ absolute path)
       
  1352 	_total_files = (unsigned int)mergeVector.size();
       
  1353 
       
  1354 	cout << "\nTotal baseline files: " << amount << "\nTotal current files: " << amount2 << "\nFile pairs found: "
       
  1355 		<< _total_files << "\n";
       
  1356 
       
  1357 	cout << "\nComparing " << _total_files << " matching files between\n " << iParams.getParameter(BASELINEDIR)
       
  1358 		<< " (Version " << iParams.getParameter(BASELINEVERSION) << ")\nand\n " << iParams.getParameter(CURRENTDIR)
       
  1359 		<< " (Version " << iParams.getParameter(CURRENTVERSION) << ")\n\n\n\n";
       
  1360 
       
  1361 	
       
  1362 	ReportGenerator report(iParams.getParameter(REPORTFILE));
       
  1363 	report.setCmdLineParms(iParams.getGivenParameters());
       
  1364 	report.setVersions(iParams.getParameter(BASELINEVERSION),iParams.getParameter(CURRENTVERSION));
       
  1365 	report.setXSL("BBCResults.xsl",false);
       
  1366 	
       
  1367 
       
  1368 	report.startReport();
       
  1369 	// start the timer
       
  1370 	time_t starttime;
       
  1371 	time_t endtime;
       
  1372 	starttime = time(NULL);
       
  1373 	
       
  1374 	PlatformHeaders pfHeaders;
       
  1375 	pfHeaders.reserve(mergeVector.size());
       
  1376 
       
  1377 	// Vector that holds the the headers those should be excluded from analysis.
       
  1378 	// These header files are mentioned in platform headers
       
  1379 	vector<pair<string,string> > excludeHeaders;
       
  1380 	excludeHeaders.reserve(mergeVector.size());
       
  1381 
       
  1382 
       
  1383 	// Headers that are found from platform data are inserted in pfHeaders.
       
  1384 	// Others are left to mergeVector.
       
  1385 	vector<pair<string, string> > resourceVector;
       
  1386 	resourceVector.reserve(mergeVector.size());
       
  1387 
       
  1388 	if(mergeVector.size() > 0 )
       
  1389 		InitializePlatforms(pfHeaders, mergeVector,excludeHeaders,resourceVector);
       
  1390 	excludedHeaderSize = int(excludeHeaders.size());	
       
  1391 
       
  1392 	endtime = time(NULL);
       
  1393 	time_t pfInitTime = endtime - starttime;
       
  1394 	time_t originalStartTime = starttime;
       
  1395 	starttime = time(NULL);
       
  1396 
       
  1397 	//Now analyse Resource Header RH files using text parser
       
  1398 	if(resourceVector.size()>0)
       
  1399 		ParseAndCompareResourceFiles(resourceVector, report);
       
  1400 
       
  1401 	// Process each removed filename from removedMap
       
  1402 	list<string>::iterator removedbegin = removedFiles.begin();
       
  1403 	list<string>::iterator removedend = removedFiles.end();
       
  1404 	for(; removedbegin != removedend; removedbegin++)
       
  1405 	{
       
  1406 		string filename = *removedbegin;
       
  1407 		report.addIssue(filename, "", EIssueIdentityFile, EIssueTypeRemoval, ESeverityBBCBreak, ESeveritySCBreak, "", 0, "","");
       
  1408 	}
       
  1409 
       
  1410 	int issues = 0;
       
  1411 	PlatformHeaders unsuccessfulHeaders;
       
  1412 	vector<pair<string, string> > unsuccessfulHeaderNames;
       
  1413 	vector<pair<string, string> > platformUnsuccessfulHeaderNames;
       
  1414 	int compErrors = 0;
       
  1415 
       
  1416 	//validate if the headers have include guards,
       
  1417 	//move ones without guards for individual compilation
       
  1418 	validateHeaders(mergeVector, unsuccessfulHeaderNames);
       
  1419 
       
  1420 	boost::thread_group mainThreads;
       
  1421 	int mergeVectorCompErrs = 0;
       
  1422 	int unsuccessfulCompErrs = 0;
       
  1423 	int platformUnsuccessfulCompErrs = 0;
       
  1424 
       
  1425 	// Analyse headers that were not found from platform data:	
       
  1426 	if( mergeVector.size() > 0 )
       
  1427 	{
       
  1428 		//create copy of Analyser object for the new thread
       
  1429 			Analyser* obj1=new Analyser();
       
  1430 			*obj1=*this;
       
  1431 			//analyse mergeVector in different thread
       
  1432 			mainThreads.create_thread(boost::bind(&Analyser::AnalyseHeaders,obj1,boost::ref(mergeVector),bundlesize,boost::ref(report),boost::ref(issues),boost::ref(mergeVectorCompErrs)));
       
  1433 	}
       
  1434 	
       
  1435 	// Compile unsuccessful headers one by one, because it is unlikely that they
       
  1436 	// will be compiled successfully here either:
       
  1437 	if( unsuccessfulHeaderNames.size() > 0 )
       
  1438 	{
       
  1439 		//create copy of Analyser object for the new thread
       
  1440 			Analyser* obj2 = new Analyser();
       
  1441 			*obj2=*this;
       
  1442 			//analyse unsuccessfulHeaderNames in different thread
       
  1443 			mainThreads.create_thread(boost::bind(&Analyser::AnalyseHeaders,obj2,boost::ref(unsuccessfulHeaderNames),1,boost::ref(report),boost::ref(issues),boost::ref(unsuccessfulCompErrs)));
       
  1444 	}
       
  1445 	
       
  1446 	if(pfHeaders.size() > 0)
       
  1447 	{
       
  1448 		AnalyzePlatforms(pfHeaders, unsuccessfulHeaders, report, issues, iUseThread);    
       
  1449 		if (iUseThread)
       
  1450 		{
       
  1451 			gHeaderThreads.join_all(); // wait for all threads in gHeaderThreads to complete
       
  1452 			gComponentThreads.join_all(); // wait for all threads in gComponentThreads to complete
       
  1453 
       
  1454 			//destroy the thredas in gHeaderThreads
       
  1455 			int size = gHeaderThreads.size();
       
  1456 			for (int i=0;i<size;i++)
       
  1457 			{
       
  1458 				gHeaderThreads.remove_thread(gpComponentThreads[i]);
       
  1459 				gpComponentThreads[i]->~thread();
       
  1460 			}
       
  1461 
       
  1462 			//destroy the thredas in gComponentThreads
       
  1463 			size=gComponentThreads.size();
       
  1464 			for (int i=0;i<size;i++)
       
  1465 			{
       
  1466 				gComponentThreads.remove_thread(gpHeaderThreads[i]);
       
  1467 				gpHeaderThreads[i]->~thread();
       
  1468 			}
       
  1469 		}
       
  1470 		
       
  1471 		for( PlatformHeaders::iterator i = unsuccessfulHeaders.begin(); i != unsuccessfulHeaders.end(); ++i )
       
  1472 		{  
       
  1473 			// Build list of headers that could not be compiled with platform data:
       
  1474 			platformUnsuccessfulHeaderNames.push_back(pair<string, string>(i->first->ID(), i->second->ID()));
       
  1475 		}
       
  1476 		
       
  1477 		if(platformUnsuccessfulHeaderNames.size() >0)
       
  1478 			AnalyseHeaders(platformUnsuccessfulHeaderNames, 1, report, issues, platformUnsuccessfulCompErrs); 
       
  1479 	}
       
  1480 	
       
  1481 	mainThreads.join_all(); // wait for all threads in mainThreads to complete
       
  1482 	compErrors += mergeVectorCompErrs + unsuccessfulCompErrs + platformUnsuccessfulCompErrs;
       
  1483 	report.finishReport();
       
  1484 
       
  1485 	// List number of files which had compilation errors and could not be compiled	
       
  1486 	if ( _current_files + excludedHeaderSize < _total_files )
       
  1487 		cout << "\n" << ( _total_files - (_current_files + excludedHeaderSize) ) <<"  files out of " << _total_files << " had some issues and could not be analysed.\n" << endl;
       
  1488 
       
  1489 	// Wrap up the run and print statistics
       
  1490 	unsigned int count = _total_files * 2;
       
  1491 
       
  1492 	endtime = time(NULL);
       
  1493 	time_t runningtime = endtime - starttime;
       
  1494 	double timedelta = 0.0;
       
  1495 	if (count > 0)
       
  1496 	{
       
  1497 		timedelta = (double)runningtime/(double)count;
       
  1498 	}
       
  1499 	cout << "\n";
       
  1500 	cout << "---------------------------------------------" << endl;
       
  1501 	cout << "Finished!" << endl;
       
  1502 	cout << "Files processed: " << count << endl;
       
  1503 	cout << "Total time: " << endtime - originalStartTime << " seconds." << endl;
       
  1504 	cout << "Platform data initialization time: " << pfInitTime << " seconds.\n";
       
  1505 	cout << "Compilation and analysis time: " << (long)runningtime << " seconds (Average: "<<timedelta<<" seconds per file).\n";
       
  1506 	cout << "Compilation errors: " << compErrors << endl;
       
  1507 	if(excludedHeaderSize > 0 )
       
  1508 	cout << "No of excluded headers: " << excludedHeaderSize << endl;
       
  1509 	cout << "---------------------------------------------" << endl;
       
  1510 
       
  1511 	if (iNotRemovedFiles.size() != 0)
       
  1512 	{
       
  1513 		cout << iNotRemovedFiles.size() << "\n";
       
  1514 		list<string> tempvar;
       
  1515 		list<string>::iterator removefile = iNotRemovedFiles.begin();
       
  1516 		list<string>::iterator fileend = iNotRemovedFiles.end();
       
  1517 		for(; removefile != fileend; removefile++)
       
  1518 		{
       
  1519 			CPPParser::RemoveFile(*removefile, tempvar);
       
  1520 		}
       
  1521 		if (tempvar.size() != 0)
       
  1522 		{
       
  1523 			iNotRemovedFiles = tempvar;
       
  1524 		} else
       
  1525 		{
       
  1526 			iNotRemovedFiles.clear();
       
  1527 		}
       
  1528 	}
       
  1529 
       
  1530 	if (ret == 0 && issues != 0)
       
  1531 	{
       
  1532 		ret = 1;
       
  1533 	}
       
  1534 	return ret;
       
  1535 }
       
  1536 
       
  1537 void Analyser::AnalyseHeaders(const vector<pair<string, string> >& headerList, int bundlesize, ReportGenerator& report, int& issues, int& compErrors)
       
  1538 {    
       
  1539 	unsigned int processedcount = 1;    
       
  1540 	stringvector basefilenames;
       
  1541 	stringvector curfilenames;
       
  1542 	vector<pair<string, string> > unsuccessfulHeaders;
       
  1543 	
       
  1544 	vector<pair<string, string> >::const_iterator fnmapiter = headerList.begin();
       
  1545 	while (fnmapiter != headerList.end())
       
  1546 	{
       
  1547 		// Push the pair's members to their respective vectors
       
  1548 		// for bundle handling
       
  1549 		basefilenames.push_back(fnmapiter->first);
       
  1550 		curfilenames.push_back(fnmapiter->second);
       
  1551 
       
  1552 		// If a bundle is full or the item is the last one to process,
       
  1553 		// we parse the current file lists to xml files
       
  1554 		if ((processedcount > 0 && (processedcount % bundlesize == 0)) || 
       
  1555 			processedcount == headerList.size())
       
  1556 		{
       
  1557 			if (!AnalyseBundle(basefilenames,curfilenames,report, issues))
       
  1558 			{
       
  1559 				//If there where parsing errors in a bundle, we try to compile each header
       
  1560 				// one by one
       
  1561 				stringvector::iterator basebegin = basefilenames.begin();
       
  1562 				stringvector::iterator baseend = basefilenames.end();
       
  1563 				stringvector::iterator currentbegin = curfilenames.begin();
       
  1564 
       
  1565 				if( basefilenames.size() == 1 ||
       
  1566 					bundlesize == 1 )
       
  1567 
       
  1568 				{
       
  1569 					if( basebegin != baseend )
       
  1570 					{
       
  1571 						if(!iUseForcedHeaders)
       
  1572 						{
       
  1573 							//Add compilation error to the report
       
  1574 							string compilationError = iCompErrTxt;
       
  1575 							report.addIssue((*basebegin), "", EIssueIdentityFile, EIssueTypeCompilationError, ESeverityBBCBreak, ESeveritySCBreak, "", 0,
       
  1576 								(*currentbegin),compilationError);
       
  1577 							issues++;						
       
  1578 						}
       
  1579 						else
       
  1580 							unsuccessfulHeaders.push_back(pair<string,string>(*basebegin,*currentbegin));
       
  1581 							
       
  1582 						compErrors++;
       
  1583 					}
       
  1584 				}
       
  1585 				else
       
  1586 				{
       
  1587 					while(basebegin != baseend )
       
  1588 					{
       
  1589 						stringvector basefilename;
       
  1590 						stringvector curfilename;
       
  1591 						basefilename.push_back(*basebegin);
       
  1592 						curfilename.push_back(*currentbegin);
       
  1593 						if (!AnalyseBundle(basefilename,curfilename,report, issues))
       
  1594 						{
       
  1595 							if(!iUseForcedHeaders)
       
  1596 							{
       
  1597 								//Add compilation error to the report						
       
  1598 								string compilationError = iCompErrTxt;
       
  1599 								report.addIssue((*basebegin), "", EIssueIdentityFile, EIssueTypeCompilationError, ESeverityBBCBreak, ESeveritySCBreak, "", 0,
       
  1600 									(*currentbegin),compilationError);
       
  1601 								issues++;								
       
  1602 							}
       
  1603 							else
       
  1604 								unsuccessfulHeaders.push_back(pair<string,string>(*basebegin,*currentbegin));
       
  1605 							
       
  1606 							compErrors++;
       
  1607 						}
       
  1608 						basebegin++;
       
  1609 						currentbegin++;
       
  1610 					}
       
  1611 				}
       
  1612 			}
       
  1613 			basefilenames.clear();
       
  1614 			curfilenames.clear();
       
  1615 		}
       
  1616 
       
  1617 		fnmapiter++;
       
  1618 		processedcount++;
       
  1619 	}
       
  1620 	
       
  1621 	if( compErrors > 0 && iUseForcedHeaders )
       
  1622 	{
       
  1623 		iUseForcedHeaders = false;
       
  1624 		issues = 0;
       
  1625 		compErrors = 0;   
       
  1626 		AnalyseHeaders(unsuccessfulHeaders, 1, report, issues, compErrors);
       
  1627 		iUseForcedHeaders = true;
       
  1628 	}
       
  1629 	
       
  1630 	if (iNotRemovedFiles.size() != 0)
       
  1631 	{            
       
  1632 		list<string> tempvar;
       
  1633 		list<string>::iterator removefile = iNotRemovedFiles.begin();
       
  1634 		list<string>::iterator fileend = iNotRemovedFiles.end();
       
  1635 		for(; removefile != fileend; removefile++)
       
  1636 		{
       
  1637 			CPPParser::RemoveFile(*removefile, tempvar);
       
  1638 		}
       
  1639 		if (tempvar.size() != 0)
       
  1640 		{
       
  1641 			iNotRemovedFiles = tempvar;
       
  1642 		} 
       
  1643 		else
       
  1644 		{
       
  1645 			iNotRemovedFiles.clear();
       
  1646 		}
       
  1647 	} 
       
  1648 	
       
  1649 }
       
  1650 
       
  1651 // ----------------------------------------------------------------------------
       
  1652 // Analyser::AnalyseBundle
       
  1653 // ----------------------------------------------------------------------------
       
  1654 //
       
  1655 //bool Analyser::AnalyseBundle(const stringvector& basefilenames, const stringvector& curfilenames, ReportGenerator& report, int& issues)
       
  1656 bool Analyser::AnalyseBundle(const stringvector& basefilenames, 
       
  1657                              const stringvector& curfilenames, 
       
  1658                              ReportGenerator& report, 
       
  1659                              int& issues,
       
  1660                              CPPParser* baseParser,
       
  1661                              CPPParser* currParser,
       
  1662                              stringvector* basecompileset,
       
  1663                              stringvector* currcompileset)
       
  1664 {
       
  1665 	auto_ptr<CPPParser> baseAutoPtr;
       
  1666 	auto_ptr<CPPParser> currAutoPtr;
       
  1667 	CPPParser* parser  = 0;
       
  1668 	CPPParser* parser2 = 0;
       
  1669 
       
  1670 	if( baseParser )
       
  1671 	{
       
  1672 		// This function does not own the pointer, so no auto_ptr used here.
       
  1673 		parser = baseParser;
       
  1674 	}
       
  1675 	else
       
  1676 	{
       
  1677 		parser = new CPPParser(iParams.getParameter(BASELINEPLAT));
       
  1678 		// Set temp directory for parser
       
  1679 		parser->setTemp(iParams.getParameter(TEMPDIR));
       
  1680 		// Set forced headers
       
  1681 		if(iUseForcedHeaders)
       
  1682 		parser->setForcedHeaders(iForcedBaselineHeaders);
       
  1683 		// Wrap allocated memory to an auto_ptr to get it deallocated properly.
       
  1684 		baseAutoPtr.reset(parser);                                  
       
  1685 	}
       
  1686 	if( currParser )
       
  1687 	{
       
  1688 		// This function does not own the pointer, so no auto_ptr used here.
       
  1689 		parser2 = currParser;        
       
  1690 	}
       
  1691 	else
       
  1692 	{
       
  1693 		parser2 = new CPPParser(iParams.getParameter(CURRENTPLAT));
       
  1694 		// Set temp directory for parser
       
  1695 		parser2->setTemp(iParams.getParameter(TEMPDIR));
       
  1696 		// Set forced headers
       
  1697 		if(iUseForcedHeaders)
       
  1698 		parser2->setForcedHeaders(iForcedCurrentHeaders);
       
  1699 		// Wrap allocated memory to an auto_ptr to get it deallocated properly.
       
  1700 		currAutoPtr.reset(parser2);
       
  1701 	}
       
  1702 
       
  1703 	try 
       
  1704 	{
       
  1705 		// Parse the filename vectors into XML and eventually into a DOM format
       
  1706 		DOMNode* root = 0;
       
  1707 		DOMNode* root2 = 0;
       
  1708 		if(basecompileset && basecompileset->size() != 0 )
       
  1709 		{
       
  1710 			root = parser->parse(*basecompileset, "base", iParams.getParameter(BASELINEDIR), iNotRemovedFiles);
       
  1711 		}
       
  1712 		else
       
  1713 		{
       
  1714 			root = parser->parse(basefilenames, "base", iParams.getParameter(BASELINEDIR), iNotRemovedFiles);
       
  1715 		}
       
  1716 		if(currcompileset && currcompileset->size() != 0 )
       
  1717 		{
       
  1718 			root2 = parser2->parse(*currcompileset, "current", iParams.getParameter(CURRENTDIR), iNotRemovedFiles);
       
  1719 		}
       
  1720 		else
       
  1721 		{
       
  1722 			root2 = parser2->parse(curfilenames, "current", iParams.getParameter(CURRENTDIR), iNotRemovedFiles);
       
  1723 		}
       
  1724 
       
  1725 		MacroAnalyser macros(parser->getMacroFilename(), parser2->getMacroFilename(), basefilenames, curfilenames);
       
  1726 
       
  1727 		macros.Analyse(iMacroFiles);
       
  1728 
       
  1729 #if !defined(_DEBUG) && !defined(DEBUG)
       
  1730 		parser->RemoveFile(parser->getMacroFilename(), iNotRemovedFiles);
       
  1731 		parser2->RemoveFile(parser2->getMacroFilename(), iNotRemovedFiles);
       
  1732 		parser->RemoveFile(parser->getCompErrFile(), iNotRemovedFiles);
       
  1733 		parser2->RemoveFile(parser2->getCompErrFile(), iNotRemovedFiles);
       
  1734 #endif
       
  1735 		// Merged macros
       
  1736 		//
       
  1737 		list<pair<string,string> > mergedfiles;
       
  1738 		stringvector::const_iterator basebegin = basefilenames.begin();
       
  1739 		stringvector::const_iterator baseend = basefilenames.end();
       
  1740 		stringvector::const_iterator currentbegin = curfilenames.begin();
       
  1741 		while(basebegin != baseend)
       
  1742 		{
       
  1743 			mergedfiles.push_back(pair<string,string>(*basebegin,*currentbegin));
       
  1744 			basebegin++;
       
  1745 			currentbegin++;
       
  1746 		}
       
  1747 		if(mergedfiles.size() > 0)
       
  1748 		{
       
  1749 			issues += analyseTrees(root, root2,mergedfiles,report);
       
  1750 		}
       
  1751 
       
  1752 		// Duplicated macros
       
  1753 		//
       
  1754 		// Base duplicates
       
  1755 		map<string, vector<pair<string,string> > >& duplicatedMacros = macros.getBaseDuplicates();
       
  1756 		map<string, vector<pair<string,string> > >::iterator duplicatedbegin = duplicatedMacros.begin();
       
  1757 		map<string, vector<pair<string,string> > >::iterator duplicatedend = duplicatedMacros.end();
       
  1758 		for(; duplicatedbegin != duplicatedend; duplicatedbegin++)
       
  1759 		{
       
  1760 			string filename = duplicatedbegin->first;
       
  1761 			// Process each duplicated macro from duplicatedMacros
       
  1762 			vector<pair<string,string> >::iterator duplicatedbegin2 = duplicatedbegin->second.begin();
       
  1763 			vector<pair<string,string> >::iterator duplicatedend2 = duplicatedbegin->second.end();
       
  1764 			for(; duplicatedbegin2 != duplicatedend2; duplicatedbegin2++)
       
  1765 			{
       
  1766 				string macroname = duplicatedbegin2->first;
       
  1767 				int lineNo = atoi(duplicatedbegin2->second.c_str());
       
  1768 				report.addIssue(filename, macroname, EIssueIdentityMacro, EIssueTypeNotAnalysed, ESeverityInformative, ESeveritySCInformative, "", lineNo, "", "");
       
  1769 				issues++;
       
  1770 			}
       
  1771 		}
       
  1772 
       
  1773 		// Current
       
  1774 		map<string, vector<pair<string,string> > >& currDuplicatedMacros = macros.getCurrentDuplicates();
       
  1775 		duplicatedbegin = currDuplicatedMacros.begin();
       
  1776 		duplicatedend = currDuplicatedMacros.end();
       
  1777 		for(; duplicatedbegin != duplicatedend; duplicatedbegin++)
       
  1778 		{
       
  1779 			string filename = duplicatedbegin->first;
       
  1780 			// Process each duplicated macro from duplicatedMacros
       
  1781 			vector<pair<string,string> >::iterator duplicatedbegin2 = duplicatedbegin->second.begin();
       
  1782 			vector<pair<string,string> >::iterator duplicatedend2 = duplicatedbegin->second.end();
       
  1783 			for(; duplicatedbegin2 != duplicatedend2; duplicatedbegin2++)
       
  1784 			{
       
  1785 				string macroname = duplicatedbegin2->first;
       
  1786 				int lineNo = atoi(duplicatedbegin2->second.c_str());
       
  1787 				report.addIssue("", macroname, EIssueIdentityMacro, EIssueTypeNotAnalysed, ESeverityInformative, ESeveritySCInformative, "", lineNo, filename, "");
       
  1788 				issues++;
       
  1789 			}
       
  1790 		}
       
  1791 
       
  1792 		// Removed macros
       
  1793 		//
       
  1794 		map<string, TChange<list<pair<string,string> > > >& removedMacros = macros.getRemoved();
       
  1795 		map<string, TChange<list<pair<string,string> > > >::iterator removedbegin = removedMacros.begin();
       
  1796 		map<string, TChange<list<pair<string,string> > > >::iterator removedend = removedMacros.end();
       
  1797 		for(; removedbegin != removedend; removedbegin++)
       
  1798 		{
       
  1799 			string basefilename = removedbegin->second.GetBase();
       
  1800 			string currentfilename = removedbegin->second.GetCurrent();
       
  1801 			// Process each removed macro from removedMacros
       
  1802 			list<pair<string,string> >::iterator removedbegin2 = removedbegin->second.GetValue().begin();
       
  1803 			list<pair<string,string> >::iterator removedend2 = removedbegin->second.GetValue().end();
       
  1804 			for(; removedbegin2 != removedend2; removedbegin2++)
       
  1805 			{
       
  1806 				string macroname = removedbegin2->first;
       
  1807 				//int lineNo = atoi(removedbegin2->second.c_str());
       
  1808 				// No need to pass the line no in removed case.
       
  1809 				report.addIssue(basefilename, macroname, EIssueIdentityMacro, EIssueTypeRemoval, ESeverityPossibleBBCBreak, ESeveritySCBreak, "", 0, currentfilename, "");
       
  1810 				issues++;
       
  1811 			}
       
  1812 		}
       
  1813 
       
  1814 		// Changed macros
       
  1815 		//
       
  1816 		map<string, TChange<map<string, pair<pair<string,string>,string> > > >& changedMacros = macros.getChanged();
       
  1817 		map<string, TChange<map<string, pair<pair<string,string>,string> > > >::iterator changedbegin = changedMacros.begin();
       
  1818 		map<string, TChange<map<string, pair<pair<string,string>,string> > > >::iterator changedend = changedMacros.end();
       
  1819 		for(; changedbegin != changedend; changedbegin++)
       
  1820 		{
       
  1821 			string basefilename = changedbegin->second.GetBase();
       
  1822 			string currentfilename = changedbegin->second.GetCurrent();
       
  1823 			// Process each changed macro from changedMacros
       
  1824 			map<string, pair<pair<string,string>,string> >::iterator changedbegin2 = changedbegin->second.GetValue().begin();
       
  1825 			map<string, pair<pair<string,string>,string> >::iterator changedend2 = changedbegin->second.GetValue().end();
       
  1826 			for(; changedbegin2 != changedend2; changedbegin2++)
       
  1827 			{
       
  1828 				string macroname = changedbegin2->first;
       
  1829 				string newcode = changedbegin2->second.first.second;
       
  1830 				int lineNo = atoi(changedbegin2->second.second.c_str());
       
  1831 				report.addIssue(basefilename, macroname, EIssueIdentityMacro, EIssueTypeChange, ESeverityPossibleBBCBreak, ESeveritySCNULL, newcode, lineNo, currentfilename, "");
       
  1832 				issues++;
       
  1833 			}
       
  1834 		}
       
  1835 
       
  1836 		
       
  1837 		//clear the last set of files with macros
       
  1838 		iMacroFiles.clear();
       
  1839 	} catch (HAException e)
       
  1840 	{
       
  1841 #if !defined(_DEBUG) && !defined(DEBUG)
       
  1842 		parser->RemoveFile(parser->getMacroFilename(), iNotRemovedFiles);
       
  1843 		parser2->RemoveFile(parser2->getMacroFilename(), iNotRemovedFiles);
       
  1844 #endif
       
  1845 
       
  1846 		//header has failed compilation with gccxml. get the compilation error text.
       
  1847 		if (parser2->getCompErrFile()!="")
       
  1848 		{
       
  1849 			iCompErrTxt = BBCFileUtils::getCompilationError(parser2->getCompErrFile());
       
  1850 			if (iCompErrTxt == "")
       
  1851 				iCompErrTxt = BBCFileUtils::getCompilationError(parser->getCompErrFile());
       
  1852 		}
       
  1853 		else 
       
  1854 		{
       
  1855 			if(parser->getCompErrFile()!="")
       
  1856 				iCompErrTxt = BBCFileUtils::getCompilationError(parser->getCompErrFile());
       
  1857 		}
       
  1858 #if !defined(_DEBUG) && !defined(DEBUG)
       
  1859 		parser->RemoveFile(parser->getCompErrFile(), iNotRemovedFiles);
       
  1860 		parser2->RemoveFile(parser2->getCompErrFile(), iNotRemovedFiles);
       
  1861 #endif
       
  1862 
       
  1863 		
       
  1864 		//delete parser;
       
  1865 		//delete parser2;
       
  1866 		return false;
       
  1867 	}
       
  1868 	//delete parser;
       
  1869 	//delete parser2;
       
  1870 	return true;
       
  1871 }
       
  1872 
       
  1873 
       
  1874 // ----------------------------------------------------------------------------
       
  1875 // Analyser::processFileReplaces
       
  1876 // Process the file replaces
       
  1877 // ----------------------------------------------------------------------------
       
  1878 //
       
  1879 pair<string, string> Analyser::processFileReplaces(pair<string, string>& aFile, const stringmap& aReplaceMap, list<pair<string, string> >& aCurrentFiles)
       
  1880 {
       
  1881     string searched(aFile.second);
       
  1882     pair<string, string>  replacement(aFile);
       
  1883     // If there are items on replace map, then apply the
       
  1884     // replaces when necessary
       
  1885     if (aReplaceMap.size() > 0)
       
  1886     {
       
  1887         StringMapIterC fileMapIter = aReplaceMap.find(searched);
       
  1888         if (fileMapIter != aReplaceMap.end())
       
  1889         {
       
  1890             string file = fileMapIter->second;
       
  1891             list<pair<string, string> >::const_iterator filereplace = FindFromList(toLowerCaseWin(file), aCurrentFiles, ERightValue, compareFiles);
       
  1892             if (filereplace != aCurrentFiles.end())
       
  1893             {
       
  1894                 replacement = *filereplace;
       
  1895             }
       
  1896         }
       
  1897     }
       
  1898 
       
  1899     return replacement;
       
  1900 }
       
  1901 
       
  1902 
       
  1903 // ----------------------------------------------------------------------------
       
  1904 // Analyser::createReplaceMap
       
  1905 //
       
  1906 // ----------------------------------------------------------------------------
       
  1907 //
       
  1908 void Analyser::createReplaceMap(const string& aReplaceList, stringmap& aReplaceMap)
       
  1909 {
       
  1910     string originalfilename("");
       
  1911     string replacementfilename("");
       
  1912     string* name = &originalfilename;
       
  1913     bool original = true;
       
  1914     bool isstr = false;
       
  1915     for (size_t i = 0; i < aReplaceList.length(); i++)
       
  1916     {
       
  1917         char ch = aReplaceList.at(i);
       
  1918         if (ch == ' ' && isstr == false)
       
  1919         {
       
  1920             if (original == true)
       
  1921             {
       
  1922                 original = false;
       
  1923                 name = &replacementfilename;
       
  1924             }
       
  1925             else
       
  1926             {
       
  1927                 // Pair separator found. 
       
  1928                 // Store the pair (original, replacement)
       
  1929                 stringpair mappair(toLowerCaseWin(originalfilename), toLowerCaseWin(replacementfilename));
       
  1930                 aReplaceMap.insert(mappair);
       
  1931                 replacementfilename.resize(0);
       
  1932                 originalfilename.resize(0);
       
  1933 
       
  1934                 original = true;
       
  1935                 name = &originalfilename;
       
  1936             }
       
  1937         } else if (ch == '"')
       
  1938         {
       
  1939             if (isstr == true)
       
  1940             {
       
  1941                 isstr = false;
       
  1942             } else
       
  1943             {
       
  1944                 isstr = true;
       
  1945             }
       
  1946         } else
       
  1947         {
       
  1948             *name += ch;
       
  1949         }
       
  1950     }
       
  1951     if (original == true)
       
  1952     {
       
  1953         throw HAException("Syntax error: There has been given file name to replace but not file name for replace.");
       
  1954     }
       
  1955     if (originalfilename.length() > 0 && replacementfilename.length() > 0)
       
  1956     {
       
  1957         // Store the last pair in replacement list
       
  1958         stringpair mappair(toLowerCaseWin(originalfilename), toLowerCaseWin(replacementfilename));
       
  1959         aReplaceMap.insert(mappair);
       
  1960     }
       
  1961 }
       
  1962 
       
  1963 // ----------------------------------------------------------------------------
       
  1964 // Analyser::fileDiffs
       
  1965 // ----------------------------------------------------------------------------
       
  1966 //
       
  1967 void Analyser::fileDiffs(vector<pair<string, string> >& aFiles, list<string>& aMismatches)
       
  1968 {
       
  1969     vector<pair<string, string> > ret;
       
  1970     ret.reserve(aFiles.size());
       
  1971     vector<pair<string, string> >::iterator file = aFiles.begin();
       
  1972     vector<pair<string, string> >::iterator fileend = aFiles.end();
       
  1973     
       
  1974     for(;file != fileend; file++)
       
  1975     {
       
  1976         // START -- Support for multiple header directories
       
  1977         list<pair<string, string> > basedirs = BBCFileUtils::extractFilenames(iParams.getParameter(BASELINEDIR));
       
  1978         list<pair<string, string> >::iterator basedirbegin = basedirs.begin();
       
  1979         string basedir;
       
  1980         string basefile;
       
  1981         for(; basedirbegin != basedirs.end(); basedirbegin++)
       
  1982         {
       
  1983             // Find the base dir from the list of base dirs
       
  1984             basedir = basedirbegin->first;
       
  1985             basefile = basedir + DIR_SEPARATOR + file->first;
       
  1986             if (BBCFileUtils::FileExists(basefile))
       
  1987                 break;
       
  1988         }  
       
  1989     
       
  1990         list<pair<string, string> > curdirs = BBCFileUtils::extractFilenames(iParams.getParameter(CURRENTDIR));
       
  1991         list<pair<string, string> >::iterator curdirbegin = curdirs.begin();
       
  1992         string curdir;
       
  1993         string curfile;
       
  1994         for(; curdirbegin != curdirs.end(); curdirbegin++)
       
  1995         {
       
  1996             // Find the current dir from the list of current dirs
       
  1997             curdir = curdirbegin->first;
       
  1998             curfile = curdir + DIR_SEPARATOR + file->second;
       
  1999             if (BBCFileUtils::FileExists(curfile))
       
  2000                 break;
       
  2001         } 
       
  2002         // END -- Support for multiple header directories
       
  2003          
       
  2004         if (file->second == "")
       
  2005         {
       
  2006             // We hadn't find matching file from current list so we add it to removed list
       
  2007             aMismatches.push_back(basefile);
       
  2008         } else
       
  2009         {
       
  2010             pair<string, string> tempvar(basefile, curfile);
       
  2011             ret.push_back(tempvar);
       
  2012         }
       
  2013     }
       
  2014     aFiles = ret;
       
  2015 }
       
  2016 
       
  2017 // ----------------------------------------------------------------------------
       
  2018 // Analyser::getFilenameWithoutDir
       
  2019 // Return the file part of the filename, eg. retuns the rightmost part of
       
  2020 // the given string, up to a "\" // or "/" separator.
       
  2021 // ----------------------------------------------------------------------------
       
  2022 //
       
  2023 string Analyser::getFilenameWithoutDir(const string& aFilename)
       
  2024 {
       
  2025     string ret = aFilename;
       
  2026     string::size_type idx = rightmostDirSeparatorIndex(aFilename);
       
  2027     if (idx != string::npos)
       
  2028     {
       
  2029         ret = aFilename.substr(idx+1, aFilename.length() - idx);
       
  2030     }
       
  2031     return ret;
       
  2032 }
       
  2033 
       
  2034 // ----------------------------------------------------------------------------
       
  2035 // Analyser::testFileAvailability
       
  2036 // ----------------------------------------------------------------------------
       
  2037 //
       
  2038 #if 0
       
  2039 void Analyser::testFileAvailability(stringmap map)
       
  2040 {
       
  2041     stringmap::iterator begin = map.begin();
       
  2042     stringmap::iterator end = map.end();
       
  2043 
       
  2044     for(; begin!= end; begin++)
       
  2045     {
       
  2046         string file = (*begin).first;
       
  2047 
       
  2048         int isValid = ACCESS(file.c_str(), 0);
       
  2049         if (isValid == -1)
       
  2050         {
       
  2051             throw HAException("File: \"" + file + "\" not found");
       
  2052         }
       
  2053         
       
  2054         file = (*begin).second;
       
  2055 
       
  2056         isValid = ACCESS(file.c_str(), 0);
       
  2057         if (isValid == -1)
       
  2058         {
       
  2059             throw HAException("File: \"" + file + "\" not found");
       
  2060         }
       
  2061     }
       
  2062 }
       
  2063 
       
  2064 #endif
       
  2065 
       
  2066 // ----------------------------------------------------------------------------
       
  2067 // Analyser::MergeFiles
       
  2068 // ----------------------------------------------------------------------------
       
  2069 //
       
  2070 void Analyser::MergeFiles(const list<pair<string, string> >& aBasefiles, list<pair<string, string> >& aCurrentfiles,
       
  2071                           const string& aReplaceList, vector<pair<string, string> >& aMatches)
       
  2072 {
       
  2073     size_t asdf = aBasefiles.size();
       
  2074     list<pair<string, string> >::const_iterator baseiter = aBasefiles.begin();
       
  2075     list<pair<string, string> >::const_iterator baseend = aBasefiles.end();
       
  2076     list<pair<string, string> > removedcurrentfiles;
       
  2077     list<pair<string, string> > mismatches;
       
  2078     if (!iParams.givenParameter(BASELINE))
       
  2079     {
       
  2080         stringmap replaceMap;
       
  2081         if (aReplaceList.length() > 0)
       
  2082         {            
       
  2083             createReplaceMap(aReplaceList, replaceMap);         
       
  2084             stringmap::iterator begin = replaceMap.begin();
       
  2085             stringmap::iterator end = replaceMap.end();
       
  2086         }                
       
  2087         for(; baseiter != baseend; baseiter++)
       
  2088         {            
       
  2089             pair<string, string> file = *baseiter;
       
  2090             file = processFileReplaces(file, replaceMap, aCurrentfiles);
       
  2091             pair<string,string> tempvar;
       
  2092 			//compareWholeString will be set to true, 
       
  2093 			//only if the file name with whole path of current file need to compare with base file.
       
  2094 			//else by default will always be set to false.
       
  2095             list<pair<string, string> >::iterator current = FindFromList(file.second, aCurrentfiles, ERightValue, compareFiles, false,true);
       
  2096             if (current != aCurrentfiles.end())
       
  2097             {
       
  2098                 tempvar.first = baseiter->first.substr(1);
       
  2099                 tempvar.second = current->first.substr(1);
       
  2100                 aMatches.push_back(tempvar);
       
  2101                 removedcurrentfiles.push_back(*current);
       
  2102                 aCurrentfiles.erase(current);
       
  2103             } else
       
  2104             {
       
  2105                 current = FindFromList(file.second, removedcurrentfiles, ERightValue, compareFiles, false);
       
  2106                 if (current != removedcurrentfiles.end())
       
  2107                 {
       
  2108                     tempvar.first = baseiter->first.substr(1);
       
  2109                     tempvar.second = current->first.substr(1);
       
  2110                     aMatches.push_back(tempvar);
       
  2111                 } else
       
  2112                 {
       
  2113                     mismatches.push_back(file);
       
  2114                 }
       
  2115             }
       
  2116         }        
       
  2117         baseiter = mismatches.begin();
       
  2118         baseend = mismatches.end();        
       
  2119         for(; baseiter != baseend; baseiter++)
       
  2120         {
       
  2121             string filename = BBCFileUtils::StripPath(baseiter->second);
       
  2122             pair<string, string> file(filename, filename); // We don't need to put filename to lowercase as it's already in lowercase
       
  2123             file = processFileReplaces(file, replaceMap, aCurrentfiles);
       
  2124             string empty("");
       
  2125             pair<string,string> tempvar;
       
  2126             tempvar.first = baseiter->first.substr(1);
       
  2127             list<pair<string, string> >::iterator current = FindFromList(file.second, aCurrentfiles, ERightValue, compareFiles);
       
  2128             if (current != aCurrentfiles.end())
       
  2129             {
       
  2130                 tempvar.second = current->first.substr(1);
       
  2131             } else
       
  2132             {
       
  2133                 tempvar.second = empty;
       
  2134             }
       
  2135             aMatches.push_back(tempvar);
       
  2136         }        
       
  2137     } else
       
  2138     {
       
  2139         // START -- Support for multiple header directories
       
  2140         list<pair<string, string> > basedirs = BBCFileUtils::extractFilenames(iParams.getParameter(BASELINEDIR));
       
  2141         list<pair<string, string> >::iterator basedirbegin = basedirs.begin();
       
  2142         bool  basefilefound = false;
       
  2143         string basefile;
       
  2144         for(; basedirbegin != basedirs.end(); basedirbegin++)
       
  2145         {
       
  2146             string basedir = basedirbegin->first;       
       
  2147             basefile = basedir + DIR_SEPARATOR + aBasefiles.front().first;
       
  2148 
       
  2149             if (ACCESS(basefile.c_str(), 0) != -1)
       
  2150             {
       
  2151                 basefilefound = true;
       
  2152                 break;
       
  2153             }
       
  2154       }
       
  2155         list<pair<string, string> > curdirs = BBCFileUtils::extractFilenames(iParams.getParameter(CURRENTDIR));
       
  2156         list<pair<string, string> >::iterator curdirbegin = curdirs.begin();
       
  2157         bool  curfilefound = false;
       
  2158         string curfile;
       
  2159         
       
  2160         for(; curdirbegin != curdirs.end(); curdirbegin++)
       
  2161         {
       
  2162             string curdir = curdirbegin->first;       
       
  2163             curfile = curdir + DIR_SEPARATOR + aBasefiles.front().first;
       
  2164             if (ACCESS(curfile.c_str(), 0) != -1)
       
  2165             {
       
  2166                 curfilefound = true;
       
  2167                 break;
       
  2168             }
       
  2169         }
       
  2170         if (!basefilefound )
       
  2171         {
       
  2172             throw HAException("File \"" + basefile + "\" not found");
       
  2173         }
       
  2174         if (!curfilefound)
       
  2175         {
       
  2176             throw HAException("File \"" + curfile + "\" not found");
       
  2177         }
       
  2178         pair<string,string> tempvar(aBasefiles.front().first, aCurrentfiles.front().first);
       
  2179         aMatches.push_back(tempvar);
       
  2180         // END -- Support for multiple header directories
       
  2181     }
       
  2182 }
       
  2183 
       
  2184 // ----------------------------------------------------------------------------
       
  2185 // AnalyserParams::diffs
       
  2186 //  	
       
  2187 // ----------------------------------------------------------------------------
       
  2188 //
       
  2189 void Analyser::diffs(   const list<pair<string, string> >& allfiles, 
       
  2190                         const list<pair<string, string> >& sets, 
       
  2191                         list<pair<string, string> >& result)
       
  2192 {
       
  2193     result = sets;
       
  2194     list<stringpair >::iterator setiter = result.begin();
       
  2195     while(setiter != result.end())
       
  2196     {
       
  2197         if( setiter->first.find_first_of("*?") != string::npos )
       
  2198             setiter = result.erase(setiter);
       
  2199         else
       
  2200             ++setiter;
       
  2201     }
       
  2202     
       
  2203     list<pair<string, string> >::const_iterator file = allfiles.begin();
       
  2204     list<pair<string, string> >::const_iterator fileend = allfiles.end();
       
  2205     for(; file != fileend; file++)
       
  2206     {    
       
  2207         list<pair<string, string> >::iterator set = 
       
  2208             FindFromList(file->second, result, ERightValue);
       
  2209         if (set == result.end())
       
  2210         {
       
  2211             set = FindFromList(file->second, result, ERightValue, compareFiles);
       
  2212         }
       
  2213         
       
  2214         if (set != result.end())
       
  2215         {
       
  2216             result.erase(set);
       
  2217         }
       
  2218     }
       
  2219     
       
  2220 }
       
  2221 
       
  2222 // ----------------------------------------------------------------------------
       
  2223 // AnalyserParams::canonicalizeFilename
       
  2224 // Get the actual name of a file. 
       
  2225 // ----------------------------------------------------------------------------
       
  2226 //
       
  2227 list<pair<string, string> > Analyser::canonicalizeFilename(list<pair<string, string> >& sets)
       
  2228 {
       
  2229     list<pair<string, string> > ret;
       
  2230     list<pair<string, string> >::iterator begin = sets.begin();
       
  2231     list<pair<string, string> >::iterator end = sets.end();
       
  2232     for(; begin != end; begin++)
       
  2233     {
       
  2234         if (begin->first.at(0) != DIR_SEPARATOR && begin->first.find(DIR_SEPARATOR) != string::npos)
       
  2235         {
       
  2236             string left = "";
       
  2237             left += DIR_SEPARATOR;
       
  2238             left += begin->first;
       
  2239             string right = "";
       
  2240             right += DIR_SEPARATOR;
       
  2241             right += begin->second;
       
  2242             ret.push_back(pair<string, string>(left, right));
       
  2243         } else
       
  2244         {
       
  2245             ret.push_back(*begin);
       
  2246         }
       
  2247     }
       
  2248 
       
  2249     return ret;
       
  2250 }
       
  2251 
       
  2252 
       
  2253 // ----------------------------------------------------------------------------
       
  2254 // Analyser::Wrapper
       
  2255 // Wrapper function to analyse all files in a component in separate thread.
       
  2256 // 
       
  2257 // ----------------------------------------------------------------------------
       
  2258 //
       
  2259 void Analyser::Wrapper( ReportGenerator& report, 
       
  2260                         int& issues, 
       
  2261                         CPPParser baseParser, 
       
  2262                         CPPParser currParser, 
       
  2263                         PlatformHeaders& pfHeaders, 
       
  2264                         PlatformHeaders& unsuccessfulHdrs
       
  2265                        )
       
  2266 {
       
  2267 	stringvector tiBaseFilenames; // This contains also additional headers needed to compile baseline
       
  2268 	stringvector tiCurrFilenames; // This contains also additional headers needed to compile product  
       
  2269 	PlatformHeaders tiInvalidFiles;	// holds a list of files without include guards need to be compiled individually
       
  2270 	stringvector tiBaseIncludes; // This contains also additional headers needed to compile baseline
       
  2271 	stringvector tiCurrIncludes; // This contains also additional headers needed to compile product  
       
  2272 
       
  2273 	stringvector baseSysIncludes; // This contains headers needed to compile baseline for 3rd time analyzation of a single header.
       
  2274 	stringvector curSysIncludes;  //  This contains headers needed to compile product for 3rd time analyzation of a single header.
       
  2275 
       
  2276 	tiBaseFilenames.assign(iBaseFilenames.begin(),iBaseFilenames.end());
       
  2277 	tiCurrFilenames.assign(iCurrFilenames.begin(),iCurrFilenames.end());
       
  2278 	tiInvalidFiles.assign(iInvalidFiles.begin(),iInvalidFiles.end());
       
  2279 	tiBaseIncludes.assign(iBaseIncludes.begin(),iBaseIncludes.end());
       
  2280 	tiCurrIncludes.assign(iCurrIncludes.begin(),iCurrIncludes.end());
       
  2281 	
       
  2282 	if (iOnlySystemIncludeRequired == true)
       
  2283 	{
       
  2284 		//tiBaseIncludes and tiCurrIncludes are required for 3rd time analyzation.
       
  2285 		//This time parse each unsuccessful header with both system includes and paths.
       
  2286 		baseSysIncludes.assign(tiBaseIncludes.begin(),tiBaseIncludes.end());
       
  2287 		curSysIncludes.assign(tiCurrIncludes.begin(),tiCurrIncludes.end());
       
  2288 
       
  2289 		// Clear these includes as for 2nd time parsing of each unsuccessful headres, 
       
  2290 		//as only system include paths arerequuired.
       
  2291 		tiBaseIncludes.clear();
       
  2292 		tiCurrIncludes.clear();
       
  2293 	}
       
  2294 	
       
  2295 	
       
  2296 	if( (tiBaseIncludes.size()>0 && tiCurrIncludes.size()>0)|| (tiBaseFilenames.size()>0 && tiCurrFilenames.size()>0) )
       
  2297 	{
       
  2298 		if( AnalyseBundle(tiBaseFilenames, tiCurrFilenames, report, issues, &baseParser, &currParser, &tiBaseIncludes, &tiCurrIncludes))
       
  2299 		{
       
  2300 			tiBaseFilenames.clear();
       
  2301 			tiCurrFilenames.clear();
       
  2302 		}
       
  2303 	}
       
  2304 
       
  2305 	if (iNotRemovedFiles.size() != 0)
       
  2306 	{            
       
  2307 		list<string> tempvar;
       
  2308 		list<string>::iterator removefile = iNotRemovedFiles.begin();
       
  2309 		list<string>::iterator fileend = iNotRemovedFiles.end();
       
  2310 		for(; removefile != fileend; removefile++)
       
  2311 		{
       
  2312 			CPPParser::RemoveFile(*removefile, tempvar);
       
  2313 		}
       
  2314 		if (tempvar.size() != 0)
       
  2315 		{
       
  2316 			iNotRemovedFiles = tempvar;
       
  2317 		} 
       
  2318 		else
       
  2319 		{
       
  2320 			iNotRemovedFiles.clear();
       
  2321 		}
       
  2322 	}  
       
  2323 	
       
  2324 	if(tiInvalidFiles.size() > 0)
       
  2325 	{
       
  2326 		// also add to this list, the set of headers
       
  2327 		// without include guards
       
  2328 		PlatformHeaders::iterator add = tiInvalidFiles.begin();
       
  2329 		for(; add != tiInvalidFiles.end(); ++add )
       
  2330 		{
       
  2331 			tiBaseFilenames.push_back( add->first->ID() );
       
  2332 			tiCurrFilenames.push_back( add->second->ID() );
       
  2333 		}
       
  2334 	}		
       
  2335 	
       
  2336 	// if thread flag is set and there are gretaer number of files, create threads for analysing every PLATFORM_BUNDLESIZE number of files
       
  2337 	if( iUseThread && tiBaseFilenames.size() >= PLATFORM_BUNDLESIZE  )
       
  2338 	{
       
  2339 		stringvector tmp;
       
  2340 		int pcount = 0;
       
  2341 		stringvector::iterator i = tiBaseFilenames.begin();                
       
  2342 		for(; i != tiBaseFilenames.end(); ++i )
       
  2343 		{				
       
  2344 			pcount++;
       
  2345 			PlatformHeaders::iterator h = FindHeaderPair(*i, pfHeaders);
       
  2346 			if( h != pfHeaders.end() )
       
  2347 			{			
       
  2348 				tmp.push_back(*i);
       
  2349 			}			
       
  2350 			if ((pcount % PLATFORM_BUNDLESIZE == 0 || pcount == tiBaseFilenames.size()) && tmp.size()>0)		
       
  2351 			{
       
  2352 				while (lock.locked())
       
  2353 				{
       
  2354 					#ifdef __WIN__
       
  2355 					Sleep(4000);
       
  2356 					#else
       
  2357 					usleep(4000*1000);
       
  2358 					#endif
       
  2359 				}
       
  2360 				lock.lock();
       
  2361 				
       
  2362 				if(gComponentThreads.size() >= MAX_THREAD_COUNT2)
       
  2363 				{
       
  2364 					gComponentThreads.join_all();
       
  2365 					int size = gComponentThreads.size();
       
  2366 					for (int i=0;i<size;i++)
       
  2367 					{	
       
  2368 						gComponentThreads.remove_thread(gpHeaderThreads[i]);
       
  2369 						gpHeaderThreads[i]->~thread();	
       
  2370 					}				
       
  2371 				}
       
  2372 						
       
  2373 				//2nd time analyzation of each header in a different thread
       
  2374 				Analyser* obj = new Analyser();
       
  2375 				*obj = *this;
       
  2376 				int size = gComponentThreads.size();
       
  2377 				gpHeaderThreads[size]=gComponentThreads.create_thread(boost::bind(&Analyser::Wrapper2,obj,tmp, 
       
  2378 						boost::ref(pfHeaders), boost::ref(unsuccessfulHdrs), boost::ref(report), boost::ref(issues)));
       
  2379 				lock.unlock();	
       
  2380 				tmp.clear();
       
  2381 							
       
  2382 			}
       
  2383 		}
       
  2384 	}
       
  2385 	else // do not create different thread. analyse in the same thread.
       
  2386 	{						
       
  2387 		stringvector::iterator i = tiBaseFilenames.begin();                
       
  2388 		for(; i != tiBaseFilenames.end(); ++i )
       
  2389 		{                    
       
  2390 			PlatformHeaders::iterator h = FindHeaderPair(*i, pfHeaders);
       
  2391 			if( h != pfHeaders.end() )
       
  2392 			{
       
  2393 				if(( pfHeaders.size() > 1 ) )
       
  2394 				{
       
  2395 					PlatformHeaders tempHeaders;
       
  2396 					tempHeaders.push_back(*h);
       
  2397 					h->first->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED);
       
  2398 					iOnlySystemIncludeRequired = true;
       
  2399 					//2nd time analyzation of each header in same thread
       
  2400 					AnalyzePlatforms( tempHeaders, unsuccessfulHdrs, report, issues, false );
       
  2401 					iOnlySystemIncludeRequired = false;
       
  2402 				}
       
  2403 				else
       
  2404 				{
       
  2405 					//The 3rd time parsing is required to check again each unsuccessful headers 
       
  2406 					//with system includes and paths from platform data
       
  2407 					if(!AnalyseBundle(tiBaseFilenames, tiCurrFilenames, report, issues, &baseParser, &currParser, &baseSysIncludes, &curSysIncludes))
       
  2408 					{
       
  2409 						if( FindHeaderPair(h->first->ID(), unsuccessfulHdrs ) == unsuccessfulHdrs.end() )
       
  2410 						{
       
  2411 							unsuccessfulHdrs.push_back(*h); 
       
  2412 						}
       
  2413 					} 
       
  2414 					if (iNotRemovedFiles.size() != 0)
       
  2415 					{            
       
  2416 						list<string> tempvar;
       
  2417 						list<string>::iterator removefile = iNotRemovedFiles.begin();
       
  2418 						list<string>::iterator fileend = iNotRemovedFiles.end();
       
  2419 						for(; removefile != fileend; removefile++)
       
  2420 						{
       
  2421 							CPPParser::RemoveFile(*removefile, tempvar);
       
  2422 						}
       
  2423 						if (tempvar.size() != 0)
       
  2424 						{
       
  2425 							iNotRemovedFiles = tempvar;
       
  2426 						} 
       
  2427 						else
       
  2428 						{
       
  2429 							iNotRemovedFiles.clear();
       
  2430 						}
       
  2431 					}	
       
  2432 				}                        
       
  2433 			}
       
  2434 		}	
       
  2435 	}	
       
  2436 }  
       
  2437 
       
  2438 // ----------------------------------------------------------------------------
       
  2439 // Analyser::Wrapper2
       
  2440 // Wrapper function to analyse group of files in a component individually in different thread.
       
  2441 // 
       
  2442 // ----------------------------------------------------------------------------
       
  2443 //
       
  2444 void Analyser::Wrapper2(stringvector filenames, PlatformHeaders& pfHeaders, PlatformHeaders& unsuccessfulHdrs, ReportGenerator& report, int& issues)
       
  2445 {
       
  2446 	PlatformHeaders tempHeaders;
       
  2447 	stringvector::iterator i = filenames.begin();                
       
  2448 	for(; i != filenames.end(); ++i )
       
  2449 	{	
       
  2450 		PlatformHeaders::iterator h = FindHeaderPair(*i, pfHeaders);
       
  2451 		if( h != pfHeaders.end() )
       
  2452 		{	
       
  2453 			tempHeaders.push_back(*h);
       
  2454 			h->first->SetStatus(Header::HDR_STATUS_TO_BE_ANALYZED);
       
  2455 			iOnlySystemIncludeRequired = true;	
       
  2456 			AnalyzePlatforms( tempHeaders, unsuccessfulHdrs, report, issues, false );
       
  2457 			iOnlySystemIncludeRequired = false;
       
  2458 		}
       
  2459 	}	
       
  2460 
       
  2461 	if (iNotRemovedFiles.size() != 0)
       
  2462 					{            
       
  2463 						list<string> tempvar;
       
  2464 						list<string>::iterator removefile = iNotRemovedFiles.begin();
       
  2465 						list<string>::iterator fileend = iNotRemovedFiles.end();
       
  2466 						for(; removefile != fileend; removefile++)
       
  2467 						{
       
  2468 							CPPParser::RemoveFile(*removefile, tempvar);
       
  2469 						}
       
  2470 						if (tempvar.size() != 0)
       
  2471 						{
       
  2472 							iNotRemovedFiles = tempvar;
       
  2473 						} 
       
  2474 						else
       
  2475 						{
       
  2476 							iNotRemovedFiles.clear();
       
  2477 						}
       
  2478 					}
       
  2479 }
       
  2480 
       
  2481 
       
  2482 
       
  2483 void Analyser::ParseAndCompareResourceFiles(vector<pair< string, string> >& resourcevector, ReportGenerator& report)
       
  2484 {
       
  2485 	ResourceContent baseResource;
       
  2486 	ResourceContent curResource;
       
  2487 
       
  2488 	list<pair<string, string> > iBaseSystemheaders = BBCFileUtils::extractFilenames(iParams.getParameter(BASELINEPLAT));
       
  2489 	list<pair<string, string> > iCurSystemheaders = BBCFileUtils::extractFilenames(iParams.getParameter(CURRENTPLAT));
       
  2490 
       
  2491 	for(int outer = 0; outer< (int)resourcevector.size(); outer++)
       
  2492 	{
       
  2493 		list<pair<string, string> > baseSystemheaders;
       
  2494 		list<pair<string, string> > curSystemheaders;
       
  2495 
       
  2496 		baseSystemheaders = iBaseSystemheaders;
       
  2497 		curSystemheaders = iCurSystemheaders;
       
  2498 		pair <string, string> files = resourcevector.at(outer);
       
  2499 		vector <string> bIncludes;
       
  2500 		vector <string> cIncludes;
       
  2501 
       
  2502 
       
  2503 		baseResource.RHFileName = "";
       
  2504 		curResource.RHFileName = "";
       
  2505 
       
  2506 		baseResource.RHFileName = BBCFileUtils::TrimAll(files.first);
       
  2507 		curResource.RHFileName = BBCFileUtils::TrimAll(files.second);
       
  2508 
       
  2509 		pair <string, string> fileAnalyzed;
       
  2510 		fileAnalyzed.first = baseResource.RHFileName;
       
  2511 		fileAnalyzed.second = curResource.RHFileName;
       
  2512 		bool pairFound = false;
       
  2513 		// check if the file is already analyzed or not.
       
  2514 		for(int i = 0; i < (int)iRHFile_Analyzed.size(); i++ )
       
  2515 		{
       
  2516 			pair<string,string> filePair = iRHFile_Analyzed.at(i);
       
  2517 			if(fileAnalyzed.first == filePair.first )
       
  2518 			{
       
  2519 				pairFound = true;
       
  2520 				break;
       
  2521 			}
       
  2522 		}
       
  2523 		// File is not analyzed yet, so analyze it.
       
  2524 		if(pairFound == false )
       
  2525 		{
       
  2526 			iRHFile_Analyzed.push_back(fileAnalyzed);
       
  2527 
       
  2528 			ifstream file(files.first.c_str());
       
  2529 			if(!file.is_open())
       
  2530 			{
       
  2531 				cerr << "ERROR: Cannot open " << files.first << " for reading!" << endl;
       
  2532 				exit(17);
       
  2533 			}
       
  2534 
       
  2535 			// baseline resource file parsing
       
  2536 			getElementListFromRHFile(file,baseResource,bIncludes );
       
  2537 			file.close();
       
  2538 
       
  2539 			// handle #include .RH headers, get proper path from system includes
       
  2540 			int basePos = (int)baseResource.RHFileName.find_last_of(DIR_SEPARATOR);
       
  2541 			string basePath = baseResource.RHFileName.substr(0,basePos);
       
  2542 			vector<pair<string,string> > includes;
       
  2543 			bool isPresent = false;
       
  2544 			pair<string,string> bPath;
       
  2545 			list<pair<string,string> >::iterator bHdr = baseSystemheaders.begin();
       
  2546 			for(;bHdr!= baseSystemheaders.end(); bHdr++)
       
  2547 			{
       
  2548 				bPath = *bHdr;
       
  2549 				if(bPath.first == basePath)
       
  2550 				{
       
  2551 					isPresent = true;
       
  2552 					break;
       
  2553 				}			
       
  2554 			}
       
  2555 			if(isPresent == false)
       
  2556 			{
       
  2557 				pair<string,string> bPair;
       
  2558 				bPair.first =basePath;
       
  2559 				bPair.second =basePath;
       
  2560 				baseSystemheaders.push_back(bPair);
       
  2561 			}
       
  2562 
       
  2563 			bHdr= baseSystemheaders.begin();
       
  2564 			for(int i = 0; i < (int)bIncludes.size(); i++) 
       
  2565 			{
       
  2566 				for(;bHdr != baseSystemheaders.end(); bHdr++)
       
  2567 				{
       
  2568 					pair<string,string> baseHeader = *bHdr;
       
  2569 					pair<string,string>basePair;
       
  2570 					if(BBCFileUtils::FileExists(baseHeader.first + DIR_SEPARATOR + bIncludes.at(i)) )
       
  2571 					{
       
  2572 						basePair.first = baseHeader.first + DIR_SEPARATOR + bIncludes.at(i);
       
  2573 						includes.push_back(basePair);
       
  2574 						break;
       
  2575 					}
       
  2576 				}
       
  2577 			}
       
  2578 
       
  2579 			ifstream file2(files.second.c_str());
       
  2580 			if(!file2.is_open())
       
  2581 			{
       
  2582 				cerr << "ERROR: Cannot open " << files.second << " for reading!" << endl;
       
  2583 				exit(17);
       
  2584 			}
       
  2585 			// current resource file parsing
       
  2586 			getElementListFromRHFile(file2,curResource, cIncludes );
       
  2587 			file2.close();
       
  2588 			
       
  2589 			_current_files++;
       
  2590 			cout << "\nAnalysing files (" << _current_files << "/" << _total_files << "): " << files.first <<" => "<< files.second << endl;
       
  2591 
       
  2592 			// get current resource file's path and add to system include paths 
       
  2593 			// to get proper path for #include rh headers in current file
       
  2594 			int cPos = (int)curResource.RHFileName.find_last_of(DIR_SEPARATOR);
       
  2595 			string curPath = curResource.RHFileName.substr(0,cPos);
       
  2596 			isPresent = false;
       
  2597 			list<pair<string,string> >::iterator chdr= curSystemheaders.begin();
       
  2598 			pair<string,string> cPath;
       
  2599 			for(;chdr != curSystemheaders.end(); chdr++)
       
  2600 			{
       
  2601 				cPath = *chdr;
       
  2602 				if(cPath.first == curPath)
       
  2603 				{
       
  2604 					isPresent = true;
       
  2605 					break;
       
  2606 				}			
       
  2607 			}
       
  2608 			if(isPresent == false)
       
  2609 			{
       
  2610 				pair<string,string> cPair;
       
  2611 				cPair.first = curPath;
       
  2612 				cPair.second = curPath;
       
  2613 				curSystemheaders.push_back(cPair);
       
  2614 			}
       
  2615 
       
  2616 			
       
  2617 			for(int out = 0; out < (int)includes.size(); out++)
       
  2618 			{
       
  2619 				int bLoc = (int)includes.at(out).first.find_last_of(DIR_SEPARATOR);
       
  2620 				string bString = includes.at(out).first.substr(bLoc+1,string::npos);
       
  2621 				bool includedHeaderPresent = false;
       
  2622 
       
  2623 				for(int j = 0; j < (int)cIncludes.size(); j++) 
       
  2624 				{
       
  2625 					bool fileMatched = false;
       
  2626 					chdr= curSystemheaders.begin();
       
  2627 					for(;chdr != curSystemheaders.end(); chdr++)
       
  2628 					{
       
  2629 						pair<string,string> curHeader = *chdr;
       
  2630 						string curFile = curHeader.first + DIR_SEPARATOR + cIncludes.at(j);
       
  2631 						int loc = (int)curFile.find_last_of(DIR_SEPARATOR);
       
  2632 						string curTemp = curFile.substr(loc+1 ,string::npos);
       
  2633 						if(bString == curTemp)
       
  2634 						{
       
  2635 							includedHeaderPresent = true;
       
  2636 							if(BBCFileUtils::FileExists(curFile) ) 
       
  2637 							{
       
  2638 								fileMatched = true; // current file found in curr dir
       
  2639 								includes.at(out).second = curFile;
       
  2640 								break;
       
  2641 							}							
       
  2642 						}
       
  2643 					}
       
  2644 
       
  2645 					if ( fileMatched = false )
       
  2646 					{
       
  2647 						// file does not exists in curdir
       
  2648 						report.addIssue(baseResource.RHFileName, includes.at(out).first, EIssueIdentityFile, 
       
  2649 							EIssueTypeRemoval,ESeverityBBCBreak,ESeveritySCNULL, "", 0, curResource.RHFileName,"");
       
  2650 						break;
       
  2651 					}
       
  2652 				}
       
  2653 				if(includedHeaderPresent == false)
       
  2654 				{
       
  2655 					// add issue, as field is removed in current file.
       
  2656 					report.addIssue(baseResource.RHFileName, bString, EIssueIdentityField, 
       
  2657 						EIssueTypeRemoval,ESeverityNULL,ESeveritySCBreak, "", 0, curResource.RHFileName,"");
       
  2658 				}
       
  2659 			}
       
  2660 
       
  2661 			for(int l = 0; l < (int)includes.size(); l++ )
       
  2662 			{
       
  2663 				pair<string,string> pair = includes.at(l);
       
  2664 				if(pair.first.size() > 0 && pair.second.size()>0)
       
  2665 				{				
       
  2666 					resourcevector.push_back(pair);
       
  2667 				}
       
  2668 			}
       
  2669 
       
  2670 			compareResources( baseResource, curResource, report);
       
  2671 		}
       
  2672 
       
  2673 
       
  2674 		baseResource.structList.clear();
       
  2675 		baseResource.enumList.clear();
       
  2676 		baseResource.macroList.clear();
       
  2677 
       
  2678 		curResource.structList.clear();
       
  2679 		curResource.enumList.clear();
       
  2680 		curResource.macroList.clear();
       
  2681 
       
  2682 
       
  2683 	}// end of one resource
       
  2684 	cout<<"\n\n"<<endl;
       
  2685 }
       
  2686 
       
  2687 
       
  2688 void Analyser::getElementListFromRHFile(std::ifstream& RHFile,ResourceContent& resource, vector< string >& includes )
       
  2689 {
       
  2690 	string line;
       
  2691 	EnumElement lEnum;
       
  2692 	string tempData;
       
  2693 	string elementVal;
       
  2694 
       
  2695 	StructElement lStruct;
       
  2696 	string structName;
       
  2697 
       
  2698 	bool structInuse = false;
       
  2699 	bool enumInuse = false;
       
  2700 	bool macroInuse = false;
       
  2701 	bool keyFound = false;
       
  2702 	bool elementfound = false;
       
  2703 	bool valueFound = false;
       
  2704 
       
  2705 	bool comment = false;	
       
  2706 	bool ignoreLine = false;
       
  2707 
       
  2708 	bool newLinecharFound = false; // for macros, newline character can be present
       
  2709 
       
  2710 	long currentEnumVal = -1;
       
  2711 
       
  2712 	char keywords [23][15] = {"short","long", "word", "len", "byte", "struct", "ltext","enum", "ltext8", "ltext16", "ltext32", "llink", "srlink","double",
       
  2713 		"buf<1>","buf<2>","buf<4>","buf<8>","buf<16>","buf<32>","buf<64>","buf<128>","buf<256>"};
       
  2714 
       
  2715 	MacroElement macro;
       
  2716 	int lineNo = 0;
       
  2717 
       
  2718 	while(getline(RHFile,line))
       
  2719 	{
       
  2720 		lineNo++;
       
  2721 		pair<string,int> enummember;
       
  2722 		StructMember elementMember;
       
  2723 		line = toLowerCase(trimWhiteSpace(line));
       
  2724 
       
  2725 		// Ignore all comment lines. e.g /*xxxxxxxxxx*/ Struct ABCD , start reading characterwise from struct
       
  2726 		if(enumInuse == false && macroInuse == false && structInuse == false )
       
  2727 		{
       
  2728 			if(line.find("/*") != -1 )
       
  2729 			{
       
  2730 				if( line.find("*/") == -1)
       
  2731 				{
       
  2732 				comment = true;
       
  2733 				continue;
       
  2734 				}
       
  2735 				else
       
  2736 				{
       
  2737 					int com = (int)line.find_last_of("*");
       
  2738 					line= line.substr(com +2, string::npos);
       
  2739 				}
       
  2740 			}
       
  2741 			if(line.find("*/") != -1 )
       
  2742 			{
       
  2743 				comment = false;
       
  2744 				if(ignoreLine == true)
       
  2745 					ignoreLine = false;
       
  2746 				continue;
       
  2747 			}
       
  2748 			if(comment == true)
       
  2749 			{
       
  2750 				continue;
       
  2751 			}
       
  2752 			if(line.find("//") != -1 ) 
       
  2753 			{
       
  2754 				int com = (int)line.find_first_of("//");
       
  2755 				bool wordFound = false;
       
  2756 				line = line.substr(0,com);
       
  2757 				for (int i = 0; i< (int)line.size(); i++ )
       
  2758 				{
       
  2759 					// check  '//' commentline starts after some key value e.g struct ABCD // xyz
       
  2760 					if ( (int)line.at(i ) != 32 && (int)line.at(i) != 9 ) // 32 and 9 are for space and invalid character
       
  2761 					{
       
  2762 						wordFound = true;
       
  2763 						break;
       
  2764 					}
       
  2765 				}
       
  2766 				if(wordFound == false)
       
  2767 				continue;
       
  2768 			}
       
  2769 
       
  2770 		}
       
  2771  
       
  2772 		// Find any other header file is included in current file
       
  2773 		// Then add it to file and check whether this is already analyzed or not.
       
  2774 		// If not, then analyze it.
       
  2775 		if(line.find ("#") != -1 && line.find("include") != -1 )
       
  2776 		{
       
  2777 				int start = (int)line.find_first_of ("<");
       
  2778 			
       
  2779 			int end;
       
  2780 			if(start == -1)
       
  2781 			{
       
  2782 				start =(int) line.find_first_of("\"");
       
  2783 				end = (int)line.find_last_of("\"");
       
  2784 			}
       
  2785 			else
       
  2786 			{
       
  2787 				end = (int)line.find(">");
       
  2788 			}
       
  2789 
       
  2790 			if (start > 0 && end > 0 )
       
  2791 			{
       
  2792 				line = line.substr(start + 1,(end - start) - 1);
       
  2793 				line = BBCFileUtils::TrimAll(line);
       
  2794 				int loc = (int)line.find(RH_EXTENSION);
       
  2795 				// Include only .rh files
       
  2796 				if(loc != -1)
       
  2797 					includes.push_back(line);
       
  2798 			}
       
  2799 		}
       
  2800 
       
  2801 		// Now check lines for key structure (struct, enum, #inlude and start reading characterwise unless the key structure end.
       
  2802 		if (keyFound == false )
       
  2803 		{
       
  2804 			tempData.clear();
       
  2805 			int enumloc = (int)line.find(KEY_ENUM);
       
  2806 			// to get enum key word properly. After "enum" keyword, there might be no name present.
       
  2807 			// For this case, following checks are needed.
       
  2808 			if( enumloc!= -1)
       
  2809 			{
       
  2810 				enumInuse = true;
       
  2811 				string prestring = line.substr(0,enumloc);
       
  2812 				for(int i = 0; i< (int)prestring.size(); i++ )
       
  2813 				{
       
  2814 					if( (int)prestring.at(i)!= 32 && (int)prestring.at(i) != 9 )
       
  2815 					{
       
  2816 						enumInuse =false;
       
  2817 						break;
       
  2818 					}
       
  2819 				}
       
  2820 				if(enumInuse == true)
       
  2821 				{
       
  2822 					string postline = line.substr(enumloc+strlen(KEY_ENUM) ,string::npos);
       
  2823 					if( postline.size() > 0 && (int)postline.at(0)!= 32 && (int)postline.at(0) != 9 )
       
  2824 					{
       
  2825 							enumInuse =false;
       
  2826 							break;
       
  2827 					}
       
  2828 					else
       
  2829 					{
       
  2830 						line = postline;
       
  2831 						macroInuse = false;
       
  2832 						structInuse = false;
       
  2833 						lEnum.enumName = "";
       
  2834 						lEnum.enums.clear();
       
  2835 					}
       
  2836 				}
       
  2837 			}
       
  2838 			if(line.find(KEY_MACRO) != -1)
       
  2839 			{
       
  2840 				macroInuse = true;
       
  2841 				enumInuse = false;
       
  2842 				structInuse = false;
       
  2843 				macro.macroName = "";
       
  2844 				macro.macroVal = "";
       
  2845 				line = line.substr(strlen(KEY_MACRO),string::npos);
       
  2846 			}
       
  2847 
       
  2848 			if(line.find(KEY_STRUCT) != -1)
       
  2849 			{
       
  2850 				structInuse = true;
       
  2851 				enumInuse = false;
       
  2852 				macroInuse = false;
       
  2853 				lStruct.structName = "";
       
  2854 				lStruct.members.clear();
       
  2855 				line = line.substr(strlen(KEY_STRUCT),string::npos);
       
  2856 			}	
       
  2857 		}
       
  2858 
       
  2859 		// If any of the key found, then following lines will be checked character wise.
       
  2860 		if ( enumInuse == true || macroInuse == true || structInuse == true )
       
  2861 		{
       
  2862 			keyFound = true;
       
  2863 
       
  2864 			EnumMember enummember;
       
  2865 
       
  2866 			string elementName;
       
  2867 			string elementType;
       
  2868 			string structElementVal;
       
  2869 
       
  2870 			bool lineend = false;
       
  2871 			int length = int(line.size());
       
  2872 
       
  2873 			for (int j = 0; j < length ; j++)
       
  2874 			{
       
  2875 				int temp = line.at(j);
       
  2876 				//int templie = line.at(j);
       
  2877 				switch (temp)
       
  2878 				{
       
  2879 				case 32:  // For ' '
       
  2880 				case 9: //for Invalid space
       
  2881 					{
       
  2882 						if (structInuse == true && tempData.size() > 0)
       
  2883 						{
       
  2884 							if ( elementfound == true )
       
  2885 							{	
       
  2886 								for (int k = 0 ; k < 23 ; k++ )
       
  2887 								{
       
  2888 									// got the type, will check with all possible data types.Else it will be member name.
       
  2889 									int loc = int(line.find_first_of(keywords[k]));
       
  2890 									string key(keywords[k]);
       
  2891 									if (tempData == key )
       
  2892 									{											
       
  2893 										elementType.append(keywords[k]);
       
  2894 										tempData.clear();
       
  2895 										break;
       
  2896 									}										
       
  2897 								}
       
  2898 							}
       
  2899 						}
       
  2900 						if (macroInuse == true && macro.macroName.size() <=0 && tempData.size() > 0) // can be macro name
       
  2901 						{
       
  2902 							macro.macroName = tempData;
       
  2903 							macro.lineNo = lineNo;
       
  2904 							tempData.clear();
       
  2905 						}
       
  2906 					}
       
  2907 					break;
       
  2908 				case 59://For ';'
       
  2909 					{						
       
  2910 						if ( structInuse == true && elementfound == true && tempData.size() > 0)
       
  2911 						{
       
  2912 							elementName.append(tempData);
       
  2913 							elementMember.elementName = elementName;
       
  2914 							elementMember.elementType = elementType;
       
  2915 							elementMember.lineNo = lineNo;
       
  2916 							if (valueFound == true)
       
  2917 							{
       
  2918 								elementMember.elementValue= structElementVal; 
       
  2919 								valueFound = false;
       
  2920 							}
       
  2921 							lStruct.members.push_back (elementMember);
       
  2922 							tempData.clear();
       
  2923 						}
       
  2924 
       
  2925 						if(macroInuse ==false)
       
  2926 							break;	
       
  2927 
       
  2928 					}
       
  2929 					
       
  2930 				case 44://For ','
       
  2931 					{	
       
  2932 						if(macroInuse ==false)
       
  2933 						{
       
  2934 							if ( enumInuse == true && elementfound == true && tempData.size() > 0)
       
  2935 							{
       
  2936 								if (valueFound == true)
       
  2937 								{
       
  2938 									enummember.enumVal = elementVal.c_str();
       
  2939 									char *p;
       
  2940 									// convert enumVal to long , so that can be incremented if required.
       
  2941 									currentEnumVal = strtol(enummember.enumVal.c_str(),&p,0);
       
  2942 									valueFound = false;
       
  2943 								}
       
  2944 								else
       
  2945 								{
       
  2946 									currentEnumVal += 1;
       
  2947 									string p;
       
  2948 									// convert long to string
       
  2949 									enummember.enumVal = ltoa(currentEnumVal,p,0);
       
  2950 								}
       
  2951 								enummember.enumMemName.append(tempData);
       
  2952 								enummember.lineNo = lineNo;
       
  2953 
       
  2954 								lEnum.enums.push_back(enummember);
       
  2955 
       
  2956 								tempData.clear();
       
  2957 								elementVal.clear();
       
  2958 							}
       
  2959 							break;
       
  2960 						}
       
  2961 					}
       
  2962 					
       
  2963 				case 61: //For '='
       
  2964 					{
       
  2965 						if(macroInuse == false)
       
  2966 						{
       
  2967 							valueFound = true;
       
  2968 							break;
       
  2969 						}
       
  2970 					}
       
  2971 					//break;
       
  2972 
       
  2973 				case 123:  //For '{'
       
  2974 					{
       
  2975 						if(macroInuse ==false)
       
  2976 						{
       
  2977 							if(tempData.size() > 0 )
       
  2978 							{
       
  2979 								if(structInuse == true)
       
  2980 								{
       
  2981 									lStruct.structName.assign(tempData);
       
  2982 									lStruct.lineNo = lineNo;
       
  2983 								}
       
  2984 								else
       
  2985 								{
       
  2986 									lEnum.enumName.assign(tempData);
       
  2987 									lEnum.lineNo = lineNo;
       
  2988 								}
       
  2989 							}
       
  2990 							tempData.clear();
       
  2991 							elementfound = true;
       
  2992 
       
  2993 							break;
       
  2994 						}
       
  2995 					}
       
  2996 				case 125: //For '}'
       
  2997 					{
       
  2998 						if(macroInuse ==false)
       
  2999 						{
       
  3000 							if(structInuse == true)
       
  3001 							{
       
  3002 								structInuse = false;	
       
  3003 								if(tempData.size() > 0) // if some inline macro is present
       
  3004 								{
       
  3005 									elementMember.elementName = tempData ;
       
  3006 									elementMember.elementType = "";
       
  3007 									elementMember.lineNo = lineNo;
       
  3008 									lStruct.members.push_back(elementMember);
       
  3009 								}
       
  3010 								resource.structList.push_back(lStruct);
       
  3011 							}
       
  3012 							else if ( enumInuse == true )
       
  3013 							{
       
  3014 								if (elementfound == true && tempData.size() > 0)
       
  3015 								{
       
  3016 									if (valueFound == true)
       
  3017 									{
       
  3018 										enummember.enumVal = elementVal.c_str(); 
       
  3019 										char *p;
       
  3020 										// convert enumVal to long , so that can be incremented if required.
       
  3021 										currentEnumVal = strtol(enummember.enumVal.c_str(),&p,0);
       
  3022 										valueFound = false;
       
  3023 									}
       
  3024 									else
       
  3025 									{
       
  3026 										currentEnumVal += 1;
       
  3027 										string p;
       
  3028 										// convert long to string
       
  3029 										enummember.enumVal = ltoa(currentEnumVal,p,0);
       
  3030 									}
       
  3031 
       
  3032 									enummember.lineNo = lineNo;
       
  3033 
       
  3034 									enummember.enumMemName.append(tempData);
       
  3035 
       
  3036 									lEnum.enums.push_back(enummember);							
       
  3037 								}
       
  3038 								currentEnumVal = -1;
       
  3039 								elementVal.clear();
       
  3040 								enumInuse = false;
       
  3041 								resource.enumList.push_back(lEnum);
       
  3042 							}
       
  3043 							keyFound = false;
       
  3044 							elementfound = false;
       
  3045 							tempData.clear();
       
  3046 
       
  3047 							break;
       
  3048 						}
       
  3049 					}
       
  3050 				default:
       
  3051 					{
       
  3052 						// followings are to ignore any comment line in between.
       
  3053 						if( j+1 <length)
       
  3054 						{
       
  3055 							if (line.at(j) == '/' )
       
  3056 							{
       
  3057 								if(line.at(j+1) == '*')
       
  3058 									ignoreLine = true;
       
  3059 
       
  3060 								else if ( line.at(j+1) == '/')
       
  3061 								{
       
  3062 									lineend = true;
       
  3063 									break;
       
  3064 								}
       
  3065 							}
       
  3066 							if(ignoreLine == true)
       
  3067 							{
       
  3068 								if (j+1 <length && line.at(j) == '*' && line.at(j+1) == '/')
       
  3069 								{
       
  3070 									ignoreLine = false;
       
  3071 									j = j+2;
       
  3072 									continue;
       
  3073 
       
  3074 								}
       
  3075 							}
       
  3076 						} // comment line checks ended
       
  3077 
       
  3078 						if(ignoreLine == false && j<length)
       
  3079 						{
       
  3080 							// newline character's int value is 92, for macros, newline char can be present mainly.
       
  3081 							if ((int) line.at(j)== 92 && macroInuse == true && tempData.size() > 0) // can be macro name
       
  3082 							{
       
  3083 								newLinecharFound = true; // new line character found
       
  3084 								if ( macro.macroName.size() <=0)
       
  3085 								{
       
  3086 									macro.macroName = tempData;	
       
  3087 									macro.lineNo = lineNo;
       
  3088 								}
       
  3089 								else
       
  3090 								{
       
  3091 									macro.macroVal.append(tempData);
       
  3092 								}
       
  3093 								tempData.clear();
       
  3094 								
       
  3095 							}
       
  3096 							// Check macro definition ended after newlines
       
  3097 							if( (int) line.at(j)!= 92 && j+1 >= length && macroInuse == true &&  newLinecharFound == true )
       
  3098 							{
       
  3099 								newLinecharFound =false;
       
  3100 								//macroInuse = false;
       
  3101 								//macro.macroVal.append(tempData);
       
  3102 								//tempData.clear();
       
  3103 								break;
       
  3104 							}
       
  3105 							if (enumInuse == true || macroInuse == true || structInuse == true)
       
  3106 							{
       
  3107 								if(valueFound == true)
       
  3108 								{
       
  3109 									if ( structInuse == true )
       
  3110 										structElementVal.push_back(line.at(j));
       
  3111 									else
       
  3112 										elementVal.push_back(line.at(j));									
       
  3113 								}
       
  3114 								else
       
  3115 								{
       
  3116 									if( (int)line.at(j) != 92)// ignore newline character
       
  3117 									tempData.push_back(line.at(j));
       
  3118 								}
       
  3119 							}
       
  3120 						}
       
  3121 
       
  3122 						
       
  3123 					}
       
  3124 					break;
       
  3125 				}
       
  3126 				if (lineend == true)
       
  3127 					break;
       
  3128 			}// line end
       
  3129 
       
  3130 			// Macro structure ended, fill the values.
       
  3131 			if( macroInuse == true && newLinecharFound == false && tempData.size() > 0 )
       
  3132 			{
       
  3133 				if(tempData.size()> 0 )
       
  3134 				{
       
  3135 					macro.macroVal.append(tempData);
       
  3136 					tempData.clear();
       
  3137 				}
       
  3138 				keyFound = false;
       
  3139 				macroInuse = false ;
       
  3140 				resource.macroList.push_back(macro);
       
  3141 			}
       
  3142 		}
       
  3143 
       
  3144 	}// End of all lines in resource file
       
  3145 
       
  3146 }
       
  3147 
       
  3148 void Analyser::compareResources(ResourceContent &baseResource, ResourceContent &curResource, ReportGenerator& report)
       
  3149 {
       
  3150 	int base_struct_no = (int)baseResource.structList.size();
       
  3151 	int cur_struct_no = (int)curResource.structList.size();
       
  3152 
       
  3153 	int base_enum_no = (int)baseResource.enumList.size();
       
  3154 	int cur_enum_no = (int)curResource.enumList.size();
       
  3155 
       
  3156 	int base_macro_no = (int)baseResource.macroList.size();
       
  3157 	int cur_macro_no = (int)curResource.macroList.size();
       
  3158 
       
  3159 	StructElement baseStruct;
       
  3160 	StructElement curStruct;
       
  3161 
       
  3162 	EnumElement baseEnum;
       
  3163 	EnumElement curEnum;
       
  3164 
       
  3165 	MacroElement baseMacro;
       
  3166 	MacroElement curMacro;
       
  3167 
       
  3168 	for(int i = 0; i < base_struct_no; i++ )
       
  3169 	{
       
  3170 		baseStruct =  baseResource.structList.at(i);
       
  3171 		bool structFound = false;
       
  3172 		for(int j = 0; j < cur_struct_no; j++ )
       
  3173 		{
       
  3174 			curStruct = curResource.structList.at(j);
       
  3175 			if(baseStruct.structName == curStruct.structName )
       
  3176 			{
       
  3177 				int baseMemNo = (int)baseStruct.members.size();
       
  3178 				int curMemNo = (int)curStruct.members.size();
       
  3179 
       
  3180 				structFound = true;
       
  3181 
       
  3182 				for( int bInner = 0; bInner < baseMemNo; bInner++ )
       
  3183 				{
       
  3184 					bool memFound = false;
       
  3185 					for ( int cInner = 0; cInner < curMemNo; cInner++ )
       
  3186 					{
       
  3187 						if ( baseStruct.members.at(bInner).elementName == curStruct.members.at(cInner).elementName )
       
  3188 						{
       
  3189 							memFound = true;
       
  3190 							if(baseStruct.members.at(bInner).elementType == curStruct.members.at(cInner).elementType)
       
  3191 							{
       
  3192 								if(baseStruct.members.at(bInner).elementValue.size() > 0
       
  3193 									&& (baseStruct.members.at(bInner).elementValue != curStruct.members.at(cInner).elementValue) )
       
  3194 								{
       
  3195 									//add issue	member value mismatch		
       
  3196 									string bVal = baseStruct.structName + "::" + baseStruct.members.at(bInner).elementName;
       
  3197 									string cVal = curStruct.members.at(cInner).elementValue;
       
  3198 									int lineNo = curStruct.members.at(cInner).lineNo;
       
  3199 									report.addIssue(baseResource.RHFileName, bVal, EIssueIdentityStructMember, EIssueTypeChangeInInitialisation, 
       
  3200 										ESeverityNULL, ESeveritySCBreak, cVal, lineNo,curResource.RHFileName,"");
       
  3201 								} 
       
  3202 							}
       
  3203 							else
       
  3204 							{
       
  3205 								// add issue tyechange
       
  3206 								string bType = baseStruct.structName + "::" + baseStruct.members.at(bInner).elementName;
       
  3207 								string cType = curStruct.members.at(cInner).elementType;
       
  3208 								int lineNo = curStruct.members.at(cInner).lineNo;
       
  3209 								report.addIssue(baseResource.RHFileName, bType, EIssueIdentityStructMember, EIssueTypeChangeInType, 
       
  3210 									ESeverityNULL, ESeveritySCBreak, cType, lineNo,curResource.RHFileName,"");
       
  3211 							}
       
  3212 
       
  3213 							break;
       
  3214 
       
  3215 						}// memeber name matched
       
  3216 					}// loop thru all curr struct member
       
  3217 
       
  3218 					if( memFound == false)
       
  3219 					{
       
  3220 						// Add Issue Member not found  // baseStruct.members.at(bInner)
       
  3221 						string bMember = baseStruct.structName + "::" + baseStruct.members.at(bInner).elementName;
       
  3222 						int lineNo = curStruct.lineNo;
       
  3223 						report.addIssue(baseResource.RHFileName, bMember, EIssueIdentityStructMember, EIssueTypeRemoval, 
       
  3224 							ESeverityNULL,ESeveritySCBreak, "", lineNo,curResource.RHFileName,"");
       
  3225 					}
       
  3226 				}// loop base struct member
       
  3227 
       
  3228 			}// struct name match
       
  3229 		}// loop curr structs
       
  3230 
       
  3231 		if( structFound == false )
       
  3232 		{ 
       
  3233 			//Add issue struct not found
       
  3234 			report.addIssue(baseResource.RHFileName, baseStruct.structName, EIssueIdentityStruct, EIssueTypeRemoval, 
       
  3235 				ESeverityNULL, ESeveritySCBreak, "", 0,curResource.RHFileName,"");
       
  3236 		}
       
  3237 	}//loop base structs
       
  3238 
       
  3239 	// --------------Enum Comparison ------------
       
  3240 	vector<EnumMember>baseEnumNameEmptyMemberList;
       
  3241 	vector<EnumMember>curEnumNameEmptyMemberList;
       
  3242 	vector<EnumElement> bEnumList;
       
  3243 	vector<EnumElement> cEnumList;
       
  3244 
       
  3245     for( int b = 0; b < base_enum_no; b++)
       
  3246 	{
       
  3247 		baseEnum = baseResource.enumList.at(b);
       
  3248 		
       
  3249 		if(baseEnum.enumName.size()<=0)
       
  3250 		{
       
  3251 			for(int k = 0; k < (int)baseEnum.enums.size(); k++)
       
  3252 			{
       
  3253 				baseEnumNameEmptyMemberList.push_back(baseEnum.enums.at(k));
       
  3254 			}
       
  3255 		}
       
  3256 		else
       
  3257 		{
       
  3258 			bEnumList.push_back(baseEnum);
       
  3259 		}
       
  3260 	}
       
  3261 
       
  3262 	for( int c = 0; c < cur_enum_no; c++)
       
  3263 	{
       
  3264 		curEnum = curResource.enumList.at(c);
       
  3265 		
       
  3266 		if(curEnum.enumName.size()<=0)
       
  3267 		{
       
  3268 			for(int k = 0; k < (int)curEnum.enums.size(); k++)
       
  3269 			{
       
  3270 				curEnumNameEmptyMemberList.push_back(curEnum.enums.at(k));
       
  3271 			}
       
  3272 		}
       
  3273 		else
       
  3274 		{
       
  3275 			cEnumList.push_back(curEnum);
       
  3276 		}
       
  3277 	}
       
  3278 
       
  3279 	// Compare and report issue for enum list with name
       
  3280 	for( int l = 0; l < (int) bEnumList.size(); l++)
       
  3281 	{
       
  3282 		baseEnum = bEnumList.at(l);
       
  3283 		bool enumFound = false;
       
  3284 
       
  3285 		for( int m = 0; m < (int)cEnumList.size(); m++ )
       
  3286 		{
       
  3287 			curEnum = cEnumList.at(m);
       
  3288 			if ( baseEnum.enumName == curEnum.enumName )
       
  3289 			{
       
  3290 				int bMemNo = (int)baseEnum.enums.size();
       
  3291 				int cMemNo = (int)curEnum.enums.size();
       
  3292 
       
  3293 				enumFound = true;
       
  3294 
       
  3295 				for ( int outer = 0; outer < bMemNo; outer++ )
       
  3296 				{
       
  3297 					bool enumMemFound = false;
       
  3298 					for( int inner = 0; inner < cMemNo; inner++ )
       
  3299 					{
       
  3300 						if(baseEnum.enums.at(outer).enumMemName == curEnum.enums.at(inner).enumMemName )
       
  3301 						{ 
       
  3302 							enumMemFound = true;
       
  3303 							// member name found
       
  3304 							if(baseEnum.enums.at(outer).enumVal.size() > 0 )
       
  3305 							{
       
  3306 								if (baseEnum.enums.at(outer).enumVal != curEnum.enums.at(inner).enumVal )
       
  3307 								{
       
  3308 									//add issue Member value changed
       
  3309 									string baseEnumVal = baseEnum.enumName +"::" + baseEnum.enums.at(outer).enumMemName;
       
  3310 									string curEnumVal = curEnum.enums.at(inner).enumVal;
       
  3311 									int lineNo = curEnum.enums.at(inner).lineNo;
       
  3312 
       
  3313 									report.addIssue(baseResource.RHFileName, baseEnumVal, EIssueIdentityEnumerationValue, EIssueTypeChangeInInitialisation, 
       
  3314 										ESeverityNULL, ESeveritySCBreak, curEnumVal, lineNo,curResource.RHFileName,"");
       
  3315 								}
       
  3316 							}
       
  3317 							break;
       
  3318 						}
       
  3319 					} // loop cur mems
       
  3320 
       
  3321 					if ( enumMemFound == false)
       
  3322 					{ 
       
  3323 						// Add Enum Member Missing
       
  3324 						string bMemName = baseEnum.enumName +"::" + baseEnum.enums.at(outer).enumMemName;
       
  3325 						int lineNo = curEnum.lineNo;
       
  3326 						report.addIssue(baseResource.RHFileName, bMemName, EIssueIdentityEnumerationValue, EIssueTypeRemoval, 
       
  3327 							ESeverityNULL, ESeveritySCBreak, "", lineNo,curResource.RHFileName,"");
       
  3328 
       
  3329 					}
       
  3330 				}// loop base mems
       
  3331 
       
  3332 				break;
       
  3333 			}// enum name matched
       
  3334 		}// loop cur enums
       
  3335 
       
  3336 		if (enumFound == false )
       
  3337 		{
       
  3338 			// Enum List missing
       
  3339 			string bEnum = baseEnum.enumName;
       
  3340 			string cEnum = curEnum.enumName;
       
  3341 			report.addIssue(baseResource.RHFileName, bEnum, EIssueIdentityEnumerationValue, EIssueTypeRemoval, 
       
  3342 				ESeverityNULL, ESeveritySCBreak, cEnum, 0,curResource.RHFileName,"");
       
  3343 		}
       
  3344 	}//base enums
       
  3345 
       
  3346 	// Now check for enum list with no enum name, in this case check member name and value
       
  3347 	if(baseEnumNameEmptyMemberList.size() > 0)
       
  3348 	{
       
  3349 		EnumMember bEnumMem;
       
  3350 		for(unsigned long i = 0; i < (unsigned long)baseEnumNameEmptyMemberList.size(); i++)
       
  3351 		{
       
  3352 			bEnumMem = baseEnumNameEmptyMemberList.at(i);
       
  3353 			EnumMember cEnumMem;
       
  3354 			bool enumMemFound = false;
       
  3355 			for(unsigned long j = 0; j <(unsigned long) curEnumNameEmptyMemberList.size(); j++ )
       
  3356 			{
       
  3357 				cEnumMem = curEnumNameEmptyMemberList.at(j);
       
  3358 				if(bEnumMem.enumMemName == cEnumMem.enumMemName)
       
  3359 				{
       
  3360 					enumMemFound = true;
       
  3361 					if(bEnumMem.enumVal != cEnumMem.enumVal )
       
  3362 					{
       
  3363 						//add issue enum value changed 
       
  3364 						string baseEnumVal = "::" + bEnumMem.enumMemName;
       
  3365 						string curEnumVal = cEnumMem.enumMemName;
       
  3366 						int lineNo = cEnumMem.lineNo;
       
  3367 
       
  3368 						report.addIssue(baseResource.RHFileName, baseEnumVal, EIssueIdentityEnumerationValue, EIssueTypeChangeInInitialisation, 
       
  3369 							ESeverityNULL, ESeveritySCBreak, curEnumVal, lineNo,curResource.RHFileName,"");
       
  3370 					}
       
  3371 					break;
       
  3372 				}
       
  3373 			}
       
  3374 			if(enumMemFound == false)
       
  3375 			{
       
  3376 				// add issue enum mem mising
       
  3377 				string bMemName = "::" + bEnumMem.enumMemName;
       
  3378 				report.addIssue(baseResource.RHFileName, bMemName, EIssueIdentityEnumerationValue, EIssueTypeRemoval, 
       
  3379 					ESeverityNULL, ESeveritySCBreak, "", 0,curResource.RHFileName,"");
       
  3380 			}
       
  3381 		}
       
  3382 	}
       
  3383 
       
  3384 
       
  3385 	// --------------------- Macro Comparision --------------
       
  3386 
       
  3387 	for (int p = 0; p < base_macro_no; p++ )
       
  3388 	{
       
  3389 		bool macroFound = false;
       
  3390 		baseMacro = baseResource.macroList.at(p);
       
  3391 		for (int q = 0; q < cur_macro_no; q++ )
       
  3392 		{
       
  3393 			curMacro = curResource.macroList.at(q);
       
  3394 			if(baseMacro.macroName == curMacro.macroName )
       
  3395 			{ // check Macro value
       
  3396 				macroFound = true;
       
  3397 				if(baseMacro.macroVal != curMacro.macroVal )
       
  3398 				{
       
  3399 					//add issue macro value mismatch
       
  3400 					report.addIssue(baseResource.RHFileName, baseMacro.macroName, EIssueIdentityMacro, EIssueTypeChange, 
       
  3401 						ESeverityNULL, ESeveritySCBreak, curMacro.macroVal, curMacro.lineNo,curResource.RHFileName,"");
       
  3402 				}
       
  3403 				break; // macro name matched
       
  3404 			}
       
  3405 
       
  3406 		}
       
  3407 
       
  3408 		if (macroFound == false )
       
  3409 		{
       
  3410 			// add issue macro not found
       
  3411 			report.addIssue(baseResource.RHFileName, baseMacro.macroName, EIssueIdentityMacro, EIssueTypeRemoval, 
       
  3412 				ESeverityNULL, ESeveritySCBreak, "", 0,curResource.RHFileName,"");
       
  3413 		}
       
  3414 	}
       
  3415 
       
  3416 
       
  3417 
       
  3418 }
       
  3419