apicompatanamdw/compatanalysercmd/libraryanalyser/src/la_analysis.cpp
changeset 0 638b9c697799
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apicompatanamdw/compatanalysercmd/libraryanalyser/src/la_analysis.cpp	Tue Jan 12 14:52:39 2010 +0530
@@ -0,0 +1,1161 @@
+/*
+* Copyright (c) 2007-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:  Functionality of analysis 
+*
+*/
+
+
+#include "la.hpp"
+#include "la_parser.hpp"
+#include "xmlprocessor.hpp"
+#include "xmldomainmap.hpp"
+#include "xmlsaxparser.hpp"
+#include "xmlnode.hpp"
+#include "xmlsaxhandler.hpp"
+#include "xmlsaxerrorhandler.hpp"
+
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+typedef XMLSAXHandler<XMLDomainMap<XMLNode> > DOCHANDLER;
+typedef XMLSAXErrorHandler ERRORHANDLER;
+typedef XMLSAXParser<DOCHANDLER, ERRORHANDLER> PARSER;
+typedef XMLProcessor<PARSER> XMLEngine;
+
+
+int XmlTools::initialiseDOM()
+{
+    try
+    {
+        XMLPlatformUtils::Initialize();
+    } catch (const XMLException& e )
+    {
+        char* message = _X( e.getMessage() );
+        cout << "Error during initialization! :\n" << message << endl ;
+        _XX(message);
+		    return -1;
+    }
+
+    DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation( _X("Core") );
+    iParser = ((DOMImplementationLS*)impl)->createDOMBuilder( DOMImplementationLS::MODE_SYNCHRONOUS, 0 );
+    if ( iParser->canSetFeature( XMLUni::fgDOMValidation, true ) )
+        iParser->setFeature( XMLUni::fgDOMValidation, true );
+    if ( iParser->canSetFeature( XMLUni::fgDOMNamespaces, true ) )
+        iParser->setFeature( XMLUni::fgDOMNamespaces, true );
+    if ( iParser->canSetFeature( XMLUni::fgDOMDatatypeNormalization, true ) )
+        iParser->setFeature( XMLUni::fgDOMDatatypeNormalization, true );
+        
+    return 0;
+}
+
+void XmlTools::uninitialiseDOM()
+{
+    iParser->release();
+    XMLPlatformUtils::Terminate();
+}
+
+XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* XmlTools::readFile( const char* aFilename )
+{
+	XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* doc;
+    DOMErrorHandler* myErrorHandler;
+
+    fstream ifile;
+    bool validate = false;
+    
+    string filedoctype;
+    string doctype("<!DOCTYPE");
+    
+    //check if a document type definition is provided for the xml file
+    ifile.open(aFilename);  
+    ifile >> filedoctype ;
+    ifile.close();
+    
+    if(doctype.compare(filedoctype) == 0)
+        validate = true;
+        
+    //if document type definition present,create and set error handler to parser, to report any parse errors in issues document.
+    if(validate)
+    {
+        myErrorHandler = new DOMPrintErrorHandler();
+        XmlTools::iParser->setErrorHandler(myErrorHandler);	
+    }
+    
+    try
+    {
+        doc = iParser->parseURI( aFilename );
+    }
+    catch ( const XMLException& e )
+    {
+        char* message = _X( e.getMessage() );
+        cout << "Failed to read " << aFilename << ". \"" << message << "\"" << endl ;
+        _XX( message );
+        return NULL;
+    }
+    catch ( const DOMException& e )
+    {
+        char* message = _X( e.getMessage() );
+        cout << "Failed to read " << aFilename << ". \"" << message << "\"" << endl ;
+        _XX( message );
+        return NULL;
+    }
+    catch (...) 
+    {
+        cout << "Failed to read " << aFilename << ". Unexpected error." << endl ;
+    return NULL;
+    }
+    
+    //delete the error handler, if set
+    if(validate)
+        delete myErrorHandler;
+        
+    return doc;
+}
+
+bool DOMPrintErrorHandler::handleError(const DOMError &domError)
+{
+    // Display whatever error message passed from the parser
+    if (domError.getSeverity() == DOMError::DOM_SEVERITY_WARNING)
+        XERCES_STD_QUALIFIER cerr << "\nWarning Message: ";
+    else if (domError.getSeverity() == DOMError::DOM_SEVERITY_ERROR)
+        XERCES_STD_QUALIFIER cerr << "\nError Message: ";
+    else
+        XERCES_STD_QUALIFIER cerr << "\nFatal Message: ";
+
+    char *msg = XMLString::transcode(domError.getMessage());
+    DOMLocator *errorLocator = domError.getLocation();
+    XERCES_STD_QUALIFIER cerr<< errorLocator->getLineNumber() << ",";
+    XERCES_STD_QUALIFIER cerr<< errorLocator->getColumnNumber() << ": ";
+    XERCES_STD_QUALIFIER cerr<< msg <<XERCES_STD_QUALIFIER endl;
+    XMLString::release(&msg);
+
+    // Instructs the parser to continue parsing if possible.
+    return true;
+}
+
+DOMElement* XmlTools::getTagNode( const DOMElement* aParentNode, const char* aTagName )
+{
+    DOMNodeList* list = aParentNode->getElementsByTagName( _X( aTagName ) );
+    if ( list == NULL || list->getLength() == 0 )
+        return NULL;
+    else
+        return (DOMElement*) list->item( 0 );
+}
+
+int XmlTools::getTagValue( const DOMElement* aParentNode, const char* aTagName, char* aTagValue, int minLen, int maxLen )
+{
+    DOMNodeList* list = aParentNode->getElementsByTagName( _X( aTagName ) );
+
+    strcpy( aTagValue, "" );
+    if ( list == NULL || list->getLength() == 0 )
+        return -1;
+    else
+    {
+        DOMNode* textNode = list->item( 0 )->getFirstChild();
+        if ( textNode == NULL )
+            return -1;
+            
+        char* text = _X( textNode->getNodeValue() );
+        if ( text == NULL )
+            return -1;
+            
+		int len =(int) strlen( text );
+        if ( len < minLen || len > maxLen )
+            return -1;
+            
+        strcpy( aTagValue, text );
+        _XX( text );
+        
+        return 0;
+    }
+}
+
+
+void ParseAndCompareDLLXmlFiles(const string& abaselineXmlFile,const string& acurrentXmlFile)
+{
+	XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* ibaseDoc = NULL;
+	int currIndx = -1;
+	int baseIndx = -1;
+	char dll_name[1024];
+
+	if ( XmlTools::initialiseDOM() == -1 )
+        return ;
+
+	// read report document
+	ibaseDoc = XmlTools::readFile( abaselineXmlFile.c_str() );
+	if ( ibaseDoc == NULL )
+	{
+		XmlTools::uninitialiseDOM();
+		return ;
+	}
+
+	// Parse file
+	cout << "Gathering dll information... " ;
+	
+	//With SAX parser , parse the base xml doc
+	// Create an instance of our XMLFactory
+	XMLEngine baseParser(abaselineXmlFile);
+	// Turn off validation
+	baseParser.doValidation(false);
+	baseParser.parse();
+	
+
+	//With SAX parser , parse the current xml doc
+	// Create an instance of our XMLFactory
+	XMLEngine currParser(acurrentXmlFile);
+	// Turn off validation
+	currParser.doValidation(false);
+	// Parse our XML file
+	currParser.parse();
+
+	cout << "Done" <<endl;
+
+	// Get the tree root
+	XMLNode baseRoot = baseParser.getRootElement();
+	XMLNode curRoot = currParser.getRootElement();
+
+	int totcurDlls = (int)curRoot.childCount(); 
+	int totbaseDlls = (int)baseRoot.childCount();
+
+	XMLNode dllNorode = curRoot.child("dll",currIndx);	
+	XMLNode baseNode = baseRoot.child("dll",baseIndx);
+
+	//If baseline dll is missing, report it as informative
+	for(unsigned int outer = 0; outer < _lib_files_baseline.size(); outer++ )
+	{
+		dll_issue tempIssue;
+
+		string finallibname(_lib_files_baseline.at(outer));
+		finallibname=getFilename(finallibname);
+		unsigned int inner;
+		
+		for(inner = baseIndx; inner < totbaseDlls; inner++ )
+		{
+			XMLNode base_dlllist = baseRoot.children_[inner];
+
+			string base_dllname = base_dlllist.child("dllname").value();
+			base_dllname = getFilename(base_dllname);
+			if (StringICmpFileNamesWithoutExtension(finallibname,base_dllname) == 0)
+				break;
+		}
+		if (inner == totbaseDlls)
+		{
+			intializeDllIssue(tempIssue);
+			tempIssue.l_dllname = finallibname;
+			tempIssue.i_list_typeid.push_back(DLL_BASELINE_MISSING);
+			_dll_issuelist.push_back(tempIssue);			
+		}
+	}
+	
+    // get dll breaks by comparing baseline and current dll data file
+	if (baseIndx >=0 && currIndx>=0)
+	{
+		for (unsigned long i = baseIndx; i < totbaseDlls; ++i )
+		{
+			dll_issue issue;
+			XMLNode base_dlllist = baseRoot.children_[i];
+			if ( base_dlllist.childCount() == 0 )
+				continue;
+			string base_dllname = base_dlllist.child("dllname").value();
+			base_dllname = getFilename(base_dllname);
+			
+			int l;
+			//char baseVal[5][255];
+			char attribs[5][12] = { "uid1", "uid2", "uid3", "sid" ,"capability"};			
+			
+			if (base_dllname.size() > 0 )
+			{
+				intializeDllIssue(issue);				
+				issue.l_dllname = base_dllname;
+				string baseShortName = getFilename(base_dllname);
+				int curIter;
+				
+				for( curIter = currIndx ; curIter < totcurDlls ; curIter++ )
+				{
+					XMLNode curr_dlllist = curRoot.children_[curIter];
+					
+					string cur_dllname = curr_dlllist.child("dllname").value();
+					cur_dllname = getFilename(cur_dllname);
+					vector<unsigned int> typeId_list;
+									
+					if(stricmp (baseShortName.c_str(),cur_dllname.c_str()) == 0)
+					{						
+
+						for ( l = 0; l < 5; ++ l )
+						{
+							string curVal = curr_dlllist.child(attribs[l]).value();
+							string baseVal = base_dlllist.child(attribs[l]).value();
+							unsigned int typeId = 0;
+
+							if(l == 4) // capability check
+							{
+								unsigned long baseCap =parseHex(baseVal.c_str());
+								unsigned long curCap = parseHex(curVal.c_str());
+								unsigned long resultCap = baseCap & curCap;
+								if( baseCap != resultCap)
+									typeId_list.push_back(DLL_CAPABILITY_CHANGED);
+							}							
+							else if( curVal.compare(baseVal)!= 0)
+							{								
+								fillDllIssue(attribs[l], typeId);
+								typeId_list.push_back(typeId);
+							}
+						}
+						
+						if(typeId_list.size()> 0 )
+						{
+							issue.i_list_typeid = typeId_list;
+							_dll_issuelist.push_back(issue);
+						}
+						break;
+					}
+				}
+
+				if (curIter == totcurDlls ) // missing dll in current xml file
+				{
+					issue.i_list_typeid.push_back( DLL_CURRENT_MISSING);
+					_dll_issuelist.push_back(issue);	
+				}
+			}
+
+		}
+	}//end of dll list
+	
+	XmlTools::uninitialiseDOM();
+}
+
+void WriteReportHeader()
+{
+    _reportf.open(_cl_reportfile.c_str(), ios::trunc);
+
+    if (!_reportf.is_open())
+        {
+			cerr << "ERROR: Cannot open " << _cl_reportfile << " for writing!" << endl;
+			cerr << "Please check that the directory exists and there are no write permission problems" << endl;
+			exit(EXIT_CANNOT_WRITE_TO_REPORT_FILE);
+        }
+
+    WriteXMLLineOpeningTag(_reportf, 0, "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?");
+    WriteXMLLineOpeningTag(_reportf, 0, "?xml-stylesheet type=\"text/xsl\" href=\"BBCResults.xsl\"?");
+    WriteXMLLineOpeningTag(_reportf, 0, "bbcresults");
+    WriteXMLLineOpeningTag(_reportf, 1, "header");
+
+    WriteXMLLineOpenClosed(_reportf, 2, "baselineversion", _cl_baselineversion);
+    WriteXMLLineOpenClosed(_reportf, 2, "currentversion", _cl_currentversion);
+
+    WriteXMLLineOpeningTag(_reportf, 2, "timestamp");
+    WriteXMLLineOpenClosed(_reportf, 3, "day", Int2Str(_timenow->tm_mday));
+    WriteXMLLineOpenClosed(_reportf, 3, "month", Int2Str(_timenow->tm_mon + 1));
+    WriteXMLLineOpenClosed(_reportf, 3, "year", Int2Str(1900 + _timenow->tm_year));
+    WriteXMLLineOpenClosed(_reportf, 3, "hour", Int2Str(_timenow->tm_hour));
+    WriteXMLLineOpenClosed(_reportf, 3, "minute", Int2Str(_timenow->tm_min));
+    WriteXMLLineOpenClosed(_reportf, 3, "second", Int2Str(_timenow->tm_sec));
+    WriteXMLLineClosingTag(_reportf, 2, "timestamp");
+
+    WriteXMLLineOpenClosed(_reportf, 2, "laversion", LA_VERSION);
+    WriteXMLLineOpenClosed(_reportf, 2, "formatversion", LA_REPORT_FORMAT_VERSION);
+
+    WriteXMLLineOpeningTag(_reportf, 2, "cmdlineparms");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "toolchain");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _toolchain_name);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "baselinelibdir");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_baselinelibdir);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "currentlibdir");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_currentlibdir);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+    
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "baselinedlldir");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_baselinedlldir);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "currentdlldir");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_currentdlldir);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+    
+    if(_cl_baselinedlldir.empty() || _cl_currentdlldir.empty())
+    {
+      WriteXMLLineOpeningTag(_reportf, 3, "parm");
+      WriteXMLLineOpenClosed(_reportf, 4, "pname", "warning");
+      WriteXMLLineOpenClosed(_reportf, 4, "pvalue","Required parameters for checking dll properties not specified. Compatibility Breaks in dll are not checked." );
+      WriteXMLLineClosingTag(_reportf, 3, "parm");
+    }
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "baselineversion");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_baselineversion);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "currentversion");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_currentversion);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "reportfile");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_reportfile);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "tools");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_toolsdir);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "temp");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_tempdir);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+    
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "cfilt");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_cfiltloc);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineOpeningTag(_reportf, 3, "parm");
+    WriteXMLLineOpenClosed(_reportf, 4, "pname", "set");
+    WriteXMLLineOpenClosed(_reportf, 4, "pvalue", _cl_set);
+    WriteXMLLineClosingTag(_reportf, 3, "parm");
+
+    WriteXMLLineClosingTag(_reportf, 2, "cmdlineparms");
+
+    WriteXMLLineOpenClosed(_reportf, 2, "knownissuesversion", "");
+    
+    WriteXMLLineClosingTag(_reportf, 1, "header");
+    WriteXMLLineOpeningTag(_reportf, 1, "issuelist");    
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void GenerateAndWriteIssueList()
+{
+	int total_files = _lib_files_baseline.size();
+	int current_files = 0;
+	cout <<"Total baseline files "<< _lib_files_baseline.size() << endl;
+	cout <<"Total current files "<< _lib_files_current.size() << endl;
+	
+	vector<string>::const_iterator itr;
+	for (unsigned int i=0; i<_lib_files_current.size(); i++)
+	{
+		bool exists = false;
+		// check if the same lib exists in baselinedir
+		for(itr = _lib_dirs_baseline.begin(); itr != _lib_dirs_baseline.end(); itr++)
+		{
+			if (FileExists(*itr + getFilename(_lib_files_current.at(i))))
+			{
+				exists = true;
+				break;
+			}
+		}
+		if(!exists)
+		{
+			total_files++;
+		}
+	}
+	cout <<"Total files to be processed "<< total_files << endl;
+	//vector<dll_issue> dll_issuelist;
+    
+	dll_issue reportdll;
+	string dllname;
+
+	if(_baselinedllfile.size() > 0 && _currentdllfile.size() > 0)
+	{
+		ParseAndCompareDLLXmlFiles(_baselinedllfile,_currentdllfile );
+	}
+	
+	unsigned int dllIssueCount = _dll_issuelist.size();
+
+    // first go through all libs in the baseline set
+	for (unsigned int i=0; i<_lib_files_baseline.size(); i++)
+	{
+		unsigned int k;
+		vector<string>::iterator itr = _lib_files_current.end();
+		bool exists = false;
+
+		//check if the same dll is present in exe_issue, if yes then add it to final report
+		intializeDllIssue(reportdll);
+		for(unsigned int indx = 0; indx < dllIssueCount; indx++)
+		{
+			dll_issue lIssue;
+			lIssue = _dll_issuelist.at(indx);		
+			if(StringICmpFileNamesWithoutExtension(getFilename(lIssue.l_dllname),getFilename(_lib_files_baseline.at(i))) == 0)
+			{
+				reportdll = lIssue;
+				break;
+			}
+		}
+
+
+        // check if the same lib exists in currentdir
+        for(k = 0; k < _lib_dirs_current.size(); k++)
+		    {
+			      string file = _lib_dirs_current.at(k) + getFilename(_lib_files_baseline.at(i));
+			      if (FileExists( file ))
+			      {
+			          for(itr=_lib_files_current.begin() ; itr != _lib_files_current.end() ; ++itr)
+			          {
+			              if(StringICmp(file,*itr)== 0)
+			              {
+			                  exists = true;
+			                  break;
+			              }
+			          }
+			          if(exists)
+			              break;
+			      }
+			  }
+
+        // check if the same lib exists in currentdir
+        if (!exists)
+        {
+        	  cout.precision(0);
+            cout << "\nAnalysing files (" << current_files+1 << "/" << total_files << "): " << _lib_files_baseline.at(i) << endl;  
+
+			WriteXMLIssueOnlyInBaselineDir(_reportf, _lib_files_baseline.at(i),reportdll);
+        }
+        else
+        {
+            cout.precision(0);
+            cout << "\nAnalysing files (" << current_files+1 << "/" << total_files << "): " << _lib_files_baseline.at(i) << " => " << *itr << endl;  
+            // both files are available, now get the symbol table and do the comparision process
+            vector<string> symbol_table_baseline;
+            vector<string> symbol_table_current;
+
+            // get the symbol tables of the libraries
+            if (_cl_use_gcc)
+            {
+                GetSymbolTableWithNM(_gcc_nm_location, _lib_files_baseline.at(i), symbol_table_baseline);
+                GetSymbolTableWithNM(_gcc_nm_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+            }
+            else if (_cl_use_gcce)
+            {
+                if (_cl_use_libs)
+                {
+                    GetSymbolTableWithNM(_gcce_nm_location, _lib_files_baseline.at(i), symbol_table_baseline);
+                    GetSymbolTableWithNM(_gcce_nm_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+                }
+                else
+                {
+                    GetSymbolTableWithReadelf(_gcce_readelf_location, _gcce_cfilt_location, _lib_files_baseline.at(i), symbol_table_baseline);
+                    GetSymbolTableWithReadelf(_gcce_readelf_location, _gcce_cfilt_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+                }
+            }
+            else if (_cl_use_rvct)
+            {
+                if (_cl_use_libs)
+                {
+                    GetSymbolTableWithArmar(_rvct_armar_location, _rvct_cfilt_location, _lib_files_baseline.at(i), symbol_table_baseline);
+                    GetSymbolTableWithArmar(_rvct_armar_location, _rvct_cfilt_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+                }
+                else
+                {
+                    GetSymbolTableWithFromelf(_rvct_fromelf_location, _rvct_cfilt_location, _lib_files_baseline.at(i), symbol_table_baseline);
+                    GetSymbolTableWithFromelf(_rvct_fromelf_location, _rvct_cfilt_location, *itr /*_lib_files_current.at(i)*/, symbol_table_current);
+                }
+            }
+
+            // create a vector to store all issues of this library
+            vector<issue> issue_list;
+			//Local variable to store severity of the issue
+			TypeOfSeverity severity = NO_BREAK;
+            // create and init vectors to store ordinal state
+            vector<bool> matched_baseline;
+            vector<bool> checked_baseline;
+            vector<bool> matched_current;
+            vector<bool> checked_current;
+			vector<TypeOfSeverity> map_severity;
+            
+            for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+                matched_baseline.push_back(false);
+
+            for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+                checked_baseline.push_back(false);
+
+            for (unsigned int j=0; j<symbol_table_current.size(); j++)
+                matched_current.push_back(false);
+
+            for (unsigned int j=0; j<symbol_table_current.size(); j++)
+                checked_current.push_back(false);
+			//Initially set to NO_BREAK as the type of severity
+            for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+                map_severity.push_back(NO_BREAK);
+
+
+            // first loop through all ordinals in baseline to find matches
+            for (unsigned int j=0; j<symbol_table_baseline.size(); j++)
+            {
+                bool need_to_check_moving = false;
+
+                if (j < symbol_table_current.size())
+                {
+                    // check if it's an exact match or otherwise binary compatible
+                    if ( symbol_table_baseline.at(j) == symbol_table_current.at(j) ||
+                        (severity = AreFunctionsCompatible(symbol_table_baseline.at(j), symbol_table_current.at(j)))
+						 == NO_BREAK )
+                    {
+                        // match!
+                        matched_baseline.at(j) = true;
+                        matched_current.at(j) = true;
+
+                        checked_baseline.at(j) = true;
+                        checked_current.at(j) = true;
+                    }                    
+                    else
+					{
+						// possibly moved
+						need_to_check_moving = true;
+						//store the severity
+						map_severity.at(j) = severity;
+					}
+                }
+                else
+                {
+                    // it's out of range, so it can be a match, but check if it has moved
+                    need_to_check_moving = true;
+                }   
+                
+                // now do the actual checking if it has moved
+                if (need_to_check_moving)
+                {
+                    for (unsigned int l=0; l<symbol_table_current.size(); l++)
+                    {
+                        if (symbol_table_baseline.at(j) == symbol_table_current.at(l))
+                        {
+							// match found, mark as moved
+							map_severity.at(j) = CONFIRMED_BC_BREAK;
+                            AppendToIssueListCaseMoved(issue_list, symbol_table_baseline.at(j), j+1, l+1,map_severity.at(j));
+                            
+                            matched_baseline.at(j) = true;
+                            matched_current.at(l) = true;
+
+                            checked_baseline.at(j) = true;
+                            checked_current.at(l) = true;
+
+                        } // if
+                    } // for           
+                } // if (need_to_check_moving)
+            } // for (int j=0; j<symbol_table_baseline.size(); j++)
+           
+
+            // check for removed ordinals when no corresponding ordinals in current
+            if (checked_baseline.size() > checked_current.size())
+            {
+                for (unsigned int j=checked_current.size(); j<checked_baseline.size(); j++)
+                {
+                    if (checked_baseline.at(j) == false)
+                    {
+                        // ignore any absent exports
+                        string::size_type loc = symbol_table_baseline.at(j).find("_._.absent_export", 0);
+                        
+                        // mark as removed if not marked as absent
+                        if( loc == string::npos )
+						{
+							// As removed results in both BC and SC break.
+							map_severity.at(j) = CONFIRMED_BC_AND_SC_BREAK;
+                            AppendToIssueListCaseRemoved(issue_list, symbol_table_baseline.at(j), j+1,map_severity.at(j));
+						}
+
+                        checked_baseline.at(j) = true;
+                    }         
+                }          
+            }
+
+            // check for added ordinals when no corresponding ordinals in current
+            if (checked_baseline.size() < checked_current.size())
+            {
+                for (unsigned int j=checked_baseline.size(); j<checked_current.size(); j++)
+                {
+                    if (checked_current.at(j) == false)
+                    {
+                    // ignore any absent exports
+                    string::size_type loc = symbol_table_current.at(j).find("_._.absent_export", 0);
+                    
+                    // mark as added if not marked as absent
+                    if( loc == string::npos )
+                        AppendToIssueListCaseAdded(issue_list, symbol_table_current.at(j), j+1,BC_INFORMATIVE);
+
+                    checked_current.at(j) = true;
+                    }         
+                }          
+            }
+
+            // check for removed cases when current has a match at the same ordinal
+            for (unsigned int j=0; j<checked_baseline.size(); j++)
+            {
+                if (checked_baseline.at(j) == false && matched_current.at(j) == true)
+                {
+                    // ignore any absent exports
+                    string::size_type loc = symbol_table_baseline.at(j).find("_._.absent_export", 0);
+                    
+                    // mark as removed if not marked as absent
+                    if( loc == string::npos )
+					{
+						// As removed results in both BC and SC break.
+						map_severity.at(j) = CONFIRMED_BC_AND_SC_BREAK;
+						AppendToIssueListCaseRemoved(issue_list, symbol_table_baseline.at(j), j+1,map_severity.at(j));
+					}
+
+                    checked_baseline.at(j) = true;
+                }         
+            }             
+
+            // check for inserted cases
+            for (unsigned int j=0; j<checked_current.size(); j++)
+            {
+                if (checked_current.at(j) == false && matched_baseline.at(j) == true)
+                {
+                    // ignore any absent exports
+                    string::size_type loc = symbol_table_current.at(j).find("_._.absent_export", 0);
+                    
+                    // mark as inserted if not marked as absent
+                    if( loc == string::npos )
+                        AppendToIssueListCaseInserted(issue_list, symbol_table_current.at(j), j+1,CONFIRMED_BC_BREAK);
+
+                    checked_current.at(j) = true;
+                }         
+            }  
+
+            // check for modified cases
+            for (unsigned int j=0; j<checked_baseline.size(); j++)
+            {
+                if (checked_baseline.at(j) == false && checked_current.at(j) == false && matched_current.at(j) == false)
+                {
+                    // ignore any absent exports
+                    string::size_type loc = symbol_table_baseline.at(j).find("_._.absent_export", 0);
+                    string::size_type loc2 = symbol_table_current.at(j).find("_._.absent_export", 0);
+
+                    // mark as modfied if not marked as absent
+                    if( loc == string::npos && loc2 == string::npos)
+                        AppendToIssueListCaseModified(issue_list, symbol_table_baseline.at(j), symbol_table_current.at(j), j+1,map_severity.at(j));
+                    // mark as added if absent export has been modified to something else
+                    else if (loc != string::npos && loc2 == string::npos)
+                        AppendToIssueListCaseAdded(issue_list, symbol_table_current.at(j), j+1,BC_INFORMATIVE);
+                    // mark as removed if export has been modified as absent
+                    else if (loc == string::npos && loc2 != string::npos)
+                        AppendToIssueListCaseRemoved(issue_list, symbol_table_baseline.at(j), j+1,CONFIRMED_BC_AND_SC_BREAK);
+                        
+                    checked_baseline.at(j) = true;
+                    checked_current.at(j) = true;
+                }         
+            }   
+
+            // do some error checking :)
+            for (unsigned int j=0; j<checked_baseline.size(); j++)
+            {
+                if (checked_baseline.at(j) == false)
+                {
+                    cout << "OC ALGORITHM ERROR: Baseline func " << symbol_table_baseline.at(j) << " not checked!" << endl;
+                }         
+            } 
+            for (unsigned int j=0; j<checked_current.size(); j++)
+            {
+                if (checked_current.at(j) == false)
+                {
+                    cout << "OC ALGORITHM ERROR: Current rel func " << symbol_table_current.at(j) << " not checked!" << endl;
+                }         
+            }
+
+            // sort the issue list
+            sort(issue_list.begin(), issue_list.end(), IssueCompare);
+
+            // finally write the issue_list to the xml file
+			WriteIssueListToXML(_reportf, _lib_files_baseline.at(i), *itr /*_lib_files_current.at(i)*/,  issue_list, reportdll);
+            
+        } // else of (!FileExists(_cl_currentlibdir + _lib_files_baseline.at(i)))
+        //erase analysed file from vector, so that files with duplicate names will be properly analysed.
+        if( _lib_files_current.end() != itr )
+            _lib_files_current.erase(itr);
+
+        current_files++;
+	} // for (unsigned int i=0; i<_lib_files_baseline.size(); i++)
+
+
+    // finally go through all libs in the currentdir set
+	for (unsigned int i=0; i<_lib_files_current.size(); i++)
+	{
+		bool exists = false;
+		vector<string>::const_iterator itr = _lib_dirs_baseline.begin();
+        // check if the same lib exists in baselinedir
+		for(;itr != _lib_dirs_baseline.end(); itr++)
+		{
+			if (FileExists(*itr + getFilename( _lib_files_current.at(i)) ))
+			{
+				exists = true;
+				break;
+			}
+		}
+		if(!exists)
+		{
+             current_files++;
+             cout.precision(0);
+             cout << "\nAnalysing files (" << current_files << "/" << total_files << "): " << _lib_files_current.at(i) << endl;  
+
+             // only in currentdir
+             WriteXMLIssueOnlyInCurrentDir(_reportf, _lib_files_current.at(i));
+        }
+    }
+	cout << "\n---------------------------------------------";
+	cout << "\nFinished";
+	cout << "\nTotal Files analysed : " << total_files;
+	cout << "\n---------------------------------------------";
+}
+
+// ----------------------------------------------------------------------------------------------------------
+    
+void WriteReportFooter()
+{
+    // generate the footer of XML file
+    WriteXMLLineClosingTag(_reportf, 1, "issuelist");
+    WriteXMLLineClosingTag(_reportf, 0, "bbcresults");
+
+    // close writing to the report file
+    _reportf.close();    
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseMoved(vector<issue>& issueList, const string& funcname, int funcpos, int newfuncpos,TypeOfSeverity severity)
+{
+	issue i;
+	string bc_severity = "";
+	string sc_severity = "";
+	getSeverityString(severity,bc_severity,sc_severity);
+
+	i.i_typeid = ISSUE_MOVED;
+	i.i_funcname = funcname;
+	i.i_newfuncname = "";
+	i.i_funcpos = funcpos;
+	i.i_newfuncpos = newfuncpos;
+	i.i_BC_severity = bc_severity;
+	i.i_SC_severity = sc_severity;
+	
+    issueList.push_back(i); 
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseRemoved(vector<issue>& issue_list, const string& funcname, int funcpos,TypeOfSeverity severity)
+{
+	issue i;
+	string bc_severity = "";
+	string sc_severity = "";
+	getSeverityString(severity,bc_severity,sc_severity);
+
+	i.i_typeid = ISSUE_REMOVED;
+	i.i_funcname = funcname;
+	i.i_newfuncname = "";
+	i.i_funcpos = funcpos;
+	i.i_newfuncpos = 0;
+	i.i_BC_severity = bc_severity;
+	i.i_SC_severity = sc_severity;
+	
+	issue_list.push_back(i); 
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseInserted(vector<issue>& issue_list, const string& newfuncname, int newfuncpos,TypeOfSeverity severity)
+{
+	issue i;
+	string bc_severity = "";
+	string sc_severity = "";
+	getSeverityString(severity,bc_severity,sc_severity);
+
+	i.i_typeid = ISSUE_INSERTED;
+	i.i_funcname = "";
+	i.i_newfuncname = newfuncname;
+	i.i_funcpos = 0;
+	i.i_newfuncpos = newfuncpos;
+	i.i_BC_severity = bc_severity;
+	i.i_SC_severity = sc_severity;
+	
+	issue_list.push_back(i); 
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseModified(vector<issue>& issue_list, const string& funcname, const string& newfuncname, int funcpos,TypeOfSeverity severity)
+{
+	issue i;
+	string bc_severity = "";
+	string sc_severity = "";
+	getSeverityString(severity,bc_severity,sc_severity);
+
+	i.i_typeid = ISSUE_MODIFIED;
+	i.i_funcname = funcname;
+	i.i_newfuncname = newfuncname;
+	i.i_funcpos = funcpos;
+	i.i_newfuncpos = 0;
+	i.i_BC_severity = bc_severity;
+	i.i_SC_severity = sc_severity;
+	
+	issue_list.push_back(i); 
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void AppendToIssueListCaseAdded(vector<issue>& issue_list, const string& newfuncname, int newfuncpos,TypeOfSeverity severity)
+{
+	issue i;
+	string bc_severity = "";
+	string sc_severity = "";
+	getSeverityString(severity,bc_severity,sc_severity);
+
+	i.i_typeid = ISSUE_ADDED;
+	i.i_funcname = "";
+	i.i_newfuncname = newfuncname;
+	i.i_funcpos = 0;
+	i.i_newfuncpos = newfuncpos;
+	i.i_BC_severity = bc_severity;
+	i.i_SC_severity = sc_severity;
+
+	issue_list.push_back(i); 
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+bool IssueCompare(const issue& left, const issue& right)
+{
+    if (left.i_funcpos > 0 && right.i_funcpos > 0)
+    {
+        if (left.i_funcpos == right.i_funcpos && left.i_newfuncpos > 0 && right.i_newfuncpos > 0)
+            return left.i_newfuncpos < right.i_newfuncpos;
+        else
+            return left.i_funcpos < right.i_funcpos; 
+    }
+    
+    else if (left.i_funcpos == 0 && right.i_funcpos > 0)
+    {
+        if (left.i_newfuncpos == right.i_funcpos)
+            return left.i_funcpos < right.i_newfuncpos;
+        else
+            return left.i_newfuncpos < right.i_funcpos;
+    }
+    
+    else if (left.i_funcpos > 0 && right.i_funcpos == 0)
+    {
+        if (left.i_funcpos == right.i_newfuncpos)
+            return left.i_newfuncpos < right.i_funcpos;
+        else
+            return left.i_funcpos < right.i_newfuncpos;
+    }
+       
+    else // if (left.i_funcpos == 0 && right.i_funcpos == 0)
+    {
+        return left.i_newfuncpos < right.i_newfuncpos;
+    }
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLLineOpenClosed(ofstream& f, unsigned int tabstops, const string& element, const string& data)
+{
+    string tabs(tabstops, REPORT_TAB_CHAR);
+    string xmldata(data);
+    
+    // replace & -> &auml;
+    string::size_type i=0;
+    while ((i=xmldata.find("&", i)) != string::npos)
+    {
+        xmldata.replace(i, 1, "&amp;");
+        i++;
+    }
+
+    // replace < -> &lt;
+    i=0;
+    while ((i=xmldata.find("<", i)) != string::npos)
+        xmldata.replace(i, 1, "&lt;");    
+
+    // replace > -> &gt;
+    i=0;
+    while ((i=xmldata.find(">", i)) != string::npos)
+        xmldata.replace(i, 1, "&gt;");    
+
+
+    f << tabs << "<" << element << ">" << xmldata << "</" << element << ">" << endl;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLLineOpeningTag(ofstream& f, unsigned int tabstops, const string& element)
+{
+    string tabs(tabstops, REPORT_TAB_CHAR);
+
+    f << tabs << "<" << element << ">" << endl;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLLineClosingTag(ofstream& f, unsigned int tabstops, const string& element)
+{
+    string tabs(tabstops, REPORT_TAB_CHAR);
+
+    f << tabs << "</" << element << ">" << endl;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void writeXMLIssueLibraryHeader(ofstream& f, const string& libname, const string& curlibname)
+{
+    
+    WriteXMLLineOpeningTag(f, 2, "library");
+    WriteXMLLineOpenClosed(f, 3, "name", libname);
+    WriteXMLLineOpenClosed(f, 3, "comparefilename", curlibname);
+    
+    string finallibname(curlibname);
+    if (finallibname.empty())
+       finallibname=libname;
+    finallibname=getFilename(finallibname);
+    // remove any extensions from libname
+    string::size_type dot_loc = finallibname.find_last_of(".");
+    if (dot_loc != string::npos)
+        finallibname = finallibname.substr(0, dot_loc);    
+    WriteXMLLineOpenClosed(f, 3, "shortname", finallibname);
+    WriteXMLLineOpenClosed(f, 3, "baseplatform", getPlatform(libname));
+    WriteXMLLineOpenClosed(f, 3, "currentplatform", getPlatform(curlibname));
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void writeXMLIssueLibraryFooter(ofstream& f)
+{
+    WriteXMLLineClosingTag(f, 2, "library");
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLIssueOnlyInBaselineDir(ofstream& f, const string& libname, dll_issue& dllIssue)
+{
+	writeXMLIssueLibraryHeader(f, libname, "");
+	WriteXMLLineOpeningTag(f, 3, "issue");
+	WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(ISSUE_ONLY_IN_BASELINEDIR));
+	WriteXMLLineOpenClosed(f, 4, "bc_severity", "BBC Break");
+	WriteXMLLineOpenClosed(f, 4, "sc_severity", "SC Break");
+	WriteXMLLineClosingTag(f, 3, "issue");
+	for(unsigned int i =0; i< dllIssue.i_list_typeid.size(); i++ )
+	{
+		string typeinfo = "";
+		WriteXMLLineOpeningTag(f, 3, "issue");
+		WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(dllIssue.i_list_typeid.at(i)));
+		typeinfo = GetDllBreakTypeInfoString(dllIssue.i_list_typeid.at(i));
+		if(typeinfo.size() > 0)
+			WriteXMLLineOpenClosed(f, 4, "typeinfo", typeinfo);
+
+		if (dllIssue.i_list_typeid.at(i) == DLL_BASELINE_MISSING )
+			WriteXMLLineOpenClosed(f, 4, "bc_severity", "Informative");            
+		else
+			WriteXMLLineOpenClosed(f, 4, "bc_severity", "BBC Break"); 
+
+		WriteXMLLineOpenClosed(f, 4, "sc_severity", "None");            
+
+		WriteXMLLineClosingTag(f, 3, "issue");
+	}
+	writeXMLIssueLibraryFooter(f);
+}            
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteXMLIssueOnlyInCurrentDir(ofstream& f, const string& libname)
+{
+    writeXMLIssueLibraryHeader(f, "", libname);
+    WriteXMLLineOpeningTag(f, 3, "issue");
+    WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(ISSUE_ONLY_IN_CURRENTDIR));
+    WriteXMLLineOpenClosed(f, 4, "bc_severity", "Informative");
+    WriteXMLLineOpenClosed(f, 4, "sc_severity", "Informative");
+    WriteXMLLineClosingTag(f, 3, "issue");
+    writeXMLIssueLibraryFooter(f);
+}            
+
+// ----------------------------------------------------------------------------------------------------------
+
+void WriteIssueListToXML(ofstream& f, const string& libname, const string& curlibname,vector<issue>& issue_list, dll_issue& dllIssue)
+{
+	if (issue_list.size() > 0 || dllIssue.i_list_typeid.size() > 0)
+    {
+        string finallibname(curlibname);
+        // write header
+        WriteXMLLineOpeningTag(f, 2, "library");
+        WriteXMLLineOpenClosed(f, 3, "name", libname);
+        WriteXMLLineOpenClosed(f, 3, "comparefilename", curlibname);
+        finallibname=getFilename(finallibname);
+        // remove any extensions from libname
+        string::size_type dot_loc = finallibname.find_last_of(".");
+        if (dot_loc != string::npos)
+            finallibname = finallibname.substr(0, dot_loc);    
+        WriteXMLLineOpenClosed(f, 3, "shortname", finallibname);
+        WriteXMLLineOpenClosed(f, 3, "baseplatform", getPlatform(libname));
+        WriteXMLLineOpenClosed(f, 3, "currentplatform", getPlatform(curlibname));
+
+        // write all single issues        
+        for (unsigned int i=0; i<issue_list.size(); i++)
+        {
+            WriteXMLLineOpeningTag(f, 3, "issue");
+            
+            WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(issue_list.at(i).i_typeid));
+
+            if (issue_list.at(i).i_funcname.length() > 0)          
+                WriteXMLLineOpenClosed(f, 4, "funcname", issue_list.at(i).i_funcname);
+            
+            if (issue_list.at(i).i_newfuncname.length() > 0)          
+                WriteXMLLineOpenClosed(f, 4, "newfuncname", issue_list.at(i).i_newfuncname);
+            
+            if (issue_list.at(i).i_funcpos > 0)          
+                WriteXMLLineOpenClosed(f, 4, "funcpos", Int2Str(issue_list.at(i).i_funcpos));
+    
+            if (issue_list.at(i).i_newfuncpos > 0)          
+                WriteXMLLineOpenClosed(f, 4, "newfuncpos", Int2Str(issue_list.at(i).i_newfuncpos));
+                
+            if (issue_list.at(i).i_BC_severity.length() > 0)
+                WriteXMLLineOpenClosed(f, 4, "bc_severity", issue_list.at(i).i_BC_severity);
+
+            if (issue_list.at(i).i_SC_severity.length() > 0)          
+                WriteXMLLineOpenClosed(f, 4, "sc_severity", issue_list.at(i).i_SC_severity);            
+            
+            WriteXMLLineClosingTag(f, 3, "issue");
+        }
+
+		
+				for (unsigned int i=0; i<dllIssue.i_list_typeid.size(); i++)
+				{
+					string typeinfo = "";
+					WriteXMLLineOpeningTag(f, 3, "issue");
+					WriteXMLLineOpenClosed(f, 4, "typeid", Int2Str(dllIssue.i_list_typeid.at(i)));
+					typeinfo = GetDllBreakTypeInfoString(dllIssue.i_list_typeid.at(i));
+					if(typeinfo.size() > 0)
+						WriteXMLLineOpenClosed(f, 4, "typeinfo", typeinfo);
+
+					if (dllIssue.i_list_typeid.at(i) == DLL_BASELINE_MISSING )
+						WriteXMLLineOpenClosed(f, 4, "bc_severity", "Informative");            
+					else
+						WriteXMLLineOpenClosed(f, 4, "bc_severity", "BBC Break"); 
+
+					WriteXMLLineOpenClosed(f, 4, "sc_severity", "None");            
+					WriteXMLLineClosingTag(f, 3, "issue");
+				}        
+
+				// finally write footer        
+				WriteXMLLineClosingTag(f, 2, "library");        
+    }
+}
+
+// ----------------------------------------------------------------------------------------------------------
+