analyzetool/commandlineengine/src/CATDatParser.cpp
branchRCL_3
changeset 13 da2cedce4920
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/analyzetool/commandlineengine/src/CATDatParser.cpp	Tue May 25 14:22:58 2010 +0300
@@ -0,0 +1,1542 @@
+/*
+* Copyright (c) 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:  Class responsible to parse data files
+*
+*/
+
+
+#include "../inc/CATDatParser.h"
+#include "../inc/CATProject.h"
+#include "../inc/CATModule2.h"
+#include "../inc/CATMemoryAddress.h"
+#include "../inc/catromsymbol.h"
+
+// -----------------------------------------------------------------------------
+// CATDatParser::CATDatParser
+// Constructor only for testing!
+// (No module vector defined so no locating codelines / call stacks)
+// -----------------------------------------------------------------------------
+CATDatParser::CATDatParser()
+{
+	LOG_FUNC_ENTRY("CATDatParser::CATDatParser");
+	Construct();
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::CATDatParser
+// Constructor
+// -----------------------------------------------------------------------------
+CATDatParser::CATDatParser(vector<CATModule2*>* pModules )
+{
+	LOG_FUNC_ENTRY("CATDatParser::CATDatParser");
+	Construct();
+	m_pModules = pModules;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::Construct
+// "Real" constructor
+// -----------------------------------------------------------------------------
+void CATDatParser::Construct()
+{
+	LOG_FUNC_ENTRY("CATDatParser::Construct");
+
+	m_iDataVersion = 1; // Default version of data.
+	m_bDllLoadFound = false;
+	m_bProcessStartFound = false;
+	m_bSubtestOnGoing = false;
+
+	m_DataSaver.InitXML();
+	
+	m_eBuildType = -2;
+	m_eProcess_state = not_started;
+	m_eProjectBuildType = -1;
+
+	m_iCurrentProcessId = 0;
+	m_iLeakNumber = 0;
+	m_iLogLevel = 3;
+	m_iOffSet = 0;
+
+	m_iPinPointedLeaks = 0;
+	m_iPinPointedSubTestLeaks = 0;
+	m_iSubtestStartHandleCount = 0;
+	m_iSuccesfullRuns = 0;
+	m_iTotalNumberOfLeaks = 0;
+	m_iTotalRuns = 0;
+
+	m_pRomSymbol = 0;
+	m_pModules = 0;
+
+	m_sCurrentProcessName = "";
+	m_sInputFile = "";
+	m_sInputFileTemp = "";
+	m_sOutputFile = "";
+	m_sProjectPlatform = "";
+	m_vRomSymbolFiles.clear();
+	m_vDllLoadModList.clear();
+	m_vDllLoadModListSubTest.clear();
+	m_vHandleLeaks.clear();
+	m_vMemoryAddress.clear();
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::~CATDatParser
+// Destructor
+// -----------------------------------------------------------------------------
+CATDatParser::~CATDatParser()
+{
+	LOG_FUNC_ENTRY("CATDatParser::~CATDatParser");
+
+	if ( m_In.is_open() )
+		m_In.close();
+	// Delete temporary input file if any
+	if ( !m_sInputFileTemp.empty() )
+	{
+		if ( FileExists( m_sInputFileTemp.c_str() ) )
+			FileDelete( m_sInputFileTemp, false );
+	}
+	// Clean memory addresses if any
+	CleanMemoryAddresses();
+	// Delete rom symbol.
+	if ( m_pRomSymbol )
+	{
+        delete m_pRomSymbol;
+		m_pRomSymbol = NULL;
+	}
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::Analyze
+// Analyze given data file
+// -----------------------------------------------------------------------------
+int CATDatParser::Analyze()
+{
+	LOG_FUNC_ENTRY("CATDatParser::Analyze");
+	// Return if input file not set
+	if ( m_sInputFile.empty() )
+		return AT_RETURN_CODE::INVALID_DATA_FILE;
+	// If open close first
+	if ( m_In.is_open() )
+		m_In.close();
+	// Open file
+	m_In.open( m_sInputFile.c_str() );
+	if ( ! m_In.good() )
+		return AT_RETURN_CODE::INVALID_DATA_FILE;
+	try {
+		// If rom symbol file specified.
+		if ( ! m_vRomSymbolFiles.empty() )
+		{
+			// Create new rom symbol file "parser".
+			m_pRomSymbol = new CATRomSymbol();
+			m_pRomSymbol->m_bShowProgressMessages = true;
+			// Set symbol files.
+			if ( ! m_pRomSymbol->SetSymbols( m_vRomSymbolFiles ) )
+			{
+				cout << AT_MSG << "Rom/Rofs symbols error: " << m_pRomSymbol->GetError() << endl;
+				// If file open fails we delete it and will not use it.
+				delete m_pRomSymbol;
+				m_pRomSymbol = NULL;
+				cout << AT_MSG << "Analyze aborted." << endl;
+				return AT_RETURN_CODE::SYMBOL_FILE_ERROR;
+			}
+		}
+		// Return code
+		int iRet = 0;
+		// Clear variables
+		ClearParsingVariables();
+		// If output defined disable printing
+		if ( ! m_sOutputFile.empty() )
+			m_DataSaver.SetPrintFlag( false );
+		// Header
+		Header();
+		// Parsing
+		iRet = Parse();
+		// Footer
+		if ( iRet == AT_RETURN_CODE::OK )
+			Footer();
+		// If output defined save xml
+		if ( ! m_sOutputFile.empty() )
+			m_DataSaver.SaveLinesToFile( m_sOutputFile.c_str(), XML_DATA );
+		// Return
+		return iRet;
+	} catch ( int i )
+	{
+		cout << AT_MSG << "Error, Analyze failed. : " << i << endl;
+		return AT_RETURN_CODE::UNHANDLED_EXCEPTION;
+	}
+}
+// -----------------------------------------------------------------------------
+// CATDatParser::Header
+// Print header of report
+// -----------------------------------------------------------------------------
+void CATDatParser::Header()
+{
+	LOG_FUNC_ENTRY("CATDatParser::Header");
+	// Analyze report header
+	m_DataSaver.AddString( "Atool.exe v." );
+	m_DataSaver.AddString( ATOOL_VERSION );
+	m_DataSaver.AddString( "\n" );
+	m_DataSaver.AddString( "Analyzing memory leaks..." );
+	m_DataSaver.AddLineToLast();
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::Footer
+// Print footer of report
+// -----------------------------------------------------------------------------
+void CATDatParser::Footer()
+{
+	LOG_FUNC_ENTRY("CATDatParser::Footer");
+	m_DataSaver.AddString( "\nTotal Runs: " );
+	m_DataSaver.AddInteger( m_iTotalRuns );
+	m_DataSaver.AddLineToLast();
+
+	int iFailedRuns = m_iTotalRuns - m_iSuccesfullRuns;
+	m_DataSaver.AddString( "Failed Runs: " );
+	m_DataSaver.AddInteger( iFailedRuns );
+	m_DataSaver.AddLineToLast();
+
+	char cTemp[128];
+	string sResult( itoa( m_iTotalRuns, cTemp, 10 ) );
+	sResult.append( ";" );
+	sResult.append( itoa( iFailedRuns, cTemp, 10 ) );
+	sResult.append( ";" );
+
+	m_DataSaver.SaveXML( sResult, RESULT );
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ClearParsingVariables
+// Clear/Reset all member variables related to parsing data file
+// -----------------------------------------------------------------------------
+void CATDatParser::ClearParsingVariables()
+{
+	LOG_FUNC_ENTRY("CATDatParser::ClearParsingVariables");
+	// Clear variables related to analyze
+	m_eProcess_state = not_started;
+	m_bProcessStartFound = false;
+	m_bDllLoadFound = false;
+	m_iTotalNumberOfLeaks = 0;
+	m_iPinPointedLeaks = 0;
+	m_iLeakNumber = 0;
+	m_iTotalRuns = 0;
+	m_iSuccesfullRuns = 0;
+	m_bSubtestOnGoing = false;
+	m_iSubtestStartHandleCount = 0;
+	CleanMemoryAddresses();
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::Parse
+// Parses data file. Note! header and footer of the report are done in 
+// separate functions.
+// -----------------------------------------------------------------------------
+int CATDatParser::Parse()
+{
+	LOG_FUNC_ENTRY("CATDatParser::Parse");
+	// Read all lines
+	char cLine[MAX_LINE_LENGTH];
+	do
+	{
+		string sLine;
+		try {
+			m_In.getline( cLine, MAX_LINE_LENGTH );
+			sLine = cLine ;
+		} catch(...)
+		{
+			LOG_STRING( AT_MSG << "Unexpected error, reading data file." );
+			continue;
+		}
+		if( sLine.find( LABEL_DATA_FILE_VERSION ) != string::npos )
+		{
+			// Check data file version
+			if(  sLine.find( AT_DATA_FILE_VERSION ) == string::npos )
+			{
+				return AT_RETURN_CODE::WRONG_DATA_FILE_VERSION;
+			}
+		}
+		else if( sLine.find( LABEL_PROCESS_START ) != string::npos )
+		{
+			if ( ! ParseProcessStart( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_DLL_LOAD ) != string::npos )
+		{
+			if ( ! ParseDllLoad( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_DLL_UNLOAD ) != string::npos )
+		{
+			if ( ! ParseDllUnload( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_MEM_LEAK ) != string::npos)
+		{
+			if ( ! ParseMemLeak( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_PROCESS_END ) != string::npos )
+		{
+			if ( ! ParseProcessEnd( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_ERROR_OCCURED ) != string::npos )
+		{
+			if ( ! ParseErrorOccured( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_HANDLE_LEAK ) != string::npos )
+		{
+			if ( ! ParseHandleLeak( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_TEST_START ) != string::npos )
+		{
+			if ( ! ParseTestStart( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_TEST_END ) != string::npos )
+		{
+			if ( ! ParseTestEnd( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+		else if( sLine.find( LABEL_LOGGING_CANCELLED ) != string::npos )
+		{
+			if ( ! ParseLoggingCancelled( sLine ) )
+				return AT_RETURN_CODE::ANALYZE_ERROR;
+		}
+	}
+	while( m_In.good() );
+	// Message of failed run if process start was last line in data.
+	if ( m_eProcess_state == ongoing )
+	{
+		m_DataSaver.AddString( "Test run failed.\n" );
+		m_DataSaver.AddLineToLast();
+	}
+	return AT_RETURN_CODE::OK;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseProcessStart
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseProcessStart( string& sLine)
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseProcessStart");
+	if ( m_eProcess_state == ongoing )
+	{
+		m_DataSaver.AddString( "Test run failed.\n" );
+		m_DataSaver.AddLineToLast();
+	}
+	m_eProcess_state = ongoing;
+	m_bProcessStartFound = true;
+
+	// Clear handle leaks
+	m_vHandleLeaks.clear();
+	// Increment runs
+	m_iTotalRuns++;
+	// Clean leak count
+	m_iTotalNumberOfLeaks = 0;
+	// Clean pin pointed leaks count.
+	m_iPinPointedLeaks = 0;
+	// Clean leak number
+	m_iLeakNumber = 0;
+
+	// Clean loaded mods
+	m_vDllLoadModList.clear();
+	m_vDllLoadModListSubTest.clear();
+
+	// Skip text PROCESS_START
+	GetStringUntilNextSpace( sLine );
+	// Get process name
+	m_sCurrentProcessName = GetStringUntilNextSpace( sLine );
+	// Get Pid
+	string sPid = GetStringUntilNextSpace( sLine );
+	m_iCurrentProcessId = _httoi( sPid.c_str() );
+
+	// Header for process tart
+	m_DataSaver.AddString( "\n--------------------------------\n" );
+	m_DataSaver.AddString( "Test Run start (" );
+	m_DataSaver.AddString( m_sCurrentProcessName.c_str() );
+	m_DataSaver.AddString( "): " );
+
+	// Get start time
+	string sTime = GetStringUntilNextSpace( sLine );
+	sTime = ConvertTimeToLocalTime( sTime );
+	m_DataSaver.AddString( sTime.c_str() );
+
+	// Create data for xml
+	string sData( sTime );
+	sData.append( ";" );
+	
+	// Build mode UDEB/UREL.
+	string sBuildType = GetStringUntilNextSpace( sLine );
+
+	m_DataSaver.AddString( " Build target: " );
+	if( sBuildType.compare( "0" ) == 0 )
+	{
+		m_eBuildType = CATProject::UREL;
+	}
+	else if( sBuildType.compare( "1" ) == 0 )
+	{
+		m_eBuildType = CATProject::UDEB;
+	}
+	m_DataSaver.AddString( CATProject::GetBuildTypeString( m_eBuildType ).c_str() );
+
+	// Version.
+	string sVersion = GetStringUntilNextSpace( sLine );
+	unsigned int iVer = 0;
+	if ( hexToDec( sVersion, iVer ) && iVer != 0 )
+		m_iDataVersion = iVer;
+
+	// End line in data.
+	m_DataSaver.AddLineToLast();
+	
+	// xml
+	sData.append( CATProject::GetBuildTypeString( m_eBuildType ) );
+	sData.append( ";" );
+	sData.append( m_sCurrentProcessName );
+	m_DataSaver.SaveXML( sData, RUN );
+
+	// If projects platform defined check that it is same in data. (future feature).
+	if ( ! m_sProjectPlatform.empty() )
+	{
+		// If platform info is added to data file do check here.
+	}
+	// If projects build type defined check that it is same in data.
+	if ( m_eProjectBuildType != -1 )
+	{
+		if ( m_eBuildType != m_eProjectBuildType )
+		{
+			string sError(AT_MSG);
+			sError.append( "Error, analyzed data has build type of " );
+			sError.append( CATProject::GetBuildTypeString( m_eBuildType ) );
+			sError.append( " and project has build type " );
+			sError.append( CATProject::GetBuildTypeString( m_eProjectBuildType ) );
+			sError.append( ". Pinpointed code lines are not valid." );
+			m_DataSaver.AddString( sError.c_str(), false );
+			m_DataSaver.AddLineToLast();
+		}
+	}
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseProcessEnd
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseProcessEnd( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseProcessEnd");
+	GetStringUntilNextSpace( sLine );
+
+	// Get process id
+	string sProcessID = GetStringUntilNextSpace( sLine );
+	unsigned long iProcessID = _httoi( sProcessID.c_str() );
+
+	// Get time
+	string sTime = GetStringUntilNextSpace( sLine );
+
+	// Convert leak time
+	sTime = ConvertTimeToLocalTime( sTime );
+
+	// Process started?
+	if( iProcessID == m_iCurrentProcessId )
+	{
+		m_iSuccesfullRuns++;
+		m_DataSaver.AddLineToLast();
+		m_DataSaver.AddString( "Test Run end (" );
+		m_DataSaver.AddString( m_sCurrentProcessName.c_str() );
+		m_DataSaver.AddString( "): " );
+		m_DataSaver.AddString( sTime.c_str() );
+		m_DataSaver.AddLineToLast();
+		m_DataSaver.AddString( "Build target: " );
+		m_DataSaver.AddString( CATProject::GetBuildTypeString( m_eBuildType ).c_str() );
+		m_DataSaver.AddLineToLast();
+
+		m_eProcess_state = stopped;
+		// Number of leaks
+		if ( m_iLogLevel == 1 || m_iLogLevel == 2 )
+		{
+			if ( m_iPinPointedLeaks > 0 )
+			{
+				m_DataSaver.AddInteger( m_iPinPointedLeaks );
+				m_DataSaver.AddString( " number of pinpointed memory leak(s)." );
+				m_DataSaver.AddLineToLast();
+			}
+			m_DataSaver.AddInteger( m_iLeakNumber );
+			m_DataSaver.AddString( " total number of memory leak(s)." );
+			m_DataSaver.AddLineToLast();
+		}
+		else
+		{
+			m_DataSaver.AddInteger( m_iTotalNumberOfLeaks );
+			m_DataSaver.AddString( " memory leak(s) found." );
+			m_DataSaver.AddLineToLast();
+		}
+		
+		// xml
+		char cTemp[128];
+		m_DataSaver.SaveXML( itoa( m_iTotalNumberOfLeaks, cTemp, 10 ) , MEM_LEAKS );
+
+		// Print all modules which have leaks
+		for( size_t i = 0 ; i < m_vDllLoadModList.size() ; i++ )
+		{
+			if( m_vDllLoadModList.at(i).iLeaks > 0 )
+			{
+				m_DataSaver.AddInteger( m_vDllLoadModList.at(i).iLeaks );
+				m_DataSaver.AddString( " memory leak(s) in module: " );
+				m_DataSaver.AddString( m_vDllLoadModList.at(i).sModuleName.c_str() );
+				m_DataSaver.AddLineToLast();
+
+				// xml
+				string sModuleNameAndLeaks( m_vDllLoadModList[i].sModuleName );
+				sModuleNameAndLeaks.append(";");
+				sModuleNameAndLeaks.append( itoa( m_vDllLoadModList[i].iLeaks, cTemp, 10 ) );
+				m_DataSaver.SaveXML( sModuleNameAndLeaks , MEM_LEAK_MODULE );
+			}
+		}
+		
+		if ( m_vHandleLeaks.size() > 0 )
+		{
+			// We have handle leaks
+			bool bHandLeaksFound = false;
+			int iTotalNrOfLeaks = 0;
+			// Print handle leaks
+			for( size_t i = 0 ; i < m_vHandleLeaks.size() ; i++ )
+			{
+				string sTempHandleLeak( m_vHandleLeaks[i] );
+				// Name.
+				string sHandleLeakModule( GetStringUntilNextSpace( sTempHandleLeak ) );
+				// Count.
+				string sNrOfLeaks( GetStringUntilNextSpace(sTempHandleLeak) );
+				unsigned long iNrOfLeaks = _httoi( sNrOfLeaks.c_str() );
+				iTotalNrOfLeaks += iNrOfLeaks;
+				if( iNrOfLeaks )
+				{
+					if( !bHandLeaksFound )
+					{
+						m_DataSaver.SaveXML( sNrOfLeaks , HANDLE_LEAKS );
+					}
+					bHandLeaksFound = true;
+					m_DataSaver.AddInteger( iNrOfLeaks );
+					// Just print out how many leaks found.
+					// Because its always unknown.
+					m_DataSaver.AddString( " handle leak(s) found." );
+					m_DataSaver.AddLineToLast();
+
+					// xml
+					string sXMLInfo( sHandleLeakModule );
+					sXMLInfo.append( ";" ); sXMLInfo.append( sNrOfLeaks );
+					m_DataSaver.SaveXML( sXMLInfo , HANDLE_LEAK_MODULE );
+				}
+			}
+			// Update number if handle leaks
+			m_DataSaver.SaveXML( itoa( iTotalNrOfLeaks, cTemp, 10 ) , HANDLE_LEAKS );
+			if( !bHandLeaksFound )
+			{
+				//m_DataSaver.AddLineToLast();
+				m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS );
+				m_DataSaver.AddLineToLast();
+			}
+		}
+		else
+		{
+			// No handle leaks
+			m_DataSaver.AddLineToLast();
+			m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS );
+			m_DataSaver.AddLineToLast();
+		}
+
+		// Process end to xml
+		m_DataSaver.SaveXML( sTime, RUN_END );
+		// Reset current process
+		m_iCurrentProcessId = 0;
+	}
+	
+	// If no dll load or process start found
+	if ( ! m_bProcessStartFound || !m_bDllLoadFound )
+	{
+		m_DataSaver.AddLineToLast();
+		m_DataSaver.AddString( AT_ANALYZE_INSUFFICIENT_LOGGING_DATA );
+		m_DataSaver.AddLineToLast();
+	}
+	
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseDllLoad
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseDllLoad( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseDllLoad");
+	//DLL_LOAD <DLL name> <Time stamp> <Memory start address> <Memory end address>
+	m_bDllLoadFound = true;
+	DLL_LOAD_INFO structDllInfo;
+	structDllInfo.iStartAddress = 0;
+	structDllInfo.iEndAddress = 0;
+	structDllInfo.iLeaks = 0;
+
+	// Skip "DLL_LOAD "
+	GetStringUntilNextSpace( sLine );
+
+	// Get module name
+	structDllInfo.sModuleName = GetStringUntilNextSpace( sLine );
+	ChangeToLower( structDllInfo.sModuleName );
+
+	// Create module from this if project platform emulator
+	if ( _stricmp( "winscw", m_sProjectPlatform.c_str() ) == 0 )
+		CreateWinscwModule( structDllInfo.sModuleName );
+
+	if ( m_iDataVersion >= AT_DLL_TIMESTAMP_DATA_VERSION )
+	{
+		// Pickup module loading time.
+		string sLoadTime = GetStringUntilNextSpace( sLine );
+		unsigned long long ull;
+		if ( hexToDec( sLoadTime, ull ) )
+			structDllInfo.iLoadTime = ull;
+	}
+
+	// Get dll start memory string address from line
+	// Convert string address to real memory address
+	structDllInfo.iStartAddress = 
+		_httoi( GetStringUntilNextSpace( sLine ).c_str() );
+
+	// Get dll end memory string address from line
+	// Convert string address to real memory address
+	structDllInfo.iEndAddress = 
+		_httoi( 
+		GetStringUntilNextSpace( sLine ).c_str() );
+
+	// Is module already loaded, if not add it to list.
+	bool bFound = false;
+	for( vector<DLL_LOAD_INFO>::iterator it = m_vDllLoadModList.begin();
+		it != m_vDllLoadModList.end() ; it++ )
+	{
+		if( (*it).sModuleName.compare( structDllInfo.sModuleName ) == 0 )
+		{
+			bFound = true;
+			break;
+		}
+	}
+	if( ! bFound )
+		m_vDllLoadModList.push_back( structDllInfo );
+
+	// Sub test module list.
+	bFound = false;
+	for( vector<DLL_LOAD_INFO>::iterator it = m_vDllLoadModListSubTest.begin();
+		it != m_vDllLoadModListSubTest.end() ; it++ )
+	{
+		if( (*it).sModuleName.compare( structDllInfo.sModuleName ) == 0 )
+		{
+			bFound = true;
+			break;
+		}
+	}
+	if( ! bFound )
+		m_vDllLoadModListSubTest.push_back( structDllInfo );
+
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseDllUnload
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseDllUnload( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseDllUnload");
+
+	// Ignore unloads on older version because no timestamps.
+	if ( m_iDataVersion < AT_DLL_TIMESTAMP_DATA_VERSION )
+	{
+		return true;
+	}
+
+	// Skip "DLL_UNLOAD "
+	GetStringUntilNextSpace( sLine );
+
+	// Get module name
+	string sModuleName = GetStringUntilNextSpace( sLine );
+	ChangeToLower( sModuleName );
+
+	// Unload time
+	unsigned long long ull;
+	string sUnload = GetStringUntilNextSpace( sLine );
+	if ( ! hexToDec( sUnload, ull ) )
+		return true;
+
+	// Set module unload time.
+	vector<DLL_LOAD_INFO>::iterator it;
+	for( it = m_vDllLoadModList.begin() ; it != m_vDllLoadModList.end() ; it++ )
+	{
+		if ( sModuleName.compare( it->sModuleName ) == 0 )
+		{
+			(*it).iUnloadTime = ull;
+			break;
+		}
+	}
+	for( it = m_vDllLoadModListSubTest.begin() ; it != m_vDllLoadModListSubTest.end() ; it++ )
+	{
+		if ( sModuleName.compare( it->sModuleName ) == 0 )
+		{
+			(*it).iUnloadTime = ull;
+			break;
+		}
+	}
+	return true;
+}
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseLoggingCancelled
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseLoggingCancelled( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseLoggingCancelled");
+	// Skip text "LOGGING_CANCELLED"
+	GetStringUntilNextSpace( sLine );
+
+	// Get time
+	string sTime( GetStringUntilNextSpace( sLine ) );
+	sTime = ConvertTimeToLocalTime( sTime );
+	m_DataSaver.AddString( "Logging Cancelled." );
+	m_DataSaver.AddLineToLast();
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseHandleLeak
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseHandleLeak( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseHandleLeak");
+	// Skip text "HANDLE_LEAK"
+	GetStringUntilNextSpace( sLine );
+	m_vHandleLeaks.push_back( sLine );
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseTestStart
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseTestStart( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseTestStart");
+	m_bSubtestOnGoing = true;
+	m_iLeakNumber = 0;
+	m_iPinPointedSubTestLeaks = 0;
+
+	// Reset subtest leaked modules list
+	for( size_t i = 0 ; i < m_vDllLoadModListSubTest.size() ; i++ )
+	{
+		m_vDllLoadModListSubTest.at(i).iLeaks = 0;
+	}
+
+	// Skip text "TEST_START"
+	GetStringUntilNextSpace( sLine );
+	// Time
+	string sTime( GetStringUntilNextSpace( sLine ) );
+	sTime = ConvertTimeToLocalTime( sTime );
+	// Name
+	string sSubTestName( GetStringUntilNextSpace( sLine ) );				
+	m_DataSaver.AddLineToLast();
+
+	// Get handle count in subtest start
+	string sSubTestStartHandleCount( GetStringUntilNextSpace( sLine ) );
+	m_iSubtestStartHandleCount = atoi( sSubTestStartHandleCount.c_str() );
+
+	// Add start to report
+	m_DataSaver.AddString( "\nSub test (" );
+	m_DataSaver.AddString( sSubTestName.c_str() );
+	m_DataSaver.AddString( ") start: " );
+	m_DataSaver.AddString( sTime.c_str() );
+
+	// m_DataSaver.AddLineToLast();
+
+	// Add start to xml
+	string sResult( sSubTestName );
+	sResult.append( ";" );
+	sResult.append( sTime );
+	sResult.append( ";" );
+	m_DataSaver.SaveXML( sResult, TEST_START );
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseTestEnd
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseTestEnd( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseTestEnd");
+	// Skip text "TEST_END"
+	GetStringUntilNextSpace( sLine );
+
+	// Time
+	string sTime( GetStringUntilNextSpace( sLine ) );
+	sTime = ConvertTimeToLocalTime( sTime );
+
+	// Name
+	string sSubTestName( GetStringUntilNextSpace( sLine ) );
+	m_DataSaver.AddLineToLast();
+
+	// Add test end info to report
+	m_DataSaver.AddString( "Sub test (" );
+	m_DataSaver.AddString( sSubTestName.c_str() );
+	m_DataSaver.AddString( ") end: " );
+	m_DataSaver.AddString( sTime.c_str() );
+	m_DataSaver.AddLineToLast();
+
+	// Leak count to report in subtest
+	if( m_iLeakNumber > 0 )
+	{
+		if ( m_iLogLevel == 1 || m_iLogLevel == 2 )
+		{
+			m_DataSaver.AddInteger( m_iPinPointedSubTestLeaks );
+			m_DataSaver.AddString( " number of pinpointed memory leaks." );
+			m_DataSaver.AddLineToLast();
+			m_DataSaver.AddInteger( m_iLeakNumber );
+			m_DataSaver.AddString( " memory leaks found." );
+		}
+		else
+		{
+			m_DataSaver.AddInteger( m_iLeakNumber );
+			m_DataSaver.AddString( " memory leaks found." );
+		}
+	}
+	else
+	{
+		m_DataSaver.AddString( "No memory leaks found." );
+	}
+	m_DataSaver.AddLineToLast();
+
+	// Use sTime to store info to xml
+	sTime.append(";");
+	char cTemp[128];
+	// Print all modules whitch have leaks
+	for( unsigned int i = 0 ; i < m_vDllLoadModListSubTest.size() ; i++ )
+	{
+		if( m_vDllLoadModListSubTest.at(i).iLeaks > 0 )
+		{
+			// Normal report
+			m_DataSaver.AddInteger( m_vDllLoadModListSubTest[i].iLeaks );
+			m_DataSaver.AddString( " memory leaks in module: " );
+			m_DataSaver.AddString( m_vDllLoadModListSubTest.at(i).sModuleName.c_str() );
+			m_DataSaver.AddLineToLast();
+			// xml
+			string sModuleNameAndLeaks( m_vDllLoadModListSubTest.at(i).sModuleName );
+			sModuleNameAndLeaks.append(";");
+			sModuleNameAndLeaks.append( itoa( m_vDllLoadModListSubTest.at(i).iLeaks, cTemp, 10 ) );
+			m_DataSaver.SaveXML( sModuleNameAndLeaks , SUBTEST_MEM_LEAK_MODULE );
+		}
+	}
+	// Handle count
+	int iEndHandleCount = atoi( GetStringUntilNextSpace( sLine ).c_str() );
+	// Is there handle leaks in subtest?
+	if( iEndHandleCount > m_iSubtestStartHandleCount )
+	{
+		// Print normal report
+		m_DataSaver.AddInteger( iEndHandleCount - m_iSubtestStartHandleCount );
+		m_DataSaver.AddString( " handle leaks in subtest: " );
+		m_DataSaver.AddString( sSubTestName.c_str() );
+		m_DataSaver.AddString( "." );
+		m_DataSaver.AddLineToLast();
+
+		// Print handle leaks to XML
+		string sNrOfHandleLeaks( itoa( iEndHandleCount - m_iSubtestStartHandleCount, cTemp, 10 ) );
+		sNrOfHandleLeaks.append( ";" );
+		m_DataSaver.SaveXML( sNrOfHandleLeaks, SUBTEST_HANDLE_LEAKS );
+	}
+	else
+	{
+		// No handle leaks
+		m_DataSaver.AddString( TEXT_NO_HANDLE_LEAKS );
+		m_DataSaver.AddLineToLast();
+	}
+	// Save xml
+	m_DataSaver.SaveXML( sTime, TEST_END );
+	// Back to normal leaks
+	m_bSubtestOnGoing = false;
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseErrorOccured
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseErrorOccured( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseErrorOccured");
+	string sTime,sError;
+
+	// Skip text "ERROR_OCCURED:"
+	GetStringUntilNextSpace( sLine );
+
+	// Get error
+	sError = GetStringUntilNextSpace( sLine );
+	// Get and convert error time
+	sTime = GetStringUntilNextSpace( sLine );
+	sTime = ConvertTimeToLocalTime( sTime );
+
+	// Print error line
+	m_DataSaver.AddLineToLast();
+	m_DataSaver.AddString( "Error occured on: " );
+	m_DataSaver.AddString( sTime.c_str() );
+	m_DataSaver.AddString( ". " );
+	m_DataSaver.AddString( "Symbian error code: " );
+	m_DataSaver.AddString( sError.c_str() );
+	m_DataSaver.AddString( "." );
+	m_DataSaver.AddLineToLast();
+
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ParseMemLeak
+// -----------------------------------------------------------------------------
+bool CATDatParser::ParseMemLeak( string& sLine )
+{
+	LOG_FUNC_ENTRY("CATDatParser::ParseMemLeak");
+	// Increment leak count
+	if ( ! m_bSubtestOnGoing )
+		m_iTotalNumberOfLeaks++;
+
+	// Increase leak number
+	m_iLeakNumber++;
+
+	// Leak data variables
+	string sModuleName;
+	string sLeakSize;
+	string sTime;
+	unsigned long long iTime = 0;
+	string sLeakAddress;
+	
+	// Skip text "MEM_LEAK"
+	GetStringUntilNextSpace( sLine );
+	// Get leak address
+	sLeakAddress = GetStringUntilNextSpace( sLine );
+	// Get time
+	sTime = GetStringUntilNextSpace( sLine );
+	// Convert time to decimal
+	hexToDec( sTime, iTime );
+	// Get memory reserve size
+	sLeakSize = GetStringUntilNextSpace( sLine );
+	// Convert leak time
+	sTime = ConvertTimeToLocalTime( sTime );
+
+	// Loop thru call stack and put memory addresses in vector
+	CleanMemoryAddresses(); // Clean memory address vector
+	CATMemoryAddress* pMemAddr = 0;
+	vector<string> vStrings = ParseStringToVector( sLine, ' ' );
+	for( size_t i = 0; i < vStrings.size() ; i++ )
+	{
+		pMemAddr = new CATMemoryAddress( vStrings.at(i), m_iOffSet );
+		// Set address time
+		pMemAddr->SetTime( iTime );
+		// Set address module name
+		if ( pMemAddr->FindSetModuleName( &m_vDllLoadModList ) )
+		{
+			// Increment leaks in module once
+			if ( sModuleName.empty() )
+			{
+				if ( m_bSubtestOnGoing )
+					m_vDllLoadModListSubTest.at( pMemAddr->GetDllLoadInfoIndex() ).iLeaks++;
+				else
+					m_vDllLoadModList.at( pMemAddr->GetDllLoadInfoIndex() ).iLeaks++;
+				// Set leak's module where it was located.
+				sModuleName = pMemAddr->GetModuleName();
+			}
+		}
+		// Add it to vector
+		m_vMemoryAddress.push_back( pMemAddr );
+	}
+	// If logging level is 0 Skip printing / locating code lines for call stack items.
+	if ( m_iLogLevel == 0 )
+		return true;
+	if ( m_pModules && vStrings.size() > 0 )
+	{
+		// Have we successfully located code line for memory address
+		bool bSuccesfullAddressToLine = false;
+		for( size_t x = 0; x < m_vMemoryAddress.size(); x++ )
+		{
+			int iIndexInDll = m_vMemoryAddress.at( x )->GetDllLoadInfoIndex();
+			if ( iIndexInDll != -1 )
+			{
+				// Dll module name from data file
+				string sDllName = m_vDllLoadModList.at( iIndexInDll ).sModuleName;
+				// Find module from project. These are read from makefiles.
+				for ( size_t y = 0; y < m_pModules->size() ; y++ )
+				{
+					// Module name from project data (makefiles)
+					string sModuleName = m_pModules->at( y )->GetBinaryName();
+					// If we find module from project ones, use it to located code line for memory address
+					// Note! dll names can be pretty messy i.e. DLL_LOAD 10281fc6.dll{000a0000}[10281fc6] 81d57b88 81e60a90
+					if ( sDllName.find( sModuleName ) != string::npos )
+					{
+						m_pModules->at( y )->AddressToLine( m_vMemoryAddress.at( x ) );
+						if ( ! bSuccesfullAddressToLine )
+						{
+							int iPPState = m_vMemoryAddress.at( x )->GetAddressToLineState();
+							if ( iPPState == CATMemoryAddress::EXACT || iPPState == CATMemoryAddress::FUNCTION )
+							{
+								bSuccesfullAddressToLine = true;
+								if ( m_bSubtestOnGoing )
+									m_iPinPointedSubTestLeaks++;
+								else
+									m_iPinPointedLeaks++;
+							}
+						}
+					}
+				}
+			}
+		}
+		// If rom/rofs specified we use it to try get binary and function names
+		// for addresses currently out of process range.
+		if ( m_pRomSymbol )
+		{
+			for( size_t x = 0; x < m_vMemoryAddress.size(); x++ )
+			{
+				if ( m_vMemoryAddress.at(x)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_PROCESS
+					|| m_vMemoryAddress.at(x)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_RANGE )
+				{
+					m_pRomSymbol->AddressToLine( m_vMemoryAddress.at(x) );
+				}
+			}
+		}
+	}
+	// Print leak
+	PrintMemLeak( sTime, sLeakSize, sLeakAddress, sModuleName);
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::PrintMemLeak
+// -----------------------------------------------------------------------------
+void CATDatParser::PrintMemLeak(const string& sTime,
+							   const string& sLeakSize,
+							   const string& sLeakAddr,
+							   const string& sModuleName)
+{
+	LOG_FUNC_ENTRY("CATDatParser::PrintMemLeak");
+	// Print header data of leak
+	m_DataSaver.AddString("\nMemory leak ");
+	m_DataSaver.AddInteger( m_iLeakNumber, true);
+
+	// Leak size
+	m_DataSaver.AddString( " (" );
+	m_DataSaver.AddInteger( _httoi( sLeakSize.c_str() ), true );
+	m_DataSaver.AddString( " bytes) " );
+
+	// Leak address
+	m_DataSaver.AddString("(0x");
+	m_DataSaver.AddString( sLeakAddr.c_str(), true );
+	m_DataSaver.AddString( ") " );
+
+	// Time
+	m_DataSaver.AddString( sTime.c_str(), true );
+	m_DataSaver.AddString( " " );
+	
+	// Module name
+	m_DataSaver.AddString( sModuleName.c_str(), true );
+	m_DataSaver.SaveCarbideDataHeader();
+	
+	// Add header line
+	m_DataSaver.AddLineToLast();
+
+	// Print the call stack items
+	for( size_t i = 0 ; i < m_vMemoryAddress.size() ; i++ )
+	{
+		// On log levels 1 & 2 we only print located code lines.
+		#ifndef ADDR2LINE
+		if( 
+			( m_iLogLevel == 1 || m_iLogLevel == 2 )
+			&&
+			( m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::EXACT
+			&& m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::FUNCTION )
+			)
+		{
+			// Skips to next
+			continue;
+		}
+		#endif
+		#ifdef ADDR2LINE
+		if( ( m_iLogLevel == 1 || m_iLogLevel == 2 )
+			&& m_vMemoryAddress.at(i)->GetAddressToLineState() != CATMemoryAddress::EXACT )
+		{
+			// Skips to next
+			continue;
+		}
+		#endif
+		else if ( m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::OUT_OF_PROCESS )
+		{
+			// Is memory address out of modules range
+			string sTemp;
+			sTemp.append( m_vMemoryAddress.at(i)->GetAddressString() );
+			sTemp.append( " Address out of process memory.");
+			m_DataSaver.AddString( sTemp.c_str(), true );
+			m_DataSaver.AddLineToLast();
+			continue;
+		}
+		
+		// Print memory address
+		m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetAddressString().c_str(), true );
+
+		// Space (only for console output)
+		m_DataSaver.AddString( " " );
+
+		m_DataSaver.AddCarbideData( 
+			NumberToHexString( m_vMemoryAddress.at(i)->GetOffSetFromModuleStart() ) );
+
+		// Module name
+		m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetModuleName().c_str(), true );
+
+		// Print call stack memory address details depending on state of memory address
+		switch( m_vMemoryAddress.at(i)->GetAddressToLineState() )
+		{
+			// Address outside of known processes
+		case CATMemoryAddress::OUT_OF_PROCESS:
+			m_DataSaver.AddLineToLast();
+			break;
+			// Address located outside of known modules symbols
+		case CATMemoryAddress::OUT_OF_RANGE:
+			m_DataSaver.AddString( " " );
+			m_DataSaver.AddString( "???", true );
+			m_DataSaver.AddLineToLast();
+			break;
+		// Symbol state is currently used when using rom symbol file.
+		// From it we get module name & function name.
+		case CATMemoryAddress::SYMBOL:
+			m_DataSaver.AddString( " " );
+			m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true );
+			if ( ! m_vMemoryAddress.at( i )->GetFileName().empty() )
+			{
+				m_DataSaver.AddString( " (" );
+				m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true );
+				m_DataSaver.AddString( ")" );
+			}
+			m_DataSaver.AddLineToLast();
+			break;
+		// Lst & Map implementation
+		#ifndef ADDR2LINE
+		case CATMemoryAddress::FUNCTION:
+		case CATMemoryAddress::EXACT:
+			m_DataSaver.AddString( " " );
+			m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true );
+			// Small difference displaying details depending on build urel/udeb
+			if ( m_eBuildType == CATProject::UREL )
+			{
+				// UREL
+				// Set build info to data saver
+				m_DataSaver.SetBuild( false );
+				// urel = functionname: linenumber (filename)
+				m_DataSaver.AddString( ": " );
+				if (  m_vMemoryAddress.at(i)->GetFunctionLineNumber() != -1 )
+					m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetFunctionLineNumber(), true );
+				else if (  m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 )
+					m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true );
+				m_DataSaver.AddString( " (" );
+				m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true );
+				m_DataSaver.AddString( ")" );
+				m_DataSaver.AddLineToLast();
+			}
+			else
+			{
+				// UDEB
+				// udeb = functionname: (filename:linenumber)
+				m_DataSaver.AddString( " (" );
+				m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true );
+				m_DataSaver.AddString( ":" );
+				if(  m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 )
+					m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true );
+				else
+					m_DataSaver.AddString( "???", true );
+				m_DataSaver.AddString( ")" );
+				m_DataSaver.AddLineToLast();
+			}
+			break;
+		#endif
+		// addr2line implementation (new).
+		#ifdef ADDR2LINE
+		case CATMemoryAddress::FUNCTION:
+			m_DataSaver.AddString( " " );
+			m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true );
+			m_DataSaver.AddString( " (" );
+			m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true );
+			m_DataSaver.AddString( ":" );
+			if(  m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 )
+				m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetFunctionLineNumber(), true );
+			else
+				m_DataSaver.AddString( "???", true );
+			m_DataSaver.AddString( ")" );
+			m_DataSaver.AddLineToLast();
+			break;
+		case CATMemoryAddress::EXACT:
+			m_DataSaver.AddString( " " );
+			m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFunctionName().c_str(), true );
+			m_DataSaver.AddString( " (" );
+			m_DataSaver.AddString( m_vMemoryAddress.at(i)->GetFileName().c_str(), true );
+			m_DataSaver.AddString( ":" );
+			if(  m_vMemoryAddress.at(i)->GetExactLineNumber() != -1 )
+				m_DataSaver.AddInteger( m_vMemoryAddress.at(i)->GetExactLineNumber(), true );
+			else
+				m_DataSaver.AddString( "???", true );
+			m_DataSaver.AddString( ")" );
+			m_DataSaver.AddLineToLast();
+			break;
+		#endif
+		} // End switch
+		// On logging level 1 we only print one located code line
+		#ifndef ADDR2LINE
+		if ( m_iLogLevel == 1 && ( m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::EXACT ||
+			m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::FUNCTION ) )
+			break;
+		#endif
+		#ifdef ADDR2LINE
+		if ( m_iLogLevel == 1 && m_vMemoryAddress.at(i)->GetAddressToLineState() == CATMemoryAddress::EXACT )
+			break;
+		#endif
+	} // End call stack items loop
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::SetInputFile
+// -----------------------------------------------------------------------------
+void CATDatParser::SetInputFile(const string& sInputFile)
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetInputFile");
+	m_sInputFile = sInputFile;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::SetOutputFile
+// -----------------------------------------------------------------------------
+void CATDatParser::SetOutputFile(const string& sOutpuFile)
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetOutputFile");
+	m_sOutputFile = sOutpuFile;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::SetRomSymbolFiles
+// -----------------------------------------------------------------------------
+void CATDatParser::SetRomSymbolFiles(const vector<string>& vRomSymbolFiles)
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetRomSymbolFiles");
+	m_vRomSymbolFiles = vRomSymbolFiles;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::SetLogLevel
+// -----------------------------------------------------------------------------
+void CATDatParser::SetLogLevel(int iLogLevel)
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetLogLevel");
+	m_iLogLevel = iLogLevel;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::GetLogLevel
+// -----------------------------------------------------------------------------
+int CATDatParser::GetLogLevel() const
+{
+	LOG_LOW_FUNC_ENTRY("CATDatParser::GetLogLevel");
+	return m_iLogLevel;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::CleanMemoryAddresses
+// -----------------------------------------------------------------------------
+void CATDatParser::CleanMemoryAddresses()
+{
+	LOG_LOW_FUNC_ENTRY("CATDatParser::CleanMemoryAddresses");
+	// Cleanup memory addressses.
+	for( vector<CATMemoryAddress*>::iterator it = m_vMemoryAddress.begin(); it != m_vMemoryAddress.end(); it++ )
+	{
+		delete *it;
+	}
+	m_vMemoryAddress.clear();
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::ConvertTimeToLocalTime
+// -----------------------------------------------------------------------------
+string CATDatParser::ConvertTimeToLocalTime( string sInputTime )
+{
+	LOG_LOW_FUNC_ENTRY("CATDatParser::ConvertTimeToLocalTime");
+	//Is process end abnormal?
+	if( sInputTime.compare( LABEL_ABNORMAL ) == 0 )
+	{
+		return string( AT_ANALYZE_ABNORMAL_EXIT );
+	}
+	else
+	// Check that input time is at least 32-bit
+	if( sInputTime.length() <= 8 )
+	{
+		sInputTime.clear();
+		return sInputTime;
+	}
+
+	string sTemp = sInputTime;
+	const char* pTemp = sTemp.c_str();
+
+	// Are all characters hex
+	for( unsigned int i = 0 ; i < sTemp.size() ; i++ )
+	{
+		if( !IsHexCharacter( (pTemp + i) ) )
+		{
+			return sInputTime;
+		}
+	}
+	
+	// Get LSB bits
+	string sLsb;
+	sLsb.append( sInputTime.substr( sInputTime.length()-8, sInputTime.length() ) );
+	unsigned int iLsbTime = (unsigned int)_httoi( sLsb.c_str() );
+
+	// Get MSB bits
+    string sMsb;
+	sMsb.append( sInputTime.substr( 0, sInputTime.length()-8 ) );
+	unsigned int iMsbTime = (unsigned int)_httoi( sMsb.c_str() );
+
+	// Get time in microsecods
+	long long sdf = iMsbTime * 0x100000000 + iLsbTime;
+
+	// Get original time (starting at year 1970 )
+	long long llOrigTime = sdf;
+
+	// Get seconds
+	sdf = ( sdf )/1000000;
+		
+	// Check that sdf contains some time value
+	if( sdf <= 0)
+	{
+		// Error in time calculation
+		// Return empty string
+		sInputTime.clear();
+		return sInputTime;
+	}
+
+	// Original time after year 1970 in seconds
+	long long llOrignTimeInSeconds = sdf;
+	
+	// Calculate new time which does not include millisecods
+	long long llDiffTime = (llOrignTimeInSeconds * 1000000);
+
+	// Calculate time difference in milliseconds
+	int llDiffTimeInMilliSecods = (int)( llOrigTime - llDiffTime )/1000;
+	
+	// Convert difference time to char
+	char cDiffInMilliSeconds[20];
+    _itoa( llDiffTimeInMilliSecods, cDiffInMilliSeconds, 10 );
+
+	// Time info structure
+	struct tm *timeinfo;
+
+	// Get local time
+	timeinfo = localtime ( (time_t*) &sdf );
+
+	// Create string and append memory leak time to it
+	string sTime;
+	sTime.append( asctime( timeinfo ) );
+
+	// Remove last char of locale time string which is \n
+	sTime.resize( (int)sTime.length()-1 );
+	
+	// Get last space index
+	int iLastSpace = (int)sTime.find_last_of(" ");
+
+	// If last space index is valid
+	if( iLastSpace <= (int)sTime.length() && iLastSpace > 0)
+	{
+		string sTempTime;
+		// Append first part of original time string
+		sTempTime.append( sTime.substr( 0, iLastSpace ) );
+		
+		// Append millisecods
+		sTempTime.append( "." );
+		sTempTime.append( cDiffInMilliSeconds );
+
+		// Append the rest of the original time string part
+		sTempTime.append( sTime.substr( iLastSpace, sTime.length()));
+
+		// Clear original and append new time string which includes millisecods
+		sTime.clear();
+		sTime.append( sTempTime );
+	}
+
+	// Return memory leak time
+	return sTime.c_str();
+}
+
+bool CATDatParser::CreateWinscwModule( const string& sBinaryName )
+{
+	LOG_FUNC_ENTRY( "CATDatParser::CreateWinscwModule" );
+	// Is module already created?
+	for( vector<CATModule2*>::iterator it = m_pModules->begin(); it != m_pModules->end(); it++ )
+	{
+		if ( _stricmp( sBinaryName.c_str(), (*it)->GetBinaryName().c_str() ) == 0 )
+			return true;
+	}
+	// No create new one and set its values.
+	CATModule2* mod = new CATModule2();
+	mod->SetTarget( RemovePathAndExt( sBinaryName, true ) );
+	mod->SetRequestedTargetExt( GetExtension( sBinaryName ) );
+	mod->SetReleasePath( string( "\\epoc32\\release" ) );
+	if ( m_eBuildType == CATProject::UDEB )
+		mod->SetFullVariantPath( string( "winscw\\udeb" ) );
+	else
+		mod->SetFullVariantPath( string( "winscw\\urel" ) );
+	mod->SetVariantPlatform( string( "winscw" ) );
+	m_pModules->push_back( mod );
+	return true;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::FindModuleUsingAddress
+// Function finds module using given address.
+// -----------------------------------------------------------------------------
+int CATDatParser::FindModuleUsingAddress( unsigned long iAddress ) const
+{
+	LOG_LOW_FUNC_ENTRY("CATDatParser::FindModuleUsingAddress");
+	int iRet = -1;
+	for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ )
+	{
+		// Is address between start and end address?
+		if( iAddress > m_vDllLoadModList[i].iStartAddress && iAddress < m_vDllLoadModList[i].iEndAddress )
+		{
+			iRet = i;
+			break;
+		}	
+	}
+	return iRet;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::FindModuleUsingPID
+// Function finds module using module id.
+// -----------------------------------------------------------------------------
+/*
+int CATDatParser::FindModuleUsingPID( unsigned long iPID ) const
+{
+	LOG_FUNC_ENTRY("CATDatParser::FindModuleUsingPID");
+
+	int iRet = -1;
+
+	// Change module name characters to lowercase
+	for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ )
+	{
+		if( m_vDllLoadModList[i].iPID == iPID )
+		{
+			iRet = i;
+			break;
+		}	
+	}
+	return iRet;
+}
+*/
+// -----------------------------------------------------------------------------
+// CATDatParser::FindModuleUsingName
+// Function finds module using module name.
+// -----------------------------------------------------------------------------
+int CATDatParser::FindModuleUsingName( const char* pModName )
+{
+	LOG_LOW_FUNC_ENTRY("CATDatParser::FindModuleUsingName");
+
+	// Mod name empty?
+	if( pModName == NULL || *pModName == 0 )
+		return -1;
+
+	int iRet = -1;
+	string sModName( pModName );
+	// Change module name characters to lowercase
+	ChangeToLower( sModName );
+	// Remove variant marks (dots)
+	RemoveAllAfterDotIfTwoDots( sModName);
+	for( unsigned int i = 0 ; i < m_vDllLoadModList.size() ; i++ )
+	{
+		string sTemp( m_vDllLoadModList[i].sModuleName );
+		ChangeToLower( sTemp );
+		// Remove variant marks (dots)
+		RemoveAllAfterDotIfTwoDots( sTemp );
+		if( sTemp.find( sModName ) != string::npos )
+		{
+			iRet = i;
+			break;
+		}	
+	}
+	return iRet;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::SetPrintFlag
+// -----------------------------------------------------------------------------
+void CATDatParser::SetPringFlag( bool bPrintFlag )
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetPringFlag");
+	m_DataSaver.SetPrintFlag( bPrintFlag );
+}
+// -----------------------------------------------------------------------------
+// CATDatParser::SetOffSet
+// -----------------------------------------------------------------------------
+void CATDatParser::SetOffSet( int iOffSet )
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetOffSet");
+	m_iOffSet = iOffSet;
+}
+
+// -----------------------------------------------------------------------------
+// CATDatParser::GetOffSet
+// -----------------------------------------------------------------------------
+int CATDatParser::GetOffSet( ) const
+{
+	LOG_LOW_FUNC_ENTRY("CATDatParser::GetOffSet");
+	return m_iOffSet;
+}
+
+// -----------------------------------------------------------------------------
+// Set project platform.
+// -----------------------------------------------------------------------------
+void CATDatParser::SetProjectPlatform( const string& sPlatform )
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetProjectPlatform");
+	m_sProjectPlatform = sPlatform;
+
+	// Check that platform not empty before determing platform from it.
+	if ( sPlatform.empty() )
+		return;
+
+	// Set functions offset in mapfiles correct (depending on platform).
+	if ( _stricmp( sPlatform.c_str(), "armv5" ) == 0 )
+	{
+		m_iOffSet = FUNCTIONS_OFFSET_IN_MAP_FILE_ARMV5;
+	}
+	else if ( _stricmp( sPlatform.c_str(), "winscw" ) == 0 )
+	{
+		m_iOffSet = FUNCTIONS_OFFSET_IN_MAP_FILE_WINSCW;
+	}
+	else if ( _stricmp( sPlatform.c_str(), "gcce" ) == 0 )
+	{
+		m_iOffSet = FUNCTIONS_OFFSET_IN_GCCE;
+	}
+	else
+	{
+		LOG_STRING( AT_MSG << "Error, cannot set function's offset in map file, invalid platform: " << sPlatform );
+	}
+}
+
+// -----------------------------------------------------------------------------
+// Set projects build type. Use enumeration defined in CATProject.
+// -----------------------------------------------------------------------------
+void CATDatParser::SetProjectBuildType( int eBuildType )
+{
+	LOG_FUNC_ENTRY("CATDatParser::SetProjectBuildType");
+	m_eProjectBuildType = eBuildType;
+}
+
+//EOF