bintools/rcomp/src/localise.cpp
changeset 0 044383f39525
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/rcomp/src/localise.cpp	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,2043 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+
+
+#include "main.h"
+#include "localise.h"
+
+#ifdef __VC32__ 
+#pragma warning( push, 1 )	// MS STL libraries do not compile cleanly, temporarily set warning level to 1
+#pragma warning( disable : 4710 )	// function not inlined.
+#pragma warning( disable : 4530 )	// function not inlined.
+#endif
+
+#include <stdio.h>   
+#include <iostream>
+#include "ERRORHAN.H"
+
+#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
+using std::ifstream;
+using std::cerr;
+using std::endl;
+#endif //__MSVCDOTNET__
+
+
+
+/******************************************************************************************
+**
+** RlsItemRequirements
+**
+******************************************************************************************/
+
+RlsItemRequirements::RlsItemRequirements(String aRlsName, int aRequirement)
+	:iRlsName(aRlsName),
+	iRequirement(aRequirement)
+	{}
+
+RlsItemRequirements::RlsItemRequirements(const RlsItemRequirements & aRlsItemRequirements)
+	:iRlsName(aRlsItemRequirements.iRlsName),
+	iRequirement(aRlsItemRequirements.iRequirement)
+	{}
+	
+RlsItemRequirements::~RlsItemRequirements() 
+	{}
+
+/******************************************************************************************
+**
+** CommandRequirementsHolder
+**
+******************************************************************************************/
+
+CommandRequirementsHolder::CommandRequirementsHolder(String aCommandName)
+	:iCommandName(aCommandName)
+	{
+	iRlsRequirements.clear();
+	}
+
+CommandRequirementsHolder::CommandRequirementsHolder(const CommandRequirementsHolder & aCommandRequirmentsHolder)
+	:iCommandName(aCommandRequirmentsHolder.iCommandName)
+	{
+	for(unsigned int j = 0; j < aCommandRequirmentsHolder.iRlsRequirements.size() ; j++)
+		{
+		iRlsRequirements.push_back(aCommandRequirmentsHolder.iRlsRequirements[j]);
+		}
+	}
+	
+CommandRequirementsHolder::~CommandRequirementsHolder()
+	{}
+
+/******************************************************************************************
+**
+** TagParameterData
+**
+******************************************************************************************/
+
+TagParameterData::TagParameterData(String aTagParameter)
+	:iTagParameter(aTagParameter)
+	{}
+
+TagParameterData::TagParameterData(const TagParameterData & aTagParameterData)
+	:iTagParameter(aTagParameterData.iTagParameter)
+	{}
+
+TagParameterData::~TagParameterData()
+	{}
+
+void TagParameterData::SetTagParameter(String aTagParameter)
+	{
+	iTagParameter = aTagParameter;
+	}
+
+String TagParameterData::GetTagParameter()
+	{
+	return iTagParameter;
+	}
+
+/******************************************************************************************
+**
+** CommentRequirement
+**
+******************************************************************************************/
+
+CommentRequirement::CommentRequirement(int aRequirementStatus, String aDefaultParameter)
+	:iRequirementStatus(aRequirementStatus),
+	iDefaultParameter(aDefaultParameter)
+	{
+	}
+
+CommentRequirement::CommentRequirement(const CommentRequirement & aCommentRequirement)
+	:iRequirementStatus(aCommentRequirement.iRequirementStatus),
+	iDefaultParameter(aCommentRequirement.iDefaultParameter)
+	{
+	}
+
+CommentRequirement::~CommentRequirement()
+	{}
+
+String CommentRequirement::GetDefault()
+	{
+	return iDefaultParameter;
+	}
+
+int CommentRequirement::GetRequirementStatus()
+	{
+	return iRequirementStatus;
+	}
+
+/******************************************************************************************
+**
+** CommentRequirementPair
+**
+******************************************************************************************/
+
+CommentRequirementPair::CommentRequirementPair(String aRlsItem, int aStatus, String aDefault)
+	:iRlsItem(aRlsItem),
+	iCommentRequirementData(aStatus, aDefault)
+	{
+	}
+
+CommentRequirementPair::CommentRequirementPair(const CommentRequirementPair & aCommentRequirementPair)
+	:iRlsItem(aCommentRequirementPair.iRlsItem),
+	iCommentRequirementData(aCommentRequirementPair.iCommentRequirementData)
+	{}
+
+CommentRequirementPair::~CommentRequirementPair()
+	{}
+
+int CommentRequirementPair::GetRequirementStatus()
+	{
+	return iCommentRequirementData.GetRequirementStatus();
+	}
+
+String CommentRequirementPair::CheckIfOptionalAndHasDefault(String aRlsTypeName, String aCommandName)
+	{ // returns a String containing a line which needs to be written out to the rpp file, or returns ""
+	String optionalLineToAdd = "";
+	if(iRlsItem == aRlsTypeName)
+		{
+		int requirementStatus = iCommentRequirementData.GetRequirementStatus();
+		if(requirementStatus == EOptionalWithDefault)
+			{
+			String defaultValue = iCommentRequirementData.GetDefault();
+			if(defaultValue.Length()) // will only return true if a default exists
+				{
+				optionalLineToAdd = "@";
+				optionalLineToAdd += aCommandName;
+				String tempString(" ");
+				optionalLineToAdd += tempString;
+				optionalLineToAdd += defaultValue;
+				tempString = "\n";
+				optionalLineToAdd += tempString;
+				}
+			}
+		}
+	return optionalLineToAdd;
+	}
+
+String CommentRequirementPair::GetRlsItem()
+	{
+	return iRlsItem;
+	}
+
+void CommentRequirementPair::SetRlsItem(String aRlsItem)
+	{
+	iRlsItem = aRlsItem;
+	}
+
+/******************************************************************************************
+**
+** CommentTag
+**
+******************************************************************************************/
+
+CommentTag::CommentTag(String aTagType, bool aTagDeclared)
+	:iTagDeclared( aTagDeclared ),
+	iParameterType( aTagType )
+	{
+	iPermissibleParameters.clear();
+	iRequirements.clear();
+	}
+
+CommentTag::CommentTag(const CommentTag & aCommentTag)
+	:iTagDeclared( aCommentTag.iTagDeclared ),
+	iParameterType( aCommentTag.iParameterType )
+	{
+	unsigned int j;
+	for(j=0; j< aCommentTag.iPermissibleParameters.size(); j++)
+		{
+		iPermissibleParameters.push_back(aCommentTag.iPermissibleParameters[j]);
+		}
+	for(j=0; j< aCommentTag.iRequirements.size(); j++)
+		{
+		iRequirements.push_back(aCommentTag.iRequirements[j]);
+		}
+	}		
+			
+CommentTag::~CommentTag()
+	{}
+
+String CommentTag::CheckIfOptionalAndHasDefault(String aRlsTypeName, String aCommandName)
+	{
+	if(iTagDeclared)
+		{
+		for(unsigned int j=0; j<iRequirements.size(); j++)
+			{
+			String defaultParameter = iRequirements[j].CheckIfOptionalAndHasDefault(aRlsTypeName, aCommandName);
+			if(defaultParameter.Length())
+				return defaultParameter; // returns default parameter if it exists
+			}
+		}
+	return ""; // returns "" if no default parameter exists
+	}
+		
+int CommentTag::GetRequirementStatus(String aRlsItem)
+	{
+	for(unsigned int j=0; j<iRequirements.size(); j++)
+		{
+		if(iRequirements[j].GetRlsItem() == aRlsItem)
+			{
+			int requirementStatus = iRequirements[j].GetRequirementStatus();
+			return requirementStatus;
+			}
+		}
+	return EForbidden;
+	}
+
+bool CommentTag::IsTagLegalForRlsType(String aRlsTypeName)
+	{
+	for(unsigned int j=0; j<iRequirements.size(); j++)
+		{
+		if(iRequirements[j].GetRlsItem() == aRlsTypeName)
+			{
+			return iRequirements[j].GetRequirementStatus() != EForbidden ? true : false; 
+			}
+		}
+	return false;
+	}
+
+bool CommentTag::IsParameterAlreadyDeclared(String aTagParameter)
+	{
+	for(int j=0; j<GetNumberOfPermissibleParameters(); j++)
+		{
+		if(iPermissibleParameters[j].GetTagParameter() == aTagParameter)
+			{
+			return true; // returns true if the given parameter is already declared
+			}
+		}
+	return false;
+	}
+
+String CommentTag::GetPermissibleParameter(int aIndex) // returns pointer to aIndex-th parameter
+	{
+	return iPermissibleParameters[aIndex].GetTagParameter();
+	}
+
+int CommentTag::GetNumberOfPermissibleParameters()
+	{
+	return iPermissibleParameters.size();
+	}
+
+bool CommentTag::IsTagDeclared()
+	{
+	return iTagDeclared;
+	}
+
+void CommentTag::SetDeclared()
+	{
+	iTagDeclared = true;
+	}
+
+
+void CommentTag::SetParameterType(String aParameterType)
+	{
+	iParameterType = aParameterType;
+	}
+
+String CommentTag::GetParameterType()
+	{
+	return iParameterType;
+	}
+
+void CommentTag::AddTagParameterData(String aTagParameterData)
+	{
+	TagParameterData dataToAdd( aTagParameterData );
+	iPermissibleParameters.push_back( dataToAdd );
+	}
+
+void CommentTag::AddRequirements(String aRlsItem, int aRequired, String aDefault)
+	{
+	CommentRequirementPair commentRequirementPair( aRlsItem, aRequired, aDefault );
+	iRequirements.push_back( commentRequirementPair );
+	}
+
+/******************************************************************************************
+**
+** CommentTag
+**
+******************************************************************************************/
+
+CommentTagPair::CommentTagPair(String aCommandName, String aParameterType, bool aTagDeclared)
+	:iCommandName(aCommandName),
+	iTagVariables(aParameterType, aTagDeclared)
+	{}
+	
+CommentTagPair::CommentTagPair(const CommentTagPair & aCommentTagPair)
+	:iCommandName(aCommentTagPair.iCommandName),
+	iTagVariables(aCommentTagPair.iTagVariables)
+	{}
+	
+CommentTagPair::~CommentTagPair()
+	{}
+
+String CommentTagPair::CheckIfOptionalAndHasDefault(String aRlsTypeName)
+	{
+	return iTagVariables.CheckIfOptionalAndHasDefault(aRlsTypeName, iCommandName);
+	}
+
+int CommentTagPair::GetRequirementStatus(String aRlsItem)
+	{
+	return iTagVariables.GetRequirementStatus( aRlsItem );
+	}
+
+bool CommentTagPair::IsTagLegalForRlsType(String aRlsTypeName)
+	{
+	return iTagVariables.IsTagLegalForRlsType(aRlsTypeName);
+	}
+
+bool CommentTagPair::IsParameterAlreadyDeclared(String aTagParameter)
+	{
+	return iTagVariables.IsParameterAlreadyDeclared(aTagParameter);
+	}
+
+String CommentTagPair::GetPermissibleParameter(int aIndex)
+	{
+	return iTagVariables.GetPermissibleParameter(aIndex);
+	}
+
+int CommentTagPair::GetNumberOfPermissibleParameters()
+	{
+	return iTagVariables.GetNumberOfPermissibleParameters();
+	}
+
+void CommentTagPair::SetCommandName(String aCommandName)
+	{
+	iCommandName = aCommandName;
+	}
+
+String CommentTagPair::GetCommandName()
+	{
+	return iCommandName;
+	}
+
+void CommentTagPair::SetTagDeclared()
+	{
+	iTagVariables.SetDeclared();
+	}
+
+bool CommentTagPair::TagDeclared()
+	{
+	return iTagVariables.IsTagDeclared();
+	}
+
+String CommentTagPair::GetParameterType()
+	{
+	return iTagVariables.GetParameterType();
+	}
+
+void CommentTagPair::AddPermissibleParameter(String aPermissibleParameter)
+	{
+	iTagVariables.AddTagParameterData( aPermissibleParameter );
+	}
+
+void CommentTagPair::AddRlsItem(String aRlsItem, int aRequired, String aDefault)
+	{
+	iTagVariables.AddRequirements(aRlsItem, aRequired, aDefault);
+	}
+
+/******************************************************************************************
+**
+** LocalisationLine
+**
+******************************************************************************************/
+
+LocalisationLine::LocalisationLine(String aFileName, int aFirstLine)
+	:iAnalysed(false),
+	iFirstLine(aFirstLine),
+	iLastLine(aFirstLine),
+	iFileName(aFileName)
+	{
+	iData.clear();
+	}
+
+LocalisationLine::LocalisationLine(const LocalisationLine & aLocalisationLine)
+	:iAnalysed(aLocalisationLine.iAnalysed),
+	iFirstLine(aLocalisationLine.iFirstLine),
+	iLastLine(aLocalisationLine.iLastLine),
+	iFileName(aLocalisationLine.iFileName)	
+	{
+	for(unsigned int j=0; j<aLocalisationLine.iData.size(); j++)
+		{
+		iData.push_back(aLocalisationLine.iData[j]);
+		}
+	}
+
+LocalisationLine::~LocalisationLine()
+	{}
+
+void LocalisationLine::Reset(String aFileName, int aFirstLine)
+	{
+	iFirstLine = aFirstLine;
+	iLastLine = aFirstLine;
+	iFileName = aFileName;
+	iAnalysed = false;
+	iData.clear();
+	}
+
+String LocalisationLine::GetFileName()
+	{
+	return iFileName;
+	}
+
+int LocalisationLine::GetFirstLine()
+	{
+	return iFirstLine;
+	}
+
+int LocalisationLine::GetLastLine()
+	{
+	return iLastLine;
+	}
+
+void LocalisationLine::SetFirstLine(int aFirstLine)
+	{
+	iFirstLine = aFirstLine;
+	}
+
+void LocalisationLine::SetFileName(String aFileName)
+	{
+	iFileName = aFileName;
+	}
+
+unsigned int LocalisationLine::GetNumberOfTokens()
+	{
+	return iData.size();
+	}
+
+String LocalisationLine::GetElement(unsigned int aIndex)
+	{
+	return iData[aIndex];
+	}
+
+void LocalisationLine::AddElement(String aElement)
+	{
+	iData.push_back(aElement);
+	}
+
+void LocalisationLine::SetLastLine(int aLastLine)
+	{
+	iLastLine = aLastLine;
+	}
+
+void LocalisationLine::SetAnalysed(bool aParity)
+	{
+	iAnalysed = aParity;
+	}
+
+void LocalisationLine::Empty()
+	{
+	iData.clear();
+	}
+
+bool LocalisationLine::IsLineAnalysed()
+	{
+	return iAnalysed;
+	}
+
+/******************************************************************************************
+**
+** LocalisationComment
+**
+******************************************************************************************/
+
+
+LocalisationComment::LocalisationComment(LocalisationLine & aComment)
+	:iOriginalData(aComment)
+	{
+	iData.clear();
+	iOptionalLinesToAdd.clear();
+	}
+
+LocalisationComment::~LocalisationComment()
+	{
+	}
+
+String LocalisationComment::GetFileName()
+	{
+	return iOriginalData.GetFileName();
+	}
+
+int LocalisationComment::GetFirstLineOfComment()
+	{
+	return iOriginalData.GetFirstLine();
+	}
+
+int LocalisationComment::GetLastLineOfComment()
+	{
+	return iOriginalData.GetLastLine();
+	}
+
+int LocalisationComment::GetNumberOfOptionalLinesToAdd()
+	{
+	return iOptionalLinesToAdd.size();
+	}
+
+unsigned int LocalisationComment::GetNumberOfTokensInComment()
+	{
+	return iOriginalData.GetNumberOfTokens();
+	}
+
+String LocalisationComment::GetOriginalElement(unsigned int aIndex)
+	{
+	return iOriginalData.GetElement(aIndex);
+	}
+
+void LocalisationComment::AddDataLine(LocalisationLine aDataLine)
+	{
+	iData.push_back( aDataLine );
+	}
+
+unsigned int LocalisationComment::GetNumberOfTokensInLine(unsigned int aIndex)
+	{
+	return iData[aIndex].GetNumberOfTokens();
+	}
+
+LocalisationLine LocalisationComment::GetLine(unsigned int aIndex)
+	{
+	return iData[aIndex];
+	}
+
+void LocalisationComment::SetAnalysed(unsigned int aIndex, bool aParity)
+	{
+	iData[aIndex].SetAnalysed(aParity);
+	}
+
+void LocalisationComment::SetLastLine(int aLineNumber)
+	{
+	iOriginalData.SetLastLine(aLineNumber);
+	}
+
+bool LocalisationComment::IsLineAnalysed(unsigned int aIndex)
+	{
+	return iData[aIndex].IsLineAnalysed();
+	}
+
+void LocalisationComment::SetWholeTagAnalysed(bool aParity)
+	{
+	iOriginalData.SetAnalysed(aParity);
+	}
+
+String LocalisationComment::GetElementFromLine(unsigned int aLine, unsigned int aElement)
+	{
+	return iData[aLine].GetElement(aElement);
+	}
+
+int LocalisationComment::GetFirstLine(unsigned int aIndex)
+	{
+	return iData[aIndex].GetFirstLine();
+	}
+
+void LocalisationComment::AddOptionalData(String aOptionalData)
+	{
+	iOptionalLinesToAdd.push_back(aOptionalData);
+	}
+
+String LocalisationComment::GetOptionalLineToAdd(unsigned int aLine)
+	{
+	return iOptionalLinesToAdd[aLine];
+	}
+
+unsigned int LocalisationComment::GetNumberOfLinesInComment()
+	{
+	return iData.size();
+	}
+
+/******************************************************************************************
+**
+** WarningToOutput
+**
+******************************************************************************************/
+
+WarningToOutput::WarningToOutput(const String aFileName, int aLineNumber, String aComment)
+	:iFileName(aFileName),
+	iLineNumber(aLineNumber),
+	iComment(aComment)
+	{}
+
+WarningToOutput::WarningToOutput(const WarningToOutput & aWarningToOutput)
+	:iFileName(aWarningToOutput.iFileName),
+	iLineNumber(aWarningToOutput.iLineNumber),
+	iComment(aWarningToOutput.iComment)
+	{}
+	
+WarningToOutput::~WarningToOutput()
+	{}
+
+const String WarningToOutput::GetFileName()
+	{
+	return iFileName;
+	}
+
+int WarningToOutput::GetLineNumber()
+	{
+	return iLineNumber;
+	}
+
+String WarningToOutput::GetComment()
+	{
+	return iComment;
+	}
+
+WarningToOutput& WarningToOutput::operator=(const WarningToOutput& aWarningToOutput)
+	{
+	if(&aWarningToOutput==this)
+		return *this;
+	iFileName = aWarningToOutput.iFileName;
+	iLineNumber = aWarningToOutput.iLineNumber;
+	iComment = aWarningToOutput.iComment;
+	return *this;
+	}
+
+/******************************************************************************************
+**
+** GlobalLocalisationData
+**
+******************************************************************************************/
+
+GlobalLocalisationData::GlobalLocalisationData() 
+	:iCommentStarted(true)
+	{
+	iTypes[0] = "single";
+	iTypes[1] = "multiple";
+	iTypes[2] = "void";
+	iTypes[3] = "text";
+	iRlsTypes[0] = "rls_string";
+	iRlsTypes[1] = "rls_string8";
+	iRlsTypes[2] = "rls_byte";
+	iRlsTypes[3] = "rls_word";
+	iRlsTypes[4] = "rls_long";
+	iRlsTypes[5] = "rls_double";
+	iRlsTypes[6] = "RESOURCE";
+	iCommentTagStore.clear();
+	iCommentDefinitions.clear();
+	iWarningStore.clear();
+	}
+
+GlobalLocalisationData::~GlobalLocalisationData() 
+	{
+	}
+	
+int GlobalLocalisationData::NeedToAddDefaultData(String aFileName, int aFileLine)
+	{
+	for(unsigned int j=0; j<iCommentTagStore.size(); j++)
+		{
+		String fileName = iCommentTagStore[j].GetFileName();
+		if(fileName == aFileName)
+			{
+			int lastLine = iCommentTagStore[j].GetLastLineOfComment();
+			if(lastLine == aFileLine)
+				{
+				if(iCommentTagStore[j].GetNumberOfOptionalLinesToAdd())
+					return j; // returns the index of the localisation comment which needs default data adding
+				else
+					return -1; // if default data doesn't need adding for this rls item then returns -1
+				}
+			}
+		}
+	return -1;
+	}
+
+void GlobalLocalisationData::AddCommentToStore()
+	{
+	LocalisationComment aLocalisationComment( iTempCommentStore );
+	iCommentTagStore.push_back(aLocalisationComment);
+	}
+
+void GlobalLocalisationData::SetStart(String aFileName, int aLineNumber)
+	{
+	if(iCommentStarted == false) //means that any time other than first time, contents will be added to Store
+		{
+		AddCommentToStore();
+		iTempCommentStore.Reset(aFileName, aLineNumber); // empties the temporary comment store
+		}
+	else
+		{
+		iTempCommentStore.SetFirstLine( aLineNumber );
+		iTempCommentStore.SetFileName( aFileName );
+		}
+	iCommentStarted = false;
+	}
+
+void GlobalLocalisationData::AnalyseLocalisationData()
+	{
+	for(unsigned int i = 0; i < iCommentTagStore.size(); i++)
+		{
+		ParseCommentTags(i);
+		}
+	CheckIfCommentTagsFullyAnalysed();
+	CheckRlsEntries();
+	}
+
+void GlobalLocalisationData::ParseCommentTags(unsigned int i)
+	{
+	LocalisationLine tagCommandLine;
+	int newLinesSeen = 0;
+	int currentIndex;
+	int state = EStartOfComment;
+	tagCommandLine.SetFileName(iCommentTagStore[i].GetFileName());
+	int startLineNumber = iCommentTagStore[i].GetFirstLineOfComment();
+
+	// parse all the comment tags to find definitions and values
+	unsigned int originalNumberOfTokensInComment = iCommentTagStore[i].GetNumberOfTokensInComment();
+	for(unsigned int j = 0; j < originalNumberOfTokensInComment; j++)
+		{
+		bool wordIsNewLine = iCommentTagStore[i].GetOriginalElement(j) == "\n" ? true : false;
+
+		switch(state)
+			{
+			case(EStartOfComment):
+				switch(wordIsNewLine)
+					{
+					case(true): 
+						state = ENewLineAtStart;
+						newLinesSeen++;
+						break;
+					default: 
+						state = EAfterFirstWordOfTag;
+						tagCommandLine.SetFirstLine(startLineNumber + newLinesSeen);
+						tagCommandLine.SetLastLine(tagCommandLine.GetFirstLine());
+ 						tagCommandLine.AddElement(iCommentTagStore[i].GetOriginalElement(j));
+					}
+				break;
+			case(EAfterFirstWordOfTag):
+				switch(wordIsNewLine)
+					{
+					case(true):
+						state = ENewLineInTag;
+						newLinesSeen++;
+						break;
+					default:
+						state = EInTag;
+						tagCommandLine.AddElement( iCommentTagStore[i].GetOriginalElement(j) );
+					}
+				break;
+			case(ENewLineAtStart):
+				switch(wordIsNewLine)
+					{
+					case(true):
+						newLinesSeen++;
+						break;
+					default:
+						state = EAfterFirstWordOfTag;
+						tagCommandLine.SetFirstLine(startLineNumber + newLinesSeen);
+						tagCommandLine.SetLastLine( tagCommandLine.GetFirstLine() );
+						tagCommandLine.AddElement( iCommentTagStore[i].GetOriginalElement(j) );
+					}
+				break;
+			case(EInTag):
+				switch(wordIsNewLine)
+					{
+					case(true):
+						state = ENewLineInTag;
+						newLinesSeen++;
+						break;
+					default:
+						state = EInTag;
+						tagCommandLine.AddElement( iCommentTagStore[i].GetOriginalElement(j) );
+					}
+				break;
+			case(ENewLineInTag):
+				{
+				if(wordIsNewLine)
+					{
+					newLinesSeen++;
+					}
+				else if( iCommentTagStore[i].GetOriginalElement(j).FindSubString("@")==0)
+					{
+					iCommentTagStore[i].AddDataLine( tagCommandLine );
+					currentIndex = iCommentTagStore[i].GetNumberOfLinesInComment()-1;
+					Process(i, currentIndex);
+					tagCommandLine.Empty();
+					tagCommandLine.AddElement(iCommentTagStore[i].GetOriginalElement(j));
+					tagCommandLine.SetFirstLine( startLineNumber + newLinesSeen );
+					tagCommandLine.SetLastLine( tagCommandLine.GetFirstLine() );
+					state = EAfterFirstWordOfTag;
+					}
+				else
+					{
+					state = EInTag;
+					tagCommandLine.AddElement(iCommentTagStore[i].GetOriginalElement(j));
+					tagCommandLine.SetLastLine( startLineNumber + newLinesSeen );
+					}
+				}
+			}
+		}
+
+	if( tagCommandLine.GetNumberOfTokens() )
+		{
+		iCommentTagStore[i].AddDataLine( tagCommandLine );
+		currentIndex = iCommentTagStore[i].GetNumberOfLinesInComment()-1;
+		Process( i, currentIndex ); // process the current tag and parameters
+		}
+	iCommentTagStore[i].SetLastLine( startLineNumber + newLinesSeen );
+	}
+
+
+void GlobalLocalisationData::CheckIfCommentTagsFullyAnalysed()
+	{
+	for(unsigned int i = 0; i < iCommentTagStore.size(); i++)	//for each of the original comments sets whether or not all parts analysed
+		{
+		bool allAnalysed = true; //set to true then see if any are not analysed in which case will set to false
+		unsigned int numberOfLinesInComment = iCommentTagStore[i].GetNumberOfLinesInComment();
+		for(unsigned int j=0;j < numberOfLinesInComment && allAnalysed; j++)
+			{
+			if(iCommentTagStore[i].IsLineAnalysed(j) == false)
+				allAnalysed = false;
+			}
+		if(allAnalysed)
+			{
+			iCommentTagStore[i].SetWholeTagAnalysed( true );
+			}
+		}
+	}
+
+void GlobalLocalisationData::CheckRlsEntries()
+	{
+	// check each rls item to see if there is a localisation comment before it
+
+	TNameIndex::iterator end = pG->RlsNameIndex.end();
+	String rlsTypeName;
+	for (TNameIndex::iterator k = pG->RlsNameIndex.begin(); k != end; ++k)
+		{
+		int index = k->second;
+		int rlsLineNumber = pG->RlsValues[index].iLineNumber;
+		switch(pG->RlsValues[index].iType) 
+			{
+			case(ERlsString):
+			case(ERlsStringChar):
+				rlsTypeName = iRlsTypes[0];
+				break;
+			case(ERlsString8):
+				rlsTypeName = iRlsTypes[1];
+				break;
+			case(ERlsByte):
+			case(ERlsByteChar):
+				rlsTypeName = iRlsTypes[2];
+				break;
+			case(ERlsWord):
+			case(ERlsWordChar):
+				rlsTypeName = iRlsTypes[3];
+				break;
+			case(ERlsLong):
+			case(ERlsLongChar):
+				rlsTypeName = iRlsTypes[4];
+				break;
+			case(ERlsDouble):
+				rlsTypeName = iRlsTypes[5];
+				break;
+			default:
+				rlsTypeName="";
+			}
+		const String rlsFileName = *(pG->RlsValues[index].iFileName);		
+		int commentOfInterest = FindIndex(rlsFileName, rlsLineNumber);
+		if(commentOfInterest == -1) // signifies there is no comment before rls declaration
+			{
+			Message * message = pG->Messages.GetEntry(LT_005);
+			if(message->GetActivated())
+				{
+				pGL->AddWarningToStore(rlsFileName, rlsLineNumber, message->GetMessageOutput());
+				}
+			}
+		else //know that there exists a tag directly before the rls item
+			{
+			CheckCommands(rlsTypeName, commentOfInterest);
+			}
+		}
+	}
+
+bool GlobalLocalisationData::LocalisationCommentsExist()
+	{
+	return (iCommentTagStore.size()) ? true : false;
+	}
+
+void GlobalLocalisationData::CheckCommands(String aRlsTypeName, int aCommentOfInterest)
+	{
+	std::vector<String> commentsSeen;
+	unsigned int numberOfLines = iCommentTagStore[aCommentOfInterest].GetNumberOfLinesInComment();
+	for(unsigned int j=0; j<numberOfLines; j++) // for each command in the particular comment
+		{
+		if(iCommentTagStore[aCommentOfInterest].IsLineAnalysed(j) == false)
+			{
+			iCommentTagStore[aCommentOfInterest].SetAnalysed( j, true );
+			String commandName = iCommentTagStore[aCommentOfInterest].GetElementFromLine( j, 0 ); //gets tag value
+			int length = commandName.Length();
+			String tempCommandName = commandName.ExtractSubString(1, length-1); //strips off @ symbol
+
+			int definitionNumber = iCommentDefinitions.size();
+			for(int k=0; k<definitionNumber; k++) // finds tempCommandName in iCommentDefinitions
+				if(iCommentDefinitions[k].GetCommandName() == tempCommandName)
+					definitionNumber = k;
+
+			if(definitionNumber == (int)iCommentDefinitions.size()) // if tempCommandName not found
+				{
+				Message * message = pG->Messages.GetEntry(LT_006);
+				String fileName = iCommentTagStore[aCommentOfInterest].GetFileName();
+				int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+				if(message->GetActivated())
+					{
+					pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+					}
+				}
+			else if(iCommentDefinitions[definitionNumber].TagDeclared() == false) // if tempCommandName not declared
+				{
+				Message * message = pG->Messages.GetEntry(LT_006);
+				String fileName = iCommentTagStore[aCommentOfInterest].GetFileName();
+				int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+				if(message->GetActivated())
+					{
+					pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+					}
+				}
+			else 
+				{
+				bool commentAlreadySeen=false;
+				unsigned int numberOfCommentsSeen = commentsSeen.size();
+				for(unsigned int k=0; k<numberOfCommentsSeen && commentAlreadySeen == false ;k++) 
+					{ // checks in the commentsSeen vector for whether or not the tag has already been used
+					if(commandName==commentsSeen[k])
+						{
+						Message * message = pG->Messages.GetEntry(LT_007);
+						String fileName = iCommentTagStore[aCommentOfInterest].GetFileName();
+						int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+						if(message->GetActivated())
+							{
+							pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+							}
+						commentAlreadySeen = true;
+						}
+					}
+				if(commentAlreadySeen == false)
+					{
+					commentsSeen.push_back(commandName); // new tag so store it
+					if(iCommentDefinitions[definitionNumber].IsTagLegalForRlsType(aRlsTypeName) == false)
+						{
+						Message * message = pG->Messages.GetEntry(LT_008);
+						String fileName =iCommentTagStore[aCommentOfInterest].GetFileName();
+						int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+						if(message->GetActivated())
+							{
+							pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+							}
+						}
+					else
+						{
+						String parameterType = iCommentDefinitions[definitionNumber].GetParameterType();
+						int numberOfArgs = iCommentTagStore[aCommentOfInterest].GetNumberOfTokensInLine(j) - 1;
+						if(parameterType == "void")
+							{
+							if(numberOfArgs!=0) //void must have no arguments
+								{	
+								Message * message = pG->Messages.GetEntry(LT_009);
+								String fileName =iCommentTagStore[aCommentOfInterest].GetFileName();
+								int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+								if(message->GetActivated())
+									{
+									pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+									}
+								}
+							}
+						else if(parameterType == "single")
+							{
+							if(numberOfArgs!=1) //single must have one argument
+								{
+								Message * message = pG->Messages.GetEntry(LT_010);
+								String fileName =iCommentTagStore[aCommentOfInterest].GetFileName();
+								int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+								if(message->GetActivated())
+									{
+									pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+									}							
+								}
+							else
+								{
+								CheckParametersArePermitted(aCommentOfInterest, j, definitionNumber);
+								}
+							}
+						else if(parameterType == "multiple")
+							{
+							if(numberOfArgs<1) // multiple must have at least one argument
+								{
+								Message * message = pG->Messages.GetEntry(LT_011);
+								String fileName =iCommentTagStore[aCommentOfInterest].GetFileName();
+								int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+								if(message->GetActivated())
+									{
+									pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+									}	
+								}
+							else
+								{
+								CheckParametersArePermitted(aCommentOfInterest, j, definitionNumber);
+								}
+							}
+						else if(parameterType == "text")
+							{
+							if(numberOfArgs<1) // text must have somethign after it so numberOfArgs must be >= 1
+								{
+								Message * message = pG->Messages.GetEntry(LT_012);
+								String fileName =iCommentTagStore[aCommentOfInterest].GetFileName();
+								int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(j);
+								if(message->GetActivated())
+									{
+									pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+									}	
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	CheckWhetherAllCommentsPresent(aRlsTypeName, aCommentOfInterest, commentsSeen);
+	}
+
+void GlobalLocalisationData::CheckWhetherAllCommentsPresent(String aRlsTypeName, int aCommentOfInterest, std::vector<String> aCommentsSeen)
+	{
+	for(unsigned int j=0; j<iCommentDefinitions.size(); j++)
+		{
+		bool commentAlreadyUsed = false;
+		for(unsigned int k=0; k<aCommentsSeen.size() && commentAlreadyUsed == false;k++)
+			{
+			String storedCommandName = iCommentDefinitions[j].GetCommandName();
+			String extractedCommandName = aCommentsSeen[k].ExtractSubString(1,aCommentsSeen[k].Length()-1);
+			if(storedCommandName == extractedCommandName)
+				{
+				//this command already used in the comment tag
+				commentAlreadyUsed = true;
+				}
+			}
+		if(commentAlreadyUsed == false) // if tag wasn't present in the localisation comment
+			{
+			int requirementStatus = iCommentDefinitions[j].GetRequirementStatus(aRlsTypeName);
+			if(iCommentDefinitions[j].GetRequirementStatus(aRlsTypeName) == ERequired) // if required emit warning
+				{
+				Message * message = pG->Messages.GetEntry(LT_013);
+				String fileName = iCommentTagStore[aCommentOfInterest].GetFileName();
+				int lineNumber = iCommentTagStore[aCommentOfInterest].GetLastLineOfComment() + 1;
+				if(message->GetActivated())
+					{
+					String comment = message->GetMessageOutput();
+					comment += iCommentDefinitions[j].GetCommandName();
+					pGL->AddWarningToStore(fileName, lineNumber, comment);
+					}
+				}
+			else if(requirementStatus == EOptionalWithDefault) // if optional check for default and add to file if default exists
+				{
+				String dataToAdd = iCommentDefinitions[j].CheckIfOptionalAndHasDefault(aRlsTypeName);
+				if(dataToAdd != "")
+					{
+					iCommentTagStore[aCommentOfInterest].AddOptionalData(dataToAdd);
+					}
+				}
+			}
+		}
+	}
+
+void GlobalLocalisationData::CheckParametersArePermitted(int aCommentOfInterest, int aLineInComment, int aDefinitionNumber)
+	{
+	unsigned int elementsInLine = iCommentTagStore[aCommentOfInterest].GetNumberOfTokensInLine(aLineInComment);
+	for(unsigned int j=1; j< elementsInLine;j++)
+		{ // start iterating at 1 as 0th element is tag name
+		bool parameterPermitted = false;
+		unsigned int permissibleParameters = iCommentDefinitions[aDefinitionNumber].GetNumberOfPermissibleParameters();
+		for(unsigned int k=0; k<permissibleParameters && parameterPermitted==false;k++)
+			{
+			if(iCommentTagStore[aCommentOfInterest].GetElementFromLine(aLineInComment,j)== iCommentDefinitions[aDefinitionNumber].GetPermissibleParameter(k))
+				{
+				parameterPermitted = true;
+				}
+			}
+		if(parameterPermitted == false)
+			{
+			Message * message = pG->Messages.GetEntry(LT_014);
+			String fileName = iCommentTagStore[aCommentOfInterest].GetFileName();
+			int lineNumber = iCommentTagStore[aCommentOfInterest].GetFirstLine(aLineInComment);
+			if(message->GetActivated())
+				{
+				pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+				}
+			return;
+			}
+		}
+	}
+
+int GlobalLocalisationData::FindIndex(const String aFileName, int aLineNumber)
+	{
+	for(unsigned int j=0;j<iCommentTagStore.size(); j++)
+		{
+		if(iCommentTagStore[j].GetFileName() == aFileName)
+			{
+			if(iCommentTagStore[j].GetLastLineOfComment() == aLineNumber - 1)
+				{
+				return j;
+				}
+			}
+		}
+	return -1; //signifies that there is no localisation comment preceding this rls line
+	}
+
+
+bool GlobalLocalisationData::CheckFirstIsCommand(LocalisationLine aCommandLine)
+	{
+	return aCommandLine.GetElement(0).FindSubString("@") == 0 ? true : false;
+	}
+
+void GlobalLocalisationData::StoreFinalComment()
+	{
+	if(iTempCommentStore.GetFirstLine() >= 0)
+		AddCommentToStore();
+	}
+
+void GlobalLocalisationData::StoreComment(String aString) 
+	{
+	iTempCommentStore.AddElement(aString);
+	}
+
+void GlobalLocalisationData::Process(unsigned int aStoreIndex, unsigned int aCurrentIndex)
+	{
+	LocalisationLine tagCommandLine(iCommentTagStore[aStoreIndex].GetLine(aCurrentIndex));
+	String firstWord = tagCommandLine.GetElement(0);
+	iCommentTagStore[aStoreIndex].SetAnalysed(aCurrentIndex, true); // will reset to false if turns out not to be a declaration
+	if(firstWord == "@declaretag") 
+		ProcessDeclaration(aStoreIndex, aCurrentIndex);
+	else if(firstWord == "@tagvalue")
+		ProcessTagParameter(aStoreIndex, aCurrentIndex);
+	else if(firstWord == "@tagoptional")
+		{
+		ProcessOptional(aStoreIndex, aCurrentIndex);
+		}
+	else if(firstWord == "@tagrequired")
+		ProcessRequired(aStoreIndex, aCurrentIndex);
+	else if(firstWord[0]=='@') // must be a tag like 'localise' or 'description'
+		{
+		iCommentTagStore[aStoreIndex].SetAnalysed(aCurrentIndex, false);
+		}
+	else // first word on a line (not wrapping over from a previous line) does not start with an @ symbol, enit warning
+		{
+		Message * message = pG->Messages.GetEntry(LT_015);
+		String fileName = tagCommandLine.GetFileName();
+		int lineNumber = tagCommandLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		}
+	}
+
+void GlobalLocalisationData::ProcessDeclaration(unsigned int aStoreIndex, unsigned int aCurrentIndex)
+	{
+	LocalisationLine tagDeclarationLine(iCommentTagStore[aStoreIndex].GetLine(aCurrentIndex));
+	if(tagDeclarationLine.GetNumberOfTokens()!=3) // tag declaration lines must have three words in them
+		{
+		Message * message = pG->Messages.GetEntry(LT_016);
+		String fileName = tagDeclarationLine.GetFileName();
+		int lineNumber = tagDeclarationLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+	String tagType = tagDeclarationLine.GetElement(1);
+	bool acceptableParameter = false; // check that tagType is one of void, single, multiple or text
+	for(int i=0; i<4 && acceptableParameter == false; i++)
+		{
+		if(tagType == iTypes[i])
+			{
+			acceptableParameter = true;
+			}
+		}
+	if(acceptableParameter == false)
+		{
+		Message * message = pG->Messages.GetEntry(LT_017);
+		String fileName = tagDeclarationLine.GetFileName();
+		int lineNumber = tagDeclarationLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+	if(tagDeclarationLine.GetElement(2).FindSubString("@")==0)
+		{
+		Message * message = pG->Messages.GetEntry(LT_018);
+		String fileName = tagDeclarationLine.GetFileName();
+		int lineNumber = tagDeclarationLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+	String tagName = tagDeclarationLine.GetElement(2);
+	CommentTagPair dataToAdd(tagName, tagType, true);
+	int entryNumber = GetTagDeclaredIndex(tagName); // check whether tag has already been declared
+	if(entryNumber == EStringNotFound) // if not then add to store
+		{
+		iCommentDefinitions.push_back( dataToAdd );
+		}
+	else if(iCommentDefinitions[entryNumber].TagDeclared()) // emit warning if declared
+		{
+		Message * message = pG->Messages.GetEntry(LT_019);
+		String fileName = tagDeclarationLine.GetFileName();
+		int lineNumber = tagDeclarationLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		}
+	else
+		iCommentDefinitions[entryNumber].SetTagDeclared(); // set tag as declared
+	}
+
+void GlobalLocalisationData::StoreTagParameter(String aCommandName, String aParameter)
+	{
+	int entryNumber = GetTagDeclaredIndex(aCommandName);
+	iCommentDefinitions[entryNumber].AddPermissibleParameter(aParameter);
+	}
+
+int GlobalLocalisationData::GetTagDeclaredIndex(String aCommandName)
+	{ // return index number of tag in iCommentDefinitions store
+	for(unsigned int j = 0; j < iCommentDefinitions.size(); j++)
+		{
+		if(iCommentDefinitions[j].GetCommandName() == aCommandName)
+			{
+			return j;
+			}
+		}
+	return -1;
+	}
+
+void GlobalLocalisationData::ProcessTagParameter(unsigned int aStoreIndex, unsigned int aCurrentIndex)
+	{
+	LocalisationLine tagParameterLine(iCommentTagStore[aStoreIndex].GetLine(aCurrentIndex));
+	if(tagParameterLine.GetNumberOfTokens()!=3)
+		{
+		Message * message = pG->Messages.GetEntry(LT_020);
+		String fileName = tagParameterLine.GetFileName();
+		int lineNumber = tagParameterLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+	String tagName = tagParameterLine.GetElement(1);
+	if(tagName.FindSubString("@") == 0)
+		{
+		Message * message = pG->Messages.GetEntry(LT_021);
+		String fileName = tagParameterLine.GetFileName();
+		int lineNumber = tagParameterLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+	int entryNumber = GetTagDeclaredIndex(tagName);
+	String parameter = tagParameterLine.GetElement(2);
+	if(entryNumber == -1) // if tag not declared then add to store, doesn't set tag as declared though as haven't seen a @declaretag line for this tag
+		{
+		CommentTagPair dataToAdd(tagName);
+		iCommentDefinitions.push_back(dataToAdd);
+		}
+	else
+		{
+		// check whether this parameter has alreasy been declared for this tag
+		bool alreadyDeclared = iCommentDefinitions[entryNumber].IsParameterAlreadyDeclared(parameter);
+		if(alreadyDeclared)
+			{
+			Message * message = pG->Messages.GetEntry(LT_022);
+			String fileName = tagParameterLine.GetFileName();
+			int lineNumber = tagParameterLine.GetFirstLine();
+			if(message->GetActivated())
+				{
+				pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+				}
+			return;
+			}
+		}
+	StoreTagParameter(tagName, parameter); // store the parameter if all conditions met
+	}
+
+void GlobalLocalisationData::ProcessRequired(unsigned int aStoreIndex, unsigned int aCurrentIndex)
+	{
+	LocalisationLine tagRequiredLine(iCommentTagStore[aStoreIndex].GetLine(aCurrentIndex));
+
+	// @tagrequired line must consist of three distinct tokens
+
+	if(tagRequiredLine.GetNumberOfTokens()!=3)
+		{
+		Message * message = pG->Messages.GetEntry(LT_023);
+		String fileName = tagRequiredLine.GetFileName();
+		int lineNumber = tagRequiredLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+
+	// get the tag name and check it doesn't start with an @ symbol
+	
+	String tagName = tagRequiredLine.GetElement(1);
+	if(tagName.FindSubString("@")==0)
+		{
+		Message * message = pG->Messages.GetEntry(LT_024);
+		String fileName = tagRequiredLine.GetFileName();
+		int lineNumber = tagRequiredLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+
+	String rlsItem = tagRequiredLine.GetElement(2);
+
+	//check that the rls type passed is one of the legally allowed values
+
+	bool validRlsFlag = false;
+	for(int j=0; (j < ENumberOfRlsTypes) && (validRlsFlag == false); j++)
+		{
+		if(rlsItem == iRlsTypes[j])
+			{
+			validRlsFlag = true;
+			}
+		}
+	if(validRlsFlag == false)
+		{
+		Message * message = pG->Messages.GetEntry(LT_036);
+		String fileName = tagRequiredLine.GetFileName();
+		int lineNumber = tagRequiredLine.GetFirstLine();
+		if(message->GetActivated())
+			{
+			String comment = message->GetMessageOutput();
+			comment += rlsItem;
+			pGL->AddWarningToStore(fileName, lineNumber, comment);
+			}
+		return;
+		}
+	
+
+	// store the data
+
+	int entryNumber = GetTagDeclaredIndex(tagName);
+	if(entryNumber == -1)
+		{
+		CommentTagPair dataToAdd(tagName);
+		iCommentDefinitions.push_back(dataToAdd);
+		}
+	else
+		{
+		int requirementStatus = iCommentDefinitions[entryNumber].GetRequirementStatus(rlsItem);
+		if(requirementStatus != EForbidden)
+			{
+			Message * message = pG->Messages.GetEntry(LT_025);
+			String fileName = tagRequiredLine.GetFileName();
+			int lineNumber = tagRequiredLine.GetFirstLine();
+			if(message->GetActivated())
+				{
+				pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+				}
+			return;
+			}
+		}
+	StoreRlsItem(tagName, tagRequiredLine.GetElement(2), ERequired);
+	}
+
+void GlobalLocalisationData::StoreRlsItem(String aCommandName, String aRlsItem, int aRequired, String aDefault)
+	{
+	int entryNumber = GetTagDeclaredIndex(aCommandName);
+	iCommentDefinitions[entryNumber].AddRlsItem(aRlsItem,aRequired,aDefault);
+	}
+
+bool GlobalLocalisationData::IsAnRlsItem(String aString) const
+	{
+	//check whether aString is one of the legally allowed rls items
+
+	for(int j=0; j < ENumberOfRlsTypes ; j++)
+		{
+		if(aString == iRlsTypes[j])
+			{
+			return true;
+			}
+		}
+	return false;
+	}
+
+void GlobalLocalisationData::ProcessOptional(unsigned int aStoreIndex, unsigned int aCurrentIndex)
+	{
+	LocalisationLine tagOptionalLine(iCommentTagStore[aStoreIndex].GetLine(aCurrentIndex));
+	int tagLineSize = tagOptionalLine.GetNumberOfTokens();
+	
+	String fileName = tagOptionalLine.GetFileName();
+	int lineNumber = tagOptionalLine.GetFirstLine();
+	String comment;
+	
+	String commandName;
+	String defaultValue;
+	String rlsItem;
+	bool validOptionalDeclaration = false; // will be set to true if the line conforms to the accepted syntax
+
+	unsigned int state = ELookingForCommand;
+	int firstOccurance;
+	String currentToken;
+
+	for(int j=1; j<tagLineSize; j++) // start at 1 as 0th element is @tagoptional
+		{
+		currentToken = tagOptionalLine.GetElement(j);
+		switch(state)
+			{
+			case(ELookingForCommand):
+				firstOccurance = currentToken.FindSubString("=");
+				if(firstOccurance == EStringNotFound)
+					{
+					if(IsAnRlsItem(currentToken))
+						{
+						Message * message = pG->Messages.GetEntry(LT_038);
+						if(message->GetActivated())
+							{
+							pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+							}
+						return;
+						}
+					else
+						{
+						commandName = currentToken;
+						state = ELookingForEqualSignOrRlsItem;
+						}
+					}
+				else if(firstOccurance == 0) // = sign is at the start
+					{
+					Message * message = pG->Messages.GetEntry(LT_039);
+					if(message->GetActivated())
+						{
+						pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+						}
+					return;
+					}
+				else if(currentToken.FindSubString("=",firstOccurance+1)!=EStringNotFound) // more than one = sign
+					{
+					Message * message = pG->Messages.GetEntry(LT_027);
+					if(message->GetActivated())
+						{
+						pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+						}
+					return;
+					}
+				else if((unsigned int)firstOccurance == currentToken.Length() - 1) // = sign at end
+					{
+					commandName = currentToken.ExtractSubString( 0, currentToken.Length()-2 );
+					state = ELookingForDefault;
+					}
+				else // know that is of from <string1>=<string2>
+					{
+					commandName = currentToken.ExtractSubString( 0, firstOccurance - 1 );
+					defaultValue = currentToken.ExtractSubString( firstOccurance + 1, currentToken.Length()-1 );
+					if(IsAnRlsItem(commandName))
+						{
+						Message * message = pG->Messages.GetEntry(LT_040);
+						if(message->GetActivated())
+							{
+							pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+							}
+						return;
+						}
+					else if(IsAnRlsItem(defaultValue))
+						{
+						Message * message = pG->Messages.GetEntry(LT_041);
+						if(message->GetActivated())
+							{
+							pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+							}
+						return;
+						}
+					else // no problems so go and look next for an rls item
+						{
+						state = ELookingForRlsItem;
+						}
+					}
+				break;
+			case(ELookingForEqualSignOrRlsItem):
+				firstOccurance = currentToken.FindSubString("=");
+				if(firstOccurance == EStringNotFound) // element must be rls item or error
+					{
+					if(IsAnRlsItem(currentToken))
+						{
+						rlsItem = currentToken;
+						state = EShouldBeFinished;
+						validOptionalDeclaration = true;
+						}
+					else // not an rls item
+						{
+						Message * message = pG->Messages.GetEntry(LT_035);
+						if(message->GetActivated())
+							{
+							String comment = message->GetMessageOutput();
+							comment += currentToken;
+							pGL->AddWarningToStore(fileName, lineNumber, comment);
+							}
+						return;
+						}
+					}
+				else if(currentToken.FindSubString("=",firstOccurance+1)!=EStringNotFound) // more than one = sign
+					{
+					Message * message = pG->Messages.GetEntry(LT_027);
+					if(message->GetActivated())
+						{
+						pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+						}
+					return;
+					}
+				else if(firstOccurance != 0) // = sign not at start
+					{
+					Message * message = pG->Messages.GetEntry(LT_042);
+					if(message->GetActivated())
+						{
+						pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+						}
+					return;
+					}
+				else if(currentToken.Length() == 1) // = sign by itself
+					{
+					state = ELookingForDefault;
+					}
+				else
+					{
+					defaultValue = currentToken.ExtractSubString( 1, currentToken.Length()-1 );
+					if(IsAnRlsItem(defaultValue)) // if found rls item where default value should be
+						{
+						Message * message = pG->Messages.GetEntry(LT_041);
+						if(message->GetActivated())
+							{
+							pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+							}
+						return;
+						}
+					else
+						{
+						state = ELookingForRlsItem;
+						}
+					}
+				break;
+			case(ELookingForDefault):
+				firstOccurance = currentToken.FindSubString("=");
+				if(firstOccurance != EStringNotFound) // should not find any more equal signs on the line
+					{
+					Message * message = pG->Messages.GetEntry(LT_027);
+					if(message->GetActivated())
+						{
+						pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+						}
+					return;
+					}
+				else
+					{
+					defaultValue = currentToken;
+					if(IsAnRlsItem(defaultValue)) //check that default value is not an rls item
+						{
+						Message * message = pG->Messages.GetEntry(LT_041);
+						if(message->GetActivated())
+							{
+							pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+							}
+						return;
+						}
+					else
+						{
+						state = ELookingForRlsItem;
+						}
+					}
+				break;
+			case(ELookingForRlsItem):
+				rlsItem = currentToken;
+				if(IsAnRlsItem(rlsItem) == false)
+					{
+					Message * message = pG->Messages.GetEntry(LT_035);
+					if(message->GetActivated())
+						{
+						String comment = message->GetMessageOutput();
+						comment += rlsItem;
+						pGL->AddWarningToStore(fileName, lineNumber, comment);
+						}
+					return;
+					}
+				else
+					{
+					state = EShouldBeFinished;
+					validOptionalDeclaration = true;
+					}
+				break;
+			case(EShouldBeFinished):
+				Message * message = pG->Messages.GetEntry(LT_043);
+				if(message->GetActivated())
+					{
+					String comment = message->GetMessageOutput();
+					comment += currentToken;
+					pGL->AddWarningToStore(fileName, lineNumber, comment);
+					}
+				return;
+			}
+		}
+
+	if(validOptionalDeclaration == false) // end of line reached prematurely
+		{
+		Message * message = pG->Messages.GetEntry(LT_044);
+		if(message->GetActivated())
+			{
+			pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+			}
+		return;
+		}
+
+
+	int entryNumber = GetTagDeclaredIndex(commandName);
+	if(entryNumber == -1)
+		{
+		CommentTagPair dataToAdd(commandName);
+		iCommentDefinitions.push_back(dataToAdd);
+		}
+	else
+		{
+		int requirementStatus = iCommentDefinitions[entryNumber].GetRequirementStatus(rlsItem);
+		if(requirementStatus != EForbidden)
+			{
+			Message * message = pG->Messages.GetEntry(LT_025);
+			if(message->GetActivated())
+				{
+				pGL->AddWarningToStore(fileName, lineNumber, message->GetMessageOutput());
+				}
+			return;
+			}
+		}
+	
+	if(defaultValue.Length())
+		StoreRlsItem(commandName, rlsItem, EOptionalWithDefault, defaultValue);
+	else
+		StoreRlsItem(commandName, rlsItem, EOptional);
+	}
+			
+
+void GlobalLocalisationData::AddWarningToStore(const String aFileName, int aLineNumber, String aComment)
+	{
+	WarningToOutput warning(aFileName, aLineNumber, aComment);
+	iWarningStore.push_back(warning);
+	}
+
+void GlobalLocalisationData::PrintLocalisationWarnings()
+	{
+	std::vector<WarningToOutput> warningStore;
+	unsigned int j;
+	unsigned int numberOfWarnings = iWarningStore.size();
+	std::vector<int> flags;
+	for(j=0 ; j<numberOfWarnings; j++)
+		{
+		warningStore.push_back(iWarningStore[j]);
+		flags.push_back(1);
+		}
+
+	iWarningStore.clear();
+	StringLess stringCompare;
+	int currentBestIndex;
+	int totalLeft = numberOfWarnings;
+	while(totalLeft) // loop orders stored warnings alphabetically by file name and then by line number
+		{
+		String fileName;
+		int lineNumber = -1;
+		String comment;
+		String currentBestFileName;
+		int currentBestLineNumber = -1;
+		String currentBestComment;
+		bool beforeFirst = true;
+		for(j=0,totalLeft=0,currentBestIndex=-1; j< numberOfWarnings; j++)
+			{
+			if(flags[j])
+				{
+				if(beforeFirst)
+					{
+					currentBestFileName = warningStore[j].GetFileName();
+					currentBestLineNumber = warningStore[j].GetLineNumber();
+					currentBestComment = warningStore[j].GetComment();
+					currentBestIndex = j;
+					beforeFirst = false;
+					}
+				else 
+					{
+					fileName = warningStore[j].GetFileName();
+					lineNumber = warningStore[j].GetLineNumber();
+					comment = warningStore[j].GetComment();
+					if(!stringCompare(fileName, currentBestFileName) && !stringCompare(currentBestFileName, fileName))
+						{
+						if(lineNumber < currentBestLineNumber)
+							{
+							currentBestLineNumber = lineNumber;
+							currentBestComment = comment;
+							currentBestIndex = j;
+							}
+						}
+					else if(stringCompare(fileName, currentBestFileName))
+						{
+						currentBestFileName = fileName;
+						currentBestLineNumber = lineNumber;
+						currentBestComment = comment;
+						currentBestIndex = j;
+						}
+					}
+				totalLeft++;
+				}
+			}
+		if(currentBestIndex>=0)
+			{
+			flags[currentBestIndex]=0;
+			WarningToOutput warning(warningStore[currentBestIndex]);
+			iWarningStore.push_back(warning);
+			totalLeft--;
+			}
+		}
+	for(j=0; j< numberOfWarnings; j++) // outputs warning in alphabetical file order, by line number within a file
+		{
+		String fileName = iWarningStore[j].GetFileName();
+		ErrorHandler::Register(& fileName, iWarningStore[j].GetLineNumber());
+		ErrorHandler::OutputErrorLine(iWarningStore[j].GetComment());
+		}
+	}
+
+void GlobalLocalisationData::OutputLocalisedFile(String SourceFileName)
+	{ // reparse the source file and output a file with the optional tags with defaults added in
+
+	char fileChar;
+	char * fileCharAsArray = new char[2];
+	fileCharAsArray[0] = 'a';
+	fileCharAsArray[1]='\0';
+	const char * fileName = SourceFileName.GetAssertedNonEmptyBuffer();
+	ifstream iFile(fileName);
+
+	char * LocalisationOutputFileName;
+	LocalisationOutputFileName = tmpnam(NULL);
+	ofstream outputFile(LocalisationOutputFileName);
+
+	String fileLine("");
+	int fileLineLength = fileLine.Length();
+	int previousState;
+	int state = EStartOfLine;
+	int currentFileLine = 1;
+	String currentFileName = SourceFileName;
+	int newLineNumber = -1;
+	String newFileName("");
+	String newLineNumberAsString("");
+	bool validLine = false;
+	while(iFile.get(fileChar)) // read file character by character looking for file declaration lines
+		{
+		fileCharAsArray[0]=fileChar;
+		if(state == EStartOfLine) // add character to store of this line
+			fileLine = fileCharAsArray;
+		else
+			fileLine += fileCharAsArray;
+		previousState = state;
+		switch(state)
+			{
+			case(EStartOfLine):
+				switch(fileChar)
+					{
+					case('#'):
+						state = EFindLineNo;
+						break;
+					case('\n'):
+						break;
+					default:
+						state = EGeneral;
+					}
+				break;
+			case(EGeneral):
+				switch(fileChar)
+					{
+					case('\n'):
+						state = EStartOfLine;
+						break;
+					}
+				break;
+			case(EFindLineNo):
+				switch(fileChar)
+					{
+					case('\n'):
+						state = EStartOfLine;
+						break;
+					case('0'):
+					case('1'):
+					case('2'):
+					case('3'):
+					case('4'):
+					case('5'):
+					case('6'):
+					case('7'):
+					case('8'):
+					case('9'):
+						state = EInLineNo;
+						break;
+					case(' '):
+					case('\t'):
+						break;
+					default:
+						state = EGeneral;
+					}
+				break;
+			case(EInLineNo):
+				switch(fileChar)
+					{
+					case('\n'):
+						state = EStartOfLine;
+						break;
+					case('0'):
+					case('1'):
+					case('2'):
+					case('3'):
+					case('4'):
+					case('5'):
+					case('6'):
+					case('7'):
+					case('8'):
+					case('9'):
+						break;
+					case(' '):
+					case('\t'):
+						state = EFindFileName;
+						break;
+					default:
+						state = EGeneral;
+					}
+				break;
+			case(EFindFileName):
+				switch(fileChar)
+					{
+					case('\n'):
+						state = EStartOfLine;
+						break;
+					case(' '):
+					case('\t'):
+						break;
+					case('\"'):
+						state = EInFileName;
+						break;
+					default:
+						state = EGeneral;
+					}
+				break;
+			case(EInFileName):
+				switch(fileChar)
+					{
+					case('\n'):
+						state = EStartOfLine;
+						break;
+					case(' '):
+					case('\t'):
+						state = EGeneral;
+						break;
+					case('\"'):
+						state = EFindDigit;
+						break;
+					}
+				break;
+			case(EFindDigit):
+				switch(fileChar)
+					{
+					case('\n'):
+						state = EStartOfLine;
+						break;
+					case(' '):
+					case('\t'):
+						break;
+					case('1'):
+					case('2'):
+						state = EAfterDigit;
+						break;
+					default:
+						state = EGeneral;
+					}
+				break;
+			case(EAfterDigit):
+				switch(fileChar)
+					{
+					case('\n'):
+						state = EStartOfLine;
+						break;
+					case(' '):
+					case('\t'):
+						break;
+					default:
+						state = EGeneral;
+					}
+				break;
+			}
+		int lineOfInterest;
+		switch(state)
+			{
+			case(EStartOfLine):
+				if(validLine) //validline will be true if this line is a file line declaration
+					{
+					currentFileName = newFileName;
+					currentFileLine = newLineNumber - 1;
+					}
+				validLine = false;
+				newFileName.Reset();
+				newLineNumber = -1;
+				newLineNumberAsString.Reset();
+				fileLineLength = fileLine.Length();
+				lineOfInterest = NeedToAddDefaultData(currentFileName, currentFileLine); //checks if previous line was the end of a localisation tag and whether that tag has optional data to add
+				if(lineOfInterest > -1)		// data to add									   
+					{
+					int end = fileLine.FindSubString("*/");
+					String tempString;
+					if(end)
+						{
+						tempString = fileLine.ExtractSubString(0,end-1);
+						outputFile.write(tempString.GetBuffer(),tempString.Length());
+						outputFile.write("\n",1);
+						}
+					unsigned int numberOfLinesToAdd = iCommentTagStore[lineOfInterest].GetNumberOfOptionalLinesToAdd();
+					for(unsigned int j=0; j<numberOfLinesToAdd; j++)
+						{
+						tempString = iCommentTagStore[lineOfInterest].GetOptionalLineToAdd(j);
+						const char * pTempString = tempString.GetBuffer();
+						outputFile.write(pTempString,tempString.Length()-1);
+						outputFile.write("\n",1);
+						}
+					tempString = fileLine.ExtractSubString(end, fileLine.Length()-1);
+					outputFile.write(tempString.GetBuffer(),tempString.Length());
+					}
+				else
+					outputFile.write(fileLine.GetBuffer(), fileLineLength);
+				fileLine.Reset();
+				currentFileLine++;
+				break;
+			case(EGeneral):
+				if(previousState!=EGeneral)
+					{
+					newLineNumber = -1;
+					newLineNumberAsString.Reset();
+					newFileName.Reset();
+					validLine = false;
+					}
+				break;
+			case(EInLineNo):
+				if(newLineNumberAsString.Length())
+					newLineNumberAsString+= fileCharAsArray;
+				else
+					newLineNumberAsString = fileCharAsArray;
+				break;
+			case(EFindFileName):
+				if(previousState == EInLineNo)
+					{
+					newLineNumber = newLineNumberAsString.Atoi();
+					}
+				break;
+			case(EInFileName):
+				if(previousState == EInFileName)
+					{
+					if(newFileName.Length())
+						newFileName += fileCharAsArray;
+					else
+						newFileName  = fileCharAsArray;
+					}
+				break;
+			case(EFindDigit):
+				if(previousState == EInFileName)
+					validLine = true;
+				break;
+			}
+		}
+		iFile.close();
+		outputFile.close();
+		if(remove(fileName) != 0)
+			{
+			Message * message = pG->Messages.GetEntry(LT_037);
+			if(message->GetActivated())
+				{
+				cerr << message->GetMessageOutput() << endl;
+				}			
+			}
+		else
+			{
+			rename(LocalisationOutputFileName, fileName);
+			}
+		delete []fileCharAsArray;
+	}
+
+
+#ifdef __VC32__
+#pragma warning( pop )
+#endif