apicompatanamdw/compatanalysercmd/headeranalyser/src/MacroAnalyser.cpp
changeset 0 638b9c697799
child 12 a0eee409ff14
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 
       
    24 #include <iostream>
       
    25 #include <fstream>
       
    26 #include <string>
       
    27 #include <map>
       
    28 #include <list>
       
    29 #include "Utils.h"
       
    30 #include "TChange.h"
       
    31 #include "HAException.h"
       
    32 
       
    33 using namespace std;
       
    34 
       
    35 #include "MacroAnalyser.h"
       
    36 
       
    37 // ----------------------------------------------------------------------------
       
    38 // MacroAnalyser::MacroAnalyser
       
    39 // ----------------------------------------------------------------------------
       
    40 //
       
    41 MacroAnalyser::MacroAnalyser(string filebase, string filecurrent, vector<string> basebundle, vector<string> currentbundle)
       
    42 :iBaseFile(filebase), iCurrentFile(filecurrent), iBaseBundle(basebundle), iCurrentBundle(currentbundle)
       
    43 {
       
    44 }
       
    45 
       
    46 // ----------------------------------------------------------------------------
       
    47 // MacroAnalyser::~MacroAnalyser
       
    48 // ----------------------------------------------------------------------------
       
    49 //
       
    50 MacroAnalyser::~MacroAnalyser(void)
       
    51 {
       
    52 }
       
    53 
       
    54 // ----------------------------------------------------------------------------
       
    55 // MacroAnalyser::Analyse
       
    56 // ----------------------------------------------------------------------------
       
    57 //
       
    58 void MacroAnalyser::Analyse(list<string>& aMacroFiles)
       
    59 {  
       
    60     ifstream basefile(iBaseFile.c_str(), ios::in);
       
    61     ifstream currentfile(iCurrentFile.c_str(), ios::in);
       
    62 
       
    63     map<string, list<pair<pair<string, string>,string> > > baseline;
       
    64     map<string, list<pair<pair<string, string>,string> > > current;
       
    65     
       
    66     baseline = parseMacros(basefile, iBaseBundle, &iRemoved, true);
       
    67     current = parseMacros(currentfile, iCurrentBundle);
       
    68     
       
    69     vector<string>::iterator curbegin = iCurrentBundle.begin();
       
    70     vector<string>::iterator curend = iCurrentBundle.end();
       
    71     vector<string>::iterator basebegin = iBaseBundle.begin();
       
    72     vector<string>::iterator baseend = iBaseBundle.end();
       
    73     map<string, TChange<list<pair<string,string> > > >::iterator removedbegin;
       
    74     for(;curbegin != curend; curbegin++)
       
    75     {
       
    76         string curfilename = *curbegin;
       
    77         string basefilename;
       
    78         if( basebegin != iBaseBundle.end() )
       
    79         {
       
    80             basefilename = *basebegin;
       
    81         }
       
    82         else
       
    83         {
       
    84             continue;
       
    85         }
       
    86         removedbegin = iRemoved.find(basefilename);
       
    87         if (removedbegin != iRemoved.end())
       
    88         {
       
    89             map<string, list<pair<pair<string, string>,string> > >::iterator cur = current.find(curfilename);
       
    90             if (cur == current.end())       // We need to check if there is a list with given filename
       
    91                                             // because they aren't created in situation where there isn't any macros
       
    92             {                               // specific to that file or the include guard for the file is duplicated.
       
    93                 list<pair<pair<string, string>,string> > tempvar;
       
    94                 pair<string, list<pair<pair<string, string>,string> > > tempvar2(curfilename, tempvar);
       
    95                 pair<map<string, list<pair<pair<string, string>,string> > >::iterator, bool > pos = current.insert(tempvar2);
       
    96                 if (pos.second == true)
       
    97                 {
       
    98                     cur = pos.first;
       
    99                 } else
       
   100                 {                           // this shouldn't be happening
       
   101                     throw HAException("Problems ahead.");
       
   102                 }
       
   103             }
       
   104             map<string, list<pair<pair<string, string>,string> > >::iterator base = baseline.find(basefilename);
       
   105             findDuplicates(basefilename,curfilename,base->second, cur->second, removedbegin->second, iBaseDuplicates, iCurrentDuplicates);
       
   106             
       
   107 			//maintain a cache list of files with macros
       
   108 			if(base->second.size() > 0)
       
   109 				aMacroFiles.push_back(toLowerCaseWin(base->first));
       
   110 			if(cur->second.size() > 0)
       
   111 				aMacroFiles.push_back(toLowerCaseWin(cur->first));
       
   112 			
       
   113 			// After next loop we will have in list only those which has been either removed or changed
       
   114             list<pair<pair<string, string>,string> >::iterator begin = cur->second.begin();
       
   115             list<pair<pair<string, string>,string> >::iterator end = cur->second.end();
       
   116             for(;begin != end; begin++)
       
   117             {
       
   118 				list<pair<string,string> >::iterator place = FindFromList(begin->first.first, removedbegin->second.GetValue());
       
   119                 if (place != removedbegin->second.GetValue().end())
       
   120                 {
       
   121                     removedbegin->second.GetValue().erase(place);  // we found macro with same name so we can remove it
       
   122                     list<pair<pair<string, string>,string> > baselist = base->second;
       
   123 					list<pair<pair<string, string>,string> >::iterator found = FindFromList(begin->first.first, baselist, ELeftValue);
       
   124                     if (found != baselist.end())
       
   125                     {
       
   126 						if (found->first.second != begin->first.second)
       
   127                         {   // Contents of macro are different so we need to add the macro to changed list
       
   128                             pair<pair<string,string>,string> changes;
       
   129 							changes.first.first = found->first.second;
       
   130 							changes.first.second = begin->first.second;
       
   131 							changes.second = begin->second;
       
   132 							pair<string, pair<pair<string, string>,string> > param(begin->first.first,changes);
       
   133                             map<string, TChange<map<string, pair<pair<string, string>,string> > > >::iterator file = iChanged.find(basefilename);
       
   134                             if (file != iChanged.end())
       
   135                             {
       
   136                                 file->second.GetValue().insert(param);
       
   137                             } else
       
   138                             {
       
   139                                 map<string, pair<pair<string, string>,string> > tempvar;
       
   140                                 tempvar.insert(param);
       
   141                                 TChange<map<string, pair<pair<string, string>,string> > > tempvar2(basefilename, curfilename, tempvar);
       
   142                                 pair<string, TChange<map<string, pair<pair<string, string>,string> > > > tempvar3(basefilename, tempvar2);
       
   143                                 iChanged.insert(tempvar3);
       
   144                             }
       
   145                         }
       
   146                     }
       
   147                 }
       
   148             }
       
   149             removedbegin->second.SetCurrent(curfilename);
       
   150         }
       
   151         basebegin++;
       
   152     }  
       
   153 }
       
   154 
       
   155 // ----------------------------------------------------------------------------
       
   156 // MacroAnalyser::FindMacro
       
   157 // ----------------------------------------------------------------------------
       
   158 //
       
   159 pair<string, string> MacroAnalyser::FindMacro(string aLine)
       
   160 {
       
   161     pair<string, string> ret;
       
   162     string::size_type pos = aLine.find_first_of(" \t");
       
   163     while(pos != string::npos && (aLine.at(pos) == ' ' || aLine.at(pos) == '\t') )
       
   164         pos++;
       
   165     string::size_type param_pos = pos ;
       
   166     pos = aLine.find_first_of(" \t(",param_pos);
       
   167     string value;
       
   168     if (pos != string::npos && aLine.at(pos) == '(')
       
   169     {
       
   170         pos = aLine.find(')',pos);
       
   171         if(pos !=string::npos )
       
   172             pos++;
       
   173     }
       
   174     if (pos != string::npos && pos < aLine.size())
       
   175     {   // only if there is stuff after name of macro we put it to value
       
   176         size_t value_pos = (unsigned int)pos + 1;
       
   177         value = aLine.substr(value_pos);
       
   178         value = trimWhiteSpace(value);
       
   179         if (value.size() != 0)
       
   180         {
       
   181             value_pos = value.find_first_not_of(" \t");
       
   182             if (value_pos != string::npos && value_pos != 0)
       
   183             {
       
   184                 value = value.substr(value_pos);
       
   185             }
       
   186         }
       
   187     } else
       
   188     {   // otherwise we put empty value
       
   189         value = "";
       
   190     }
       
   191 
       
   192     string param = aLine.substr(param_pos, pos - param_pos);
       
   193     ret = pair<string,string>(param,value);
       
   194     return ret;
       
   195 }
       
   196 
       
   197 // ----------------------------------------------------------------------------
       
   198 // MacroAnalyser::getRemoved
       
   199 // ----------------------------------------------------------------------------
       
   200 //
       
   201 map<string, TChange<list<pair<string,string> > > >& MacroAnalyser::getRemoved()
       
   202 {
       
   203     return iRemoved;
       
   204 }
       
   205 
       
   206 // ----------------------------------------------------------------------------
       
   207 // MacroAnalyser::FindMacro
       
   208 // readParameters should be called so that first is called baseline command
       
   209 // and after that current command, otherwise it doesn't work
       
   210 // ----------------------------------------------------------------------------
       
   211 //
       
   212 map<string, TChange<map<string, pair<pair<string, string>,string> > > >& MacroAnalyser::getChanged()
       
   213 {
       
   214     return iChanged;
       
   215 }
       
   216 
       
   217 // ----------------------------------------------------------------------------
       
   218 // MacroAnalyser::getBaseDuplicates
       
   219 // ----------------------------------------------------------------------------
       
   220 //
       
   221 map<string, vector<pair<string,string> > >& MacroAnalyser::getBaseDuplicates()
       
   222 {
       
   223     return iBaseDuplicates;
       
   224 }
       
   225 
       
   226 // ----------------------------------------------------------------------------
       
   227 // MacroAnalyser::getCurrentDuplicates
       
   228 // ----------------------------------------------------------------------------
       
   229 //
       
   230 map<string, vector<pair<string,string> > >& MacroAnalyser::getCurrentDuplicates()
       
   231 {
       
   232     return iCurrentDuplicates;
       
   233 }
       
   234 
       
   235 // ----------------------------------------------------------------------------
       
   236 // MacroAnalyser::parseMacros
       
   237 // ----------------------------------------------------------------------------
       
   238 //
       
   239 map<string, list<pair<pair<string, string>,string> > > MacroAnalyser::parseMacros(ifstream& aFile, vector<string>& bundlefiles, map<string, TChange<list<pair<string,string> > > >* aRemoved, bool aAddToRemoved)
       
   240 {
       
   241     // ret, is the file and related set of macros returned by the function
       
   242     map<string, list<pair<pair<string, string>,string> > > ret;
       
   243     vector<pair<string, string> > files;
       
   244     vector<string>::iterator bundlefile = bundlefiles.begin();
       
   245     vector<string>::iterator bundleend = bundlefiles.end();
       
   246     for(; bundlefile != bundleend; bundlefile++)
       
   247     {
       
   248         pair<string, string> bothcase(toLowerCaseWin(*bundlefile), *bundlefile);
       
   249         files.push_back(bothcase);
       
   250     }
       
   251     // Read macrofiles as lines
       
   252     string cline;
       
   253     string levelname = "";
       
   254     bool isbundle = false;
       
   255     while((cline = getLine(aFile)) != KEmpty)
       
   256     {
       
   257         string line = cline;
       
   258 		char tempNo[6];
       
   259 		string lineNo;
       
   260         unsigned int length = (unsigned int)line.length();
       
   261         if (length > 6 && line.at(0) == '#' && line.at(1) == ' ')
       
   262         {   // we may have found a file descriptor: '# xx "path/to/file.h"' or
       
   263             // '# xx "path/to/file.h" 1' or '# xx "path/to/file.h" 2'
       
   264             unsigned int index;
       
   265 			int count = 0;
       
   266             for(index = 2; index < length; index++)
       
   267             {
       
   268                 char ch = line.at(index);
       
   269                 if (ch < '0' || ch > '9')
       
   270 					break;
       
   271 				else
       
   272 				{
       
   273 					tempNo[count] = ch;
       
   274 					count++;
       
   275 				}
       
   276             }
       
   277 			tempNo[count] = '\0';
       
   278 			lineNo.copy(tempNo,strlen(tempNo));
       
   279             index++;
       
   280             if (index < length)
       
   281             {
       
   282                 unsigned int index2 = index + 1;
       
   283                 for(; index2 < length; index2++)
       
   284                 {
       
   285                     char ch = line.at(index2);
       
   286                     if (ch == '"') break;
       
   287                 }
       
   288                 if (length > index2 + 1)
       
   289                 {
       
   290                     levelname = line.substr(index + 1, index2 - index - 1);
       
   291                 } else
       
   292                 {
       
   293                     levelname = line.substr(index + 1, length - index - 2);
       
   294                 }
       
   295                 string correctedname = "";
       
   296                 string::size_type start = 0;
       
   297                 string::size_type pos = levelname.find_first_of("\\/");
       
   298                 while(pos != string::npos)
       
   299                 {
       
   300                     correctedname += levelname.substr(start, pos - start);
       
   301                     correctedname += DIR_SEPARATOR;
       
   302                     start = pos + 1;
       
   303                     pos = levelname.find_first_of("\\/", start);
       
   304                 }
       
   305                 // found the levelname; filename
       
   306                 correctedname += levelname.substr(start);
       
   307                 levelname = toLowerCaseWin(correctedname);
       
   308 
       
   309                 vector<pair<string, string> >::iterator begin = files.begin();
       
   310                 vector<pair<string, string> >::iterator end = files.end();
       
   311                 
       
   312                 isbundle = false;
       
   313                 for(; begin != end; begin++)
       
   314                 {
       
   315                     if (begin->first == levelname)
       
   316                     {
       
   317                         isbundle = true;
       
   318                         levelname = begin->second;
       
   319                         break;
       
   320                     }
       
   321                 }
       
   322             }
       
   323         }
       
   324         else if (isbundle == true && length > 8 && line.substr(0, 8) == "#define ")
       
   325         {   // we found preprocessor directive #define
       
   326             pair<string,string> macro = FindMacro(line);
       
   327             // 'ret' contains the set of files and associated macros to be returned from function
       
   328             map<string, list<pair<pair<string, string>,string> > >::iterator found = ret.find(levelname);
       
   329             bool exist = false;
       
   330             if( found != ret.end())
       
   331             {
       
   332 				list< pair<pair<string, string>,string> >::iterator start = found->second.begin();
       
   333 				list< pair<pair<string, string>,string> >::iterator end = found->second.end();
       
   334 				
       
   335                 // check if this macro is already defined, within this file(levelname)
       
   336                 while(start != end)
       
   337                 {
       
   338 					if( macro.first == start->first.first )
       
   339                     exist = true;
       
   340                     start++;
       
   341                 }
       
   342             }
       
   343             // if macro not found, add it to the list of macros associated with the current file
       
   344             if( !exist )
       
   345             {
       
   346 				pair<pair<string,string>,string> tempVal(macro,tempNo);
       
   347 				// if file already defined, only add the macro
       
   348                 if (found != ret.end())
       
   349                 {
       
   350 					found->second.push_back(tempVal);
       
   351                 }
       
   352                 // else add both filename and asssociated macro
       
   353                 else
       
   354                 {				
       
   355                     list<pair<pair<string, string>,string> > values;
       
   356 					values.push_back(tempVal);
       
   357                     pair<string, list<pair<pair<string, string>,string> > > newfile(levelname, values);
       
   358                     ret.insert(newfile);
       
   359                 }
       
   360                 // perform the same test as above on aRemoved data structure
       
   361                 // this will be used for finding any duplicate macro definitions
       
   362                 if (aAddToRemoved == true)
       
   363                 {
       
   364 					pair<string,string> temp(macro.first,tempNo);
       
   365                     map<string, TChange<list<pair<string,string> > > >::iterator found2 = aRemoved->find(levelname);
       
   366                     if (found2 != aRemoved->end())
       
   367                     {
       
   368                         found2->second.GetValue().push_back(temp);
       
   369                     } else
       
   370                     {
       
   371                         list<pair<string,string> > values;
       
   372                         values.push_back(temp);
       
   373                         TChange<list<pair<string,string> > > tempvar(levelname, values);
       
   374                         pair<string, TChange<list<pair<string,string> > > > newfile(levelname, tempvar);
       
   375                         aRemoved->insert(newfile);
       
   376                     }
       
   377                 }
       
   378              } //if(!exist)
       
   379         }
       
   380     }
       
   381     return ret;
       
   382 }
       
   383 
       
   384 // ----------------------------------------------------------------------------
       
   385 // MacroAnalyser::findDuplicates
       
   386 // ----------------------------------------------------------------------------
       
   387 //
       
   388 bool MacroAnalyser::findDuplicates(const string& basefilename, const string& currentfilename, list<pair<pair<string, string>,string> >& aBaseline, list<pair<pair<string, string>,string> >& aCurrent, TChange<list<pair<string,string> > >& aRemovedList, map<string, vector<pair<string,string> > >& baselinedup, map<string, vector<pair<string,string> > >& currentdup)
       
   389 {
       
   390     bool ret = false;
       
   391     map<pair<string,string>, int> dups;
       
   392     list<pair<pair<string, string>,string> >::iterator begin = aBaseline.begin();
       
   393     list<pair<pair<string, string>,string> >::iterator end = aBaseline.end();
       
   394     bool found = false;
       
   395     while(begin != end)
       
   396     {
       
   397         found = false;
       
   398         list<pair<pair<string, string>,string> >::iterator duplicates = begin;
       
   399         duplicates++;
       
   400 		string original = begin->first.first;
       
   401 		pair<string,string> original1(original,begin->second);
       
   402         while(duplicates != end)
       
   403         {
       
   404 			if (original == duplicates->first.first)
       
   405             {
       
   406                 found = true;
       
   407                 pair<pair<string,string>, int> tempvar(original1, 1);
       
   408                 dups.insert(tempvar);
       
   409                 duplicates = aBaseline.erase(duplicates);
       
   410             } else
       
   411             {
       
   412                 duplicates++;
       
   413             }
       
   414         }
       
   415         if(found)
       
   416         {
       
   417             ret = true;
       
   418             aRemovedList.GetValue().remove(original1);
       
   419             begin = aBaseline.erase(begin);
       
   420         } 
       
   421 		    begin++;
       
   422     }
       
   423 
       
   424     if (dups.size() != 0)
       
   425     {
       
   426         vector<pair<string,string> > values;
       
   427         values.reserve(dups.size());
       
   428         map<pair<string,string>, int>::iterator dupsbegin = dups.begin();
       
   429         map<pair<string,string>, int>::iterator dupsend = dups.end();
       
   430         for(; dupsbegin != dupsend; dupsbegin++)
       
   431         {
       
   432             values.push_back(dupsbegin->first);
       
   433         }
       
   434         pair<string, vector<pair<string,string> > > tempvar(basefilename, values);
       
   435         baselinedup.insert(tempvar);
       
   436     }
       
   437 
       
   438     dups.clear();
       
   439     begin = aCurrent.begin();
       
   440     end = aCurrent.end();
       
   441     while(begin != end)
       
   442     {
       
   443         found = false;
       
   444         list<pair<pair<string, string>,string> >::iterator duplicates = begin;
       
   445         duplicates++;
       
   446 		string original = begin->first.first;
       
   447 		pair<string,string> original1(original,begin->second);
       
   448         while(duplicates != end)
       
   449         {
       
   450 			if (original == duplicates->first.first)
       
   451             {
       
   452                 found = true;
       
   453                 pair<pair<string,string>, int> tempvar(original1, 1);
       
   454                 dups.insert(tempvar);
       
   455                 duplicates = aCurrent.erase(duplicates);
       
   456             } else
       
   457             {
       
   458                 duplicates++;
       
   459             }
       
   460         }
       
   461         if (found == true)
       
   462         {
       
   463             ret = true;
       
   464             begin = aCurrent.erase(begin);
       
   465         } else
       
   466         {
       
   467             begin++;
       
   468         }
       
   469     }
       
   470 
       
   471     if (dups.size() != 0)
       
   472     {
       
   473         vector<pair<string,string> > values;
       
   474         values.reserve(dups.size());
       
   475         map<pair<string,string>, int>::iterator dupsbegin = dups.begin();
       
   476         map<pair<string,string>, int>::iterator dupsend = dups.end();
       
   477         for(; dupsbegin != dupsend; dupsbegin++)
       
   478         {
       
   479 			string macroname = dupsbegin->first.first;
       
   480 			pair<string,string> tempVal (macroname,dupsbegin->first.second);
       
   481             begin = aBaseline.begin();
       
   482             end = aBaseline.end();
       
   483             for(; begin != end; begin++)
       
   484             {   // we have to remove all macros, which have duplicates in current, from baseline
       
   485                 // so that there won't be unnecessary warnings of removed macros
       
   486                 if (begin->first.first == macroname)
       
   487                 {
       
   488                     aBaseline.erase(begin);
       
   489                     break;
       
   490                 }
       
   491             }
       
   492             values.push_back(tempVal);
       
   493         }
       
   494         pair<string, vector<pair<string,string> > > tempvar(currentfilename, values);
       
   495         currentdup.insert(tempvar);
       
   496     }
       
   497     return ret;
       
   498 }