diff -r 000000000000 -r 638b9c697799 apicompatanamdw/compatanalysercmd/headeranalyser/src/MacroAnalyser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apicompatanamdw/compatanalysercmd/headeranalyser/src/MacroAnalyser.cpp Tue Jan 12 14:52:39 2010 +0530 @@ -0,0 +1,498 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "CmdGlobals.h" +#ifdef __WIN__ +#pragma warning(disable:4786) +#endif + +#include +#include +#include +#include +#include +#include "Utils.h" +#include "TChange.h" +#include "HAException.h" + +using namespace std; + +#include "MacroAnalyser.h" + +// ---------------------------------------------------------------------------- +// MacroAnalyser::MacroAnalyser +// ---------------------------------------------------------------------------- +// +MacroAnalyser::MacroAnalyser(string filebase, string filecurrent, vector basebundle, vector currentbundle) +:iBaseFile(filebase), iCurrentFile(filecurrent), iBaseBundle(basebundle), iCurrentBundle(currentbundle) +{ +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::~MacroAnalyser +// ---------------------------------------------------------------------------- +// +MacroAnalyser::~MacroAnalyser(void) +{ +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::Analyse +// ---------------------------------------------------------------------------- +// +void MacroAnalyser::Analyse(list& aMacroFiles) +{ + ifstream basefile(iBaseFile.c_str(), ios::in); + ifstream currentfile(iCurrentFile.c_str(), ios::in); + + map,string> > > baseline; + map,string> > > current; + + baseline = parseMacros(basefile, iBaseBundle, &iRemoved, true); + current = parseMacros(currentfile, iCurrentBundle); + + vector::iterator curbegin = iCurrentBundle.begin(); + vector::iterator curend = iCurrentBundle.end(); + vector::iterator basebegin = iBaseBundle.begin(); + vector::iterator baseend = iBaseBundle.end(); + map > > >::iterator removedbegin; + for(;curbegin != curend; curbegin++) + { + string curfilename = *curbegin; + string basefilename; + if( basebegin != iBaseBundle.end() ) + { + basefilename = *basebegin; + } + else + { + continue; + } + removedbegin = iRemoved.find(basefilename); + if (removedbegin != iRemoved.end()) + { + map,string> > >::iterator cur = current.find(curfilename); + if (cur == current.end()) // We need to check if there is a list with given filename + // because they aren't created in situation where there isn't any macros + { // specific to that file or the include guard for the file is duplicated. + list,string> > tempvar; + pair,string> > > tempvar2(curfilename, tempvar); + pair,string> > >::iterator, bool > pos = current.insert(tempvar2); + if (pos.second == true) + { + cur = pos.first; + } else + { // this shouldn't be happening + throw HAException("Problems ahead."); + } + } + map,string> > >::iterator base = baseline.find(basefilename); + findDuplicates(basefilename,curfilename,base->second, cur->second, removedbegin->second, iBaseDuplicates, iCurrentDuplicates); + + //maintain a cache list of files with macros + if(base->second.size() > 0) + aMacroFiles.push_back(toLowerCaseWin(base->first)); + if(cur->second.size() > 0) + aMacroFiles.push_back(toLowerCaseWin(cur->first)); + + // After next loop we will have in list only those which has been either removed or changed + list,string> >::iterator begin = cur->second.begin(); + list,string> >::iterator end = cur->second.end(); + for(;begin != end; begin++) + { + list >::iterator place = FindFromList(begin->first.first, removedbegin->second.GetValue()); + if (place != removedbegin->second.GetValue().end()) + { + removedbegin->second.GetValue().erase(place); // we found macro with same name so we can remove it + list,string> > baselist = base->second; + list,string> >::iterator found = FindFromList(begin->first.first, baselist, ELeftValue); + if (found != baselist.end()) + { + if (found->first.second != begin->first.second) + { // Contents of macro are different so we need to add the macro to changed list + pair,string> changes; + changes.first.first = found->first.second; + changes.first.second = begin->first.second; + changes.second = begin->second; + pair,string> > param(begin->first.first,changes); + map,string> > > >::iterator file = iChanged.find(basefilename); + if (file != iChanged.end()) + { + file->second.GetValue().insert(param); + } else + { + map,string> > tempvar; + tempvar.insert(param); + TChange,string> > > tempvar2(basefilename, curfilename, tempvar); + pair,string> > > > tempvar3(basefilename, tempvar2); + iChanged.insert(tempvar3); + } + } + } + } + } + removedbegin->second.SetCurrent(curfilename); + } + basebegin++; + } +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::FindMacro +// ---------------------------------------------------------------------------- +// +pair MacroAnalyser::FindMacro(string aLine) +{ + pair ret; + string::size_type pos = aLine.find_first_of(" \t"); + while(pos != string::npos && (aLine.at(pos) == ' ' || aLine.at(pos) == '\t') ) + pos++; + string::size_type param_pos = pos ; + pos = aLine.find_first_of(" \t(",param_pos); + string value; + if (pos != string::npos && aLine.at(pos) == '(') + { + pos = aLine.find(')',pos); + if(pos !=string::npos ) + pos++; + } + if (pos != string::npos && pos < aLine.size()) + { // only if there is stuff after name of macro we put it to value + size_t value_pos = (unsigned int)pos + 1; + value = aLine.substr(value_pos); + value = trimWhiteSpace(value); + if (value.size() != 0) + { + value_pos = value.find_first_not_of(" \t"); + if (value_pos != string::npos && value_pos != 0) + { + value = value.substr(value_pos); + } + } + } else + { // otherwise we put empty value + value = ""; + } + + string param = aLine.substr(param_pos, pos - param_pos); + ret = pair(param,value); + return ret; +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::getRemoved +// ---------------------------------------------------------------------------- +// +map > > >& MacroAnalyser::getRemoved() +{ + return iRemoved; +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::FindMacro +// readParameters should be called so that first is called baseline command +// and after that current command, otherwise it doesn't work +// ---------------------------------------------------------------------------- +// +map,string> > > >& MacroAnalyser::getChanged() +{ + return iChanged; +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::getBaseDuplicates +// ---------------------------------------------------------------------------- +// +map > >& MacroAnalyser::getBaseDuplicates() +{ + return iBaseDuplicates; +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::getCurrentDuplicates +// ---------------------------------------------------------------------------- +// +map > >& MacroAnalyser::getCurrentDuplicates() +{ + return iCurrentDuplicates; +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::parseMacros +// ---------------------------------------------------------------------------- +// +map,string> > > MacroAnalyser::parseMacros(ifstream& aFile, vector& bundlefiles, map > > >* aRemoved, bool aAddToRemoved) +{ + // ret, is the file and related set of macros returned by the function + map,string> > > ret; + vector > files; + vector::iterator bundlefile = bundlefiles.begin(); + vector::iterator bundleend = bundlefiles.end(); + for(; bundlefile != bundleend; bundlefile++) + { + pair bothcase(toLowerCaseWin(*bundlefile), *bundlefile); + files.push_back(bothcase); + } + // Read macrofiles as lines + string cline; + string levelname = ""; + bool isbundle = false; + while((cline = getLine(aFile)) != KEmpty) + { + string line = cline; + char tempNo[6]; + string lineNo; + unsigned int length = (unsigned int)line.length(); + if (length > 6 && line.at(0) == '#' && line.at(1) == ' ') + { // we may have found a file descriptor: '# xx "path/to/file.h"' or + // '# xx "path/to/file.h" 1' or '# xx "path/to/file.h" 2' + unsigned int index; + int count = 0; + for(index = 2; index < length; index++) + { + char ch = line.at(index); + if (ch < '0' || ch > '9') + break; + else + { + tempNo[count] = ch; + count++; + } + } + tempNo[count] = '\0'; + lineNo.copy(tempNo,strlen(tempNo)); + index++; + if (index < length) + { + unsigned int index2 = index + 1; + for(; index2 < length; index2++) + { + char ch = line.at(index2); + if (ch == '"') break; + } + if (length > index2 + 1) + { + levelname = line.substr(index + 1, index2 - index - 1); + } else + { + levelname = line.substr(index + 1, length - index - 2); + } + string correctedname = ""; + string::size_type start = 0; + string::size_type pos = levelname.find_first_of("\\/"); + while(pos != string::npos) + { + correctedname += levelname.substr(start, pos - start); + correctedname += DIR_SEPARATOR; + start = pos + 1; + pos = levelname.find_first_of("\\/", start); + } + // found the levelname; filename + correctedname += levelname.substr(start); + levelname = toLowerCaseWin(correctedname); + + vector >::iterator begin = files.begin(); + vector >::iterator end = files.end(); + + isbundle = false; + for(; begin != end; begin++) + { + if (begin->first == levelname) + { + isbundle = true; + levelname = begin->second; + break; + } + } + } + } + else if (isbundle == true && length > 8 && line.substr(0, 8) == "#define ") + { // we found preprocessor directive #define + pair macro = FindMacro(line); + // 'ret' contains the set of files and associated macros to be returned from function + map,string> > >::iterator found = ret.find(levelname); + bool exist = false; + if( found != ret.end()) + { + list< pair,string> >::iterator start = found->second.begin(); + list< pair,string> >::iterator end = found->second.end(); + + // check if this macro is already defined, within this file(levelname) + while(start != end) + { + if( macro.first == start->first.first ) + exist = true; + start++; + } + } + // if macro not found, add it to the list of macros associated with the current file + if( !exist ) + { + pair,string> tempVal(macro,tempNo); + // if file already defined, only add the macro + if (found != ret.end()) + { + found->second.push_back(tempVal); + } + // else add both filename and asssociated macro + else + { + list,string> > values; + values.push_back(tempVal); + pair,string> > > newfile(levelname, values); + ret.insert(newfile); + } + // perform the same test as above on aRemoved data structure + // this will be used for finding any duplicate macro definitions + if (aAddToRemoved == true) + { + pair temp(macro.first,tempNo); + map > > >::iterator found2 = aRemoved->find(levelname); + if (found2 != aRemoved->end()) + { + found2->second.GetValue().push_back(temp); + } else + { + list > values; + values.push_back(temp); + TChange > > tempvar(levelname, values); + pair > > > newfile(levelname, tempvar); + aRemoved->insert(newfile); + } + } + } //if(!exist) + } + } + return ret; +} + +// ---------------------------------------------------------------------------- +// MacroAnalyser::findDuplicates +// ---------------------------------------------------------------------------- +// +bool MacroAnalyser::findDuplicates(const string& basefilename, const string& currentfilename, list,string> >& aBaseline, list,string> >& aCurrent, TChange > >& aRemovedList, map > >& baselinedup, map > >& currentdup) +{ + bool ret = false; + map, int> dups; + list,string> >::iterator begin = aBaseline.begin(); + list,string> >::iterator end = aBaseline.end(); + bool found = false; + while(begin != end) + { + found = false; + list,string> >::iterator duplicates = begin; + duplicates++; + string original = begin->first.first; + pair original1(original,begin->second); + while(duplicates != end) + { + if (original == duplicates->first.first) + { + found = true; + pair, int> tempvar(original1, 1); + dups.insert(tempvar); + duplicates = aBaseline.erase(duplicates); + } else + { + duplicates++; + } + } + if(found) + { + ret = true; + aRemovedList.GetValue().remove(original1); + begin = aBaseline.erase(begin); + } + begin++; + } + + if (dups.size() != 0) + { + vector > values; + values.reserve(dups.size()); + map, int>::iterator dupsbegin = dups.begin(); + map, int>::iterator dupsend = dups.end(); + for(; dupsbegin != dupsend; dupsbegin++) + { + values.push_back(dupsbegin->first); + } + pair > > tempvar(basefilename, values); + baselinedup.insert(tempvar); + } + + dups.clear(); + begin = aCurrent.begin(); + end = aCurrent.end(); + while(begin != end) + { + found = false; + list,string> >::iterator duplicates = begin; + duplicates++; + string original = begin->first.first; + pair original1(original,begin->second); + while(duplicates != end) + { + if (original == duplicates->first.first) + { + found = true; + pair, int> tempvar(original1, 1); + dups.insert(tempvar); + duplicates = aCurrent.erase(duplicates); + } else + { + duplicates++; + } + } + if (found == true) + { + ret = true; + begin = aCurrent.erase(begin); + } else + { + begin++; + } + } + + if (dups.size() != 0) + { + vector > values; + values.reserve(dups.size()); + map, int>::iterator dupsbegin = dups.begin(); + map, int>::iterator dupsend = dups.end(); + for(; dupsbegin != dupsend; dupsbegin++) + { + string macroname = dupsbegin->first.first; + pair tempVal (macroname,dupsbegin->first.second); + begin = aBaseline.begin(); + end = aBaseline.end(); + for(; begin != end; begin++) + { // we have to remove all macros, which have duplicates in current, from baseline + // so that there won't be unnecessary warnings of removed macros + if (begin->first.first == macroname) + { + aBaseline.erase(begin); + break; + } + } + values.push_back(tempVal); + } + pair > > tempvar(currentfilename, values); + currentdup.insert(tempvar); + } + return ret; +}