srcanamdw_os/leavescan/source/leavescan.cpp
changeset 0 83f4b4db085c
child 1 d4b442d23379
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srcanamdw_os/leavescan/source/leavescan.cpp	Tue Feb 02 01:39:43 2010 +0200
@@ -0,0 +1,3343 @@
+// Copyright (c) 1997-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:
+// Limitations:
+// Leavescan will attempt to avoid comments, strings and char literals which it
+// finds within the code. It is also capable of recognising escaped quotes,
+// but complex combinations of escaping e.g. "\\\"\"\'" may fool the parser and
+// result in false positives, or cause parsing to terminate prematurely (resulting
+// in possible unreported problems.
+// Leavescan can only parse what it sees, and is therefore oblivious to any 
+// non-trivial attempt to call a leaving function (i.e. by function pointer)
+// Macros can also fool the parser (as is), but leavscan will now indicate
+// whether the leaving invocation may, in fact, be a macro.
+// Multiple files are now supported on the command-line, along with some basic
+// options such as '-v' which will dump the version. Invoking with no 
+// parameters will dump the version & help, so that automated build systems can
+// check the version and cater for enhanced behaviour.
+// Local Version:
+// $Id: leavescan2.cpp,v 1.6 2003/02/19 12:59:00 AndrewHa Exp $
+// 
+//
+
+
+#include <fstream>
+#include <iostream>
+#include <sstream>   
+#include <string>
+#include <assert.h>
+#include <list>
+
+#define FOREVER for(;;)
+
+//static const char Kversion[] = "0.06"; // Version updated 07 March 08
+static const char Kversion[] = "0.07";  // suprrot L class, fix some defects.Version updated 07/2008
+// Shorthand
+typedef unsigned int uint;
+
+// Set of match types. E_Last must be at the end of the list.
+enum TMatchTypes { 
+  E_LCleanedUp=0,
+  E_LString,
+  E_LManaged,
+  E_LData,
+  E_Ell , 
+  E_Trap, 
+  E_BlockComment, 
+  E_LineComment, 
+  E_Eleave, 
+  E_UserEleave, 
+  E_String,
+  E_Quote,
+  E_OpenBrace,
+  E_CloseBrace,
+  E_OrLeave,
+  E_Last };
+
+// Set of return values of GetFunc().
+enum TReturnTypes {
+  E_False = 0,
+  E_True,
+  E_Continue };
+  
+enum TPPState { 
+   PPSTATE_NORMAL=0,
+   PPSTATE_ESCAPED_LINE ,
+   PPSTATE_SINGLE_COMMENT,
+   PPSTATE_MUL_COMMENT,
+   PPSTATE_STRING_LITERAL,
+   PPSTATE_SHARP_COMMENT
+  };
+
+enum TClassMemberTypes { 
+    E_NA= 0, 
+    E_MemberData, 
+    E_MemberFunctionDecl, 
+    E_MemberFunctionDef, 
+    E_Enum
+    };
+
+using namespace std;
+struct ClassMeta {
+	 string className ;
+	 int startPos;
+	 int endPos;
+};
+
+class TLeaveScanModel
+{
+public:
+  bool  Scan(ifstream& aStream);
+  void  SetFileName(char* aName);
+  char* FileName();
+  int   Verbose;
+  bool OnlyPrePrecess;
+
+private:	
+  void  FileToText(ifstream& aStream, string& aText);
+  enum  TReturnTypes  GetFunc(const string& aFile, string &name, uint &start, uint &end);
+  bool  CheckFunc(const string& aFile, string& aName, uint start, uint end, bool& aIsLeaver);
+  bool  MoveToEndOfTrapHarness(const string& aStr, uint& aIndex, uint aLen);
+  void  MoveToEndOfComment(const string& aStr, uint& aIndex, uint aLen);
+  void  MoveToEndOfLine(const string& aStr, uint& aIndex, uint aLen);
+  void  MoveToEndOfString(const string& aStr, uint& aIndex, uint aLen, char aQuote);
+  uint  GetRealStartPosition(const string& aFile, uint aStart, uint aIsvalidDoublecolon);
+  void  Peek(const string aStr, uint aPos);
+  uint  SmartFind(const string& aStr, const string& aTarget, uint aStart);
+  uint  SmartFindEndOfString(const string& aStr, uint aPos, char aQuote);
+  bool  IsInCommentScopeOrKeyword(const string& aFile, string &aName, uint aStartposition, uint aStartbraceposn);
+  bool  IsFunctionNameStringNotAMacro(const string& aFile, uint aStartbraceposn, uint aTempParenPos, uint aNstart);
+  bool  IsSemiColonAndAssignmentOccurs(const string& aFile, uint aStartbraceposn, uint aTempParenPos);
+  bool  CheckValidFuncName(const string& aFile, uint aStart);
+  bool  CheckForTemplateFunc(const string& aFile, uint nstart, uint nend);
+  uint  FindFirstMatchType(uint aMatchSet[]);
+  string PreProcess(const string& aFile);
+  string CombineLine(const string& aFile);
+  list<ClassMeta> GetClass(const string& aFile);
+  int GetLeftParenthesis(const string& aText, uint pos);
+  int GetRightParenthesis(const string& aText, uint pos);
+  int GetLeftTmpltParentBack(const string& aText,uint pos);
+  int GetRightTmpltParent(const string& aText,uint pos);
+  bool IsClassKeyword(const string& aText, uint aBegin, uint aEnd);
+  int GetLeftBracket(const string& aText,uint pos);
+  int GetRightBracket(const string& aText,uint pos);
+  void CheckClass(const string& aText , const string& aClassName, uint start,uint end);
+  void CheckInClassFunc(const string& aText , const string& aClassName, const string& aFuncName, uint start,uint end);
+  bool IsLClassCtor(const string& aName);
+  bool IsInClassScope(uint pos);
+  string GetFunctNameFromFuncHead(const string& aFuncHead);
+  string GetFunctionParam(const string& aText, uint aStart);
+  string GetFunctionHead(const string& aText, uint aStart);
+  string GetErrorLineHead(const string& aText,uint aStart);
+  string GetClassName(uint aStart);
+  void  ReportErrorLineAndString(uint aStart);
+  bool  AppendCommentToErrorString(uint aEnd);
+  bool  IdentifyMacro(const string& str, const uint aPos);
+  void  Test1();
+  void  Test2L();
+  void  Test3();
+  void  Test4();
+  
+  inline bool IsNewLine(const char& aCurChar) {return ((aCurChar)=='\n'||(aCurChar)=='\r')?true:false;}
+  inline bool IsLastChar(uint aCurPos, uint aStringLength) { return ((aCurPos+1)==aStringLength)?true:false;}
+  inline bool HasEnoughChar(uint aCurPos,uint aStringLength,uint aWanted) {return (aStringLength-aCurPos-1>=aWanted)?true:false;}
+  inline string TrimString(const string& aStr)
+  {
+	string result = aStr;
+	result.erase(result.find_last_not_of(" \t\n\r")+1);
+	result.erase(0,result.find_first_not_of(" \t\n\r"));
+	return result;
+  }
+private:
+  string	iText;
+  string	iBody;
+  string	iErrorString;
+  list<ClassMeta> iClassList;
+  int	        iPositionOfError;
+  char*         iFileName;
+  
+};
+
+void pversion()
+{
+  cout << "Leavescan version: " << Kversion <<"(build time:"<<__DATE__<<" "<<__TIME__<<")\n";
+}
+
+void pusage()
+{
+  pversion();
+  cout << "syntax: \n\tleavescan [-h|-n|-v|-N] <iFilename.cpp> [<iFilename.cpp> ...]\n\n";
+  cout << "\t-h: This help.\n";
+  cout << "\t-n: Noisy output - provides diagnostics (if available).\n";
+  cout << "\t-N: Very noisy output - provides diagnostics (if available).\n";
+  cout << "\t-v: Displays version (for build & automation systems).\n";
+  cout << "\t-E: Only do pre-process\n\n";
+
+}
+
+int main(int argc, char** argv)
+{
+  int noisy = 0;
+  bool onlyPreProcess =false;
+  if (argc < 2)
+    {
+      pusage();
+      return 1;
+    }
+  
+  for (int clparam = 1; clparam < argc; clparam++)
+    {
+      if (argv[clparam][0] == '-')
+	{
+	  switch(argv[clparam][1])
+	    {
+	    case 'n':
+	      noisy = 1;
+	      break;
+	    case 'N':
+	      noisy = 2;
+	      break;
+	    case 'h':
+	      pusage();
+	      break;
+	    case 'v':
+	      pversion();
+	      break;
+	    case 'E':
+	    	{
+	    		onlyPreProcess = true;
+	    	}
+	      break;
+	    default:
+	      pusage();
+	      break;
+	    }
+	} //if
+      else
+	{
+	  // invoked once per file
+	  TLeaveScanModel model;
+	  model.SetFileName(argv[clparam]);
+	  model.Verbose = noisy;
+	  if(onlyPreProcess)
+	  {
+		  model.OnlyPrePrecess = true;
+	  }
+	  else
+	  {
+		  model.OnlyPrePrecess = false;
+	  }
+	  ifstream file(model.FileName());
+	  (void) model.Scan(file);
+	  file.close();
+	  //	  return 0;
+	}
+    }
+  return 0;
+}
+  
+void TLeaveScanModel::SetFileName(char *aName)
+{
+  iFileName = aName;
+}
+
+char* TLeaveScanModel::FileName()
+{
+  return iFileName;
+}
+
+//
+// Main processing function which converts the file to a basic::string
+// and then searches through for methods, analysing them as they are
+// located.
+bool TLeaveScanModel::Scan(ifstream& aStream)
+{
+  FileToText(aStream, iText);
+  string oldText(iText);
+  iText = PreProcess(iText);
+  if(OnlyPrePrecess)
+	  {
+	  	cout<<iText;
+	  	return false;
+	  }
+  if(!iText.length())
+    {
+      cout << "File not found or empty.\n";
+      return false;
+    }
+  
+  uint start  = 0;
+  uint end    = 0;
+  bool isLeaver;
+  enum TReturnTypes getFuncReturnTypes;
+  //init class list
+  iClassList = GetClass(iText);
+  //check function
+  while (start < iText.length())
+    {
+      string name;
+	  getFuncReturnTypes = E_Continue;
+	  while(getFuncReturnTypes == E_Continue)
+	  {
+		  getFuncReturnTypes = GetFunc(iText, name, start, end);
+	  }
+      if (!getFuncReturnTypes)
+		break;
+      
+      bool clean = CheckFunc(iText, name, start, end, isLeaver);
+      bool isLCFunc =false;
+      if(name[name.length()-1] == 'C' && name[name.length()-2] == 'L')
+      {
+    	  isLCFunc = true;
+      }
+      if (isLeaver) // was a leaving container(safe) and no leavers found
+      {
+    	  
+    	  if (clean)
+    	  {
+    		  iPositionOfError=0;
+    		  iErrorString = "Warning - " + name + " appears to contain no leavers.";
+    		  if(!IsInClassScope(start))
+			  {
+				  ReportErrorLineAndString(start);	  
+			  }
+    	  }
+    	  else if(isLCFunc)
+    	  {
+    	      
+			  uint lcleanedupPos = iErrorString.find("LCleanedup");
+			  if(lcleanedupPos!=string::npos)
+				{
+    	    	  uint callPos = iErrorString.find(" calls ");
+				  uint lcleanedupPosInFuncName = name.find("LCleanedup");
+				  if(callPos!=string::npos && lcleanedupPosInFuncName!=string::npos && lcleanedupPos<callPos)
+				  {;}
+				  else
+				  {
+					iErrorString = "LCleanedup class is used in a function suffixed LC";
+    	    		if(!IsInClassScope(start))
+					{
+						ReportErrorLineAndString(start);	  
+					}
+				  }
+				}
+    	  }
+
+    	  // any leavers info can be supressed here since container was leaver
+      }
+      else // wasn't a leaving container 
+      {
+    	  if (!clean) // was dirty, so report
+    		  if(!IsInClassScope(start))
+			  {
+				  ReportErrorLineAndString(start);	  
+			  }
+      }
+      start = end;
+    }
+  //check class 
+  list<ClassMeta>::iterator iter; 
+  for(iter=iClassList.begin();iter!=iClassList.end();iter++) 
+  { 
+	  CheckClass(iText,iter->className,iter->startPos,iter->endPos);
+  } 
+  return true;
+}
+
+//
+// Spool a file into one large basic::string
+//
+void TLeaveScanModel::FileToText(ifstream& aStream, string& aText)
+{
+  char data[1024];
+  int len;
+  do	
+    {
+      aStream.read(data,1024);
+      len = aStream.gcount();
+      aText.append(data, len);
+    }
+  while(len);
+}
+
+// To get the actual position of starting parenthesis for a function definition
+//
+uint TLeaveScanModel::GetRealStartPosition(const string& aFile,uint aStart, uint aIsvaliddoublecolon)
+{
+	uint realstartpos = 0;
+
+	// The opening parenthesis which comes fist after opening brace while moving
+ 	// in backward direction is a valid candidate for function name.
+		
+	uint firstcurlybrace = SmartFind(aFile, "{", aStart + 1 ); // advance start
+
+	if ((firstcurlybrace == string::npos) || (firstcurlybrace >= aFile.length())) 
+	{
+		return realstartpos;
+	}
+
+	// This variable will store the first paranthesis position
+	uint tempParenPos = aFile.find_last_of('(',firstcurlybrace);
+
+	if (tempParenPos == string::npos)
+	{
+		// No '(' found yet
+		return realstartpos;
+	}
+
+	if (aIsvaliddoublecolon == 1)
+	{ 
+		tempParenPos = aStart;	
+	}
+	
+	string whiteSpaceChars = " \t\n\r*&";
+	
+	// ignore all tab and spaces between function name and opening parenthesis
+	uint nend = aFile.find_last_not_of(whiteSpaceChars, --tempParenPos);
+	uint pos = aFile.find_last_of(whiteSpaceChars, nend);
+	
+	if (pos == string::npos)
+	{
+		return realstartpos;
+	}
+	else
+	{
+		return pos;
+	}
+}
+/*
+This function checks the following :
+1) Whether the name is in comment scope, name is checked for both C-style comments(or block comments) and C++-style comments(Line Comments)
+2) The function name is not a keyword having same program construct as function name(i.e. is not among 'while', 'for','if' and 'for'
+
+@internalComponent
+@released
+@param aFile -  Buffer storing the whole source file contents(input)
+@param aName -  String that is to be checked whether it lies in the scope of the comment(input)
+@param aStartposition - Starting offset of name in file.(input)
+@param aStartbraceposn - Starting offset of function block (input)
+@param true - if name is in comment scope(output)
+@param false - if name is not in comment scope
+
+
+Following patterns are handled in this function:
+-----------------------------------------------
+NOTE: in order to remove compile warning, i use "|" stand for "/" in this section of comment
+
+Pattern 1: String is in the scope of both c-style and C++-style comments
+		
+	|*
+	|| name1
+	* |
+
+	
+Pattern 2: String is in the scope of both c-style comments
+
+	|*
+		name2()
+	* |
+			
+Pattern 3: String is in comment scope and the comment scope llies in a string
+			
+	printf(" |*  * | || ")
+	
+
+Pattern 4: String is in the scope of C++-style comments but C-style comments is also available in souurce file	
+
+	|*
+
+	* |
+
+	|| function() 	
+		
+		
+
+Pattern 5: String is in the scope of C-style comments but C+++-style comments is also available in souurce file	
+		
+	|| function() 	
+	|*
+
+	* |
+
+
+Pattern 6: The string is a keyword and the program construct for the keyword is same as for the functions
+	for()
+	{ } 
+
+
+Pattern 7: Both C-style and C++-style comments are avialable in file and the way of specifying comments 
+          is complex.(i.e. it is difficult to identify whether it is a C-Style comment or C++-style comment
+	  ||*******
+	   fun() 
+	  |******
+		**** | 
+	  {}
+
+*/
+bool TLeaveScanModel::IsInCommentScopeOrKeyword(const string& aFile, string &aName, uint aStartposition,uint aStartbraceposn)
+{
+	uint blockCommentStartPosn = aFile.rfind("/*",aStartposition);  // In backward direction
+	uint lineCommentStartPosn = aFile.rfind("//",aStartposition);
+	uint blockCommentEndPosn = aFile.find("*/", aStartposition); // In forward direction
+	uint semicolon = aFile.rfind(";",aStartposition);
+	uint isvalidlocationforBlock;
+	uint isvalidlocationforLine ;
+
+	if( (0 == strcmp(aName.c_str(),"if")) || (0 == strcmp(aName.c_str(),"while")) ||
+		(0 == strcmp(aName.c_str(),"for"))|| (0 == strcmp(aName.c_str(),"switch")) ||
+		(0 == strcmp(aName.c_str(),"defined")))
+	{
+		return true;
+	}
+	// There is no comment of any type either block comment or line comment 
+	if(blockCommentStartPosn == string::npos && lineCommentStartPosn == string::npos)
+	{
+		return false;
+	}
+	// A semiclon exists and semicolon is followed by both (1) the end of block comment scope and (2) the end of line comment scope
+	else if((semicolon != string::npos)&& 
+		((semicolon > blockCommentEndPosn) && (blockCommentStartPosn < blockCommentEndPosn))  &&
+		(semicolon > lineCommentStartPosn))
+	{
+		return false;
+	}
+	else if(lineCommentStartPosn == string::npos)
+	{
+		// Valid Block comment, verify that the function name by applying smartfind
+		isvalidlocationforBlock = SmartFind(aFile, aName, blockCommentStartPosn); 
+		if( (isvalidlocationforBlock == string::npos) || // There is no occurrence of name
+			((isvalidlocationforBlock > aStartbraceposn) && (isvalidlocationforBlock != string::npos))) // The name exists but that is inside function block
+		{
+			return true; 
+		}
+		else
+		{
+			return false; 
+		}
+	}
+	else if(blockCommentStartPosn == string::npos)
+	{
+		isvalidlocationforLine = SmartFind(aFile,aName, lineCommentStartPosn); 
+		if(	(isvalidlocationforLine == string::npos) || // There is no occurrence of name
+			((isvalidlocationforLine > aStartbraceposn) && (isvalidlocationforLine != string::npos) ) ) // The name exists but that is inside function block
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+	else
+	{
+		isvalidlocationforBlock = SmartFind(aFile,aName, blockCommentStartPosn); 
+		isvalidlocationforLine = SmartFind(aFile,aName, lineCommentStartPosn);
+		if((isvalidlocationforLine == string::npos) )
+		{
+		  return true;
+		}
+		else if(( (isvalidlocationforLine > aStartbraceposn) && (isvalidlocationforLine != string::npos)) )
+		{
+		 return true; 
+		}
+		else if( (0 == isvalidlocationforBlock) || ((isvalidlocationforBlock > aStartbraceposn) && (isvalidlocationforBlock != string::npos)) )
+		{
+		 return true; 
+		}
+		else if(( blockCommentStartPosn <  aStartbraceposn) && (blockCommentEndPosn < aStartbraceposn ) && (blockCommentStartPosn < blockCommentEndPosn) && ((isvalidlocationforBlock == string::npos)))
+		{
+			return true; 
+		}
+		else
+		{
+			return false; 
+		}
+	}
+}
+
+/*
+This function checks whether the function name is a macro or not
+
+@internalComponent
+@released
+@param aFile - Buffer storing the whole source file contents
+@param aStartbraceposn - Starting offset of function block (input)
+@param aParenPos - End position of function signature
+@param aStartposnofname - Starting offset of string that is to be considered as a function name
+@param true - If function name is not a macro
+@param false - If function name is a macro  
+
+Following patterns are handled in this function:
+-----------------------------------------------
+
+Pattern 1: Function is invoked in macro
+
+	#if defined macro()
+	#endif
+	struct s1
+	{
+
+	}
+
+Pattern 2: Function is invoked in macro but the macro itself is in comment scope
+	void fun()
+	// #if macro()
+	// #endif
+	{
+		struct s1
+		{
+		
+		}
+	}
+  
+Pattern 3: There is parameterized Constructor e.g.
+
+	Foobar(CFileMan* aFileMan) : iFileMan(aFileMan), iCurrentStep(0) {}
+
+
+Pattern 4: Function is defined on the preprocessor statement e.g 
+
+	#define __KTRACE_ALL(a,p) {if((DEBUGMASK&(a))==(a))p;}
+
+Pattern 5: All the functions name in comment scope will be ignored
+
+   void func() 
+	//	#if comments() 
+	{
+	 
+	}
+
+Pattern 6: All the functions name (e.g. comments) in comment scope will be ignored
+  
+   #if defined()
+   // comments() 
+   struct{
+ 	}
+
+*/
+
+bool TLeaveScanModel::IsFunctionNameStringNotAMacro(const string& aFile, uint aStartbraceposn, uint aParenPos, uint aStartposnofname)
+{
+	uint startofword = 0;
+	uint endofword = 0;
+	uint tempParenPos = 0;
+	bool posn = true;
+	string whiteSpaceChars = " \t\n\r";
+	uint tempColonPosn = SmartFind(aFile,":",aParenPos); 
+	string  colonString(":");
+	bool isColonInCommentScope = IsInCommentScopeOrKeyword(aFile,colonString,aParenPos,aStartbraceposn);
+	if(	(tempColonPosn != string::npos)      &&
+		(false == isColonInCommentScope)     &&
+		(tempColonPosn < aStartbraceposn) )
+	{
+		return true; // Not a macro
+	}
+	// The function ignores all the strings which are in the scope of block comments.
+	while( startofword < aStartbraceposn && endofword < aStartbraceposn && posn == true)
+	{
+		if(tempParenPos == 0)
+		{
+			tempParenPos = aParenPos; // First word
+		}
+		else
+		{
+			tempParenPos = endofword; // Next word
+		}
+		startofword = aFile.find_first_not_of(whiteSpaceChars, tempParenPos+1);
+		if(startofword != aStartbraceposn) // No string between function signature and function start block
+		{
+			// get the posn of word end boundary
+			endofword = aFile.find_first_of(whiteSpaceChars, startofword);
+			string tmpString = aFile.substr(startofword,endofword-startofword);
+			string &aName = tmpString;
+			//is throw?
+			if(0==aName.find("throw"))
+			{
+				return true;
+			}
+			if(	(0 == strcmp(aName.c_str(),"const")) ||
+				(0 == strncmp(aName.c_str(),"//",2)) ||
+				(0 == strncmp(aName.c_str(),"*/",2)) ||
+				(0 == strncmp(aName.c_str(),"/*",2)) )
+			{
+				// do nothing
+			}
+			else
+			{
+				// If string is in comment scope then it is fine i.e. the  function returns true;
+				posn = IsInCommentScopeOrKeyword(aFile,aName,startofword,aStartbraceposn);
+			}
+		}
+		else
+		{
+			//	Pattern 1: only spaces are there between ')' and '{' e.g. void fun() {}
+			posn = true;
+		}
+	}
+	if(posn == false)
+	{
+		return false;
+	}
+	uint endOfLine=aFile.rfind('\n',aStartposnofname);  // Get the new line position while backtracking 
+    uint aIndex=(endOfLine==string::npos ? 0 : endOfLine);
+	uint preprocessorDirective = aFile.rfind("#",aStartposnofname); // Get the first char of the line starting with #
+	if(preprocessorDirective != string::npos && aIndex <= preprocessorDirective)
+	{
+		return false; // // Yes, the first char is #, so the name on this line can not be a valid function name
+	}
+	// Check whether it is a macro 
+	return true;
+}
+
+
+
+/*
+This function checks whether any semocolon (';') or assignment(=) is encountered 
+when the backtracking is done to look for function name. 
+  
+@internalComponent
+@released
+@param aFile - Buffer storing the whole source file contents
+@param aStartbraceposn - Starting offset of function block (input)
+@param aTempParenPos - End position of function signature
+@param true - if either assignment expression '=' or ':' occurs between function signature and starting curly brace of function block.
+@param false - if neither assignment expression '=' nor ':' occurs between function signature and starting curly brace of function block.
+
+
+Following patterns are handled in this function:
+-----------------------------------------------
+
+Pattern 1: The semicolon is encountered while backtracking in the search of function name
+
+	_LT();
+	struct s1
+	{
+
+	}
+
+Pattern 2: The semicolon is encountered while backtracking in the search of function name
+
+  fun();
+  a = 2;
+  struct str1
+  {
+  
+  }
+
+Pattern 3: The assignment is encountered while backtracking in the search of function name
+
+  voidmain()
+  a[2] = 
+  {
+	1,2,3
+  }
+ 
+*/
+
+bool TLeaveScanModel::IsSemiColonAndAssignmentOccurs(const string& aFile,uint aStartbraceposn ,uint aTempParenPos)
+{
+	string  semicolon(";");
+	string  assignment("=");
+	uint tempSemicolonPosn = SmartFind(aFile,semicolon,aTempParenPos-1); 
+	//uint tempAssignMentPosn = SmartFind(aFile,assignment,aTempParenPos-1); 
+	bool isSemicolonInCommentScope = IsInCommentScopeOrKeyword(aFile,semicolon,aTempParenPos,aStartbraceposn);
+	bool isAssignmentInCommentScope = IsInCommentScopeOrKeyword(aFile,assignment,aTempParenPos,aStartbraceposn);
+	if( (tempSemicolonPosn != string::npos)   &&
+		((false == isSemicolonInCommentScope) || (false == isAssignmentInCommentScope)) &&
+		(tempSemicolonPosn < aStartbraceposn) 
+	  )
+	{
+		return false;
+	}
+	return true;
+}
+
+/*
+This function checks whether the function definition is terminated by semi colon
+
+If the function definition is terminated with semicolon, then it is
+more likely to be a class/struct declaration rather than a function definition.
+
+@internalComponent
+@released
+@param aFile - Buffer storing the whole source file contents
+@param aStart - Starting offset of the function name string
+@return true -  If closing brace corresponding to function names is followed by semicolon 
+@return false - If closing brace corresponding to function names is not by semicolon
+
+Following patterns are handled in this function:
+-----------------------------------------------
+
+Pattern 1: NONSHARABLE_CLASS/NONSHARABLE_STRUCT modifier is used
+
+	NONSHARABLE_CLASS(...)
+	{
+
+	}; 
+
+Pattern 2: function definition is terminated by semicolon 
+
+	aaa(...)
+	{
+
+	} // comment
+	; 
+
+Pattern 3: Class is defined in macro
+
+	#define MACRO(arg) class name { };
+
+*/
+
+bool TLeaveScanModel::CheckValidFuncName(const string &aFile, uint aStart)
+{
+  bool returnValue=false;
+  unsigned long uiNumberOfCurlyBraces = 1;
+  unsigned int TempPosn = aStart;
+  unsigned int open_brace = 0;
+  unsigned int close_brace = 0;
+  // Continue till than at least any of open curly or close curly brace is remaining
+  while( !(open_brace == string::npos) || !(close_brace == string::npos) )
+  {
+		  open_brace = SmartFind(aFile, "{", TempPosn+1);
+		  close_brace = SmartFind(aFile, "}", TempPosn+1);
+
+		  if(open_brace < close_brace) // Handle which curly comes first
+		  {
+			  if((open_brace != string::npos)&& open_brace < aFile.size())
+			  {
+				uiNumberOfCurlyBraces++; // Update the curly counter
+				TempPosn = open_brace;   // move forward to the value from where the search of next curly to be started
+			  }
+		  }
+		  else // close brace comes first
+		  {
+			  if((close_brace != string::npos)&& close_brace < aFile.size())
+			  {
+				uiNumberOfCurlyBraces--;
+				TempPosn = close_brace; // move forward to the value from where the search of next curly to be started
+			  }
+			  if(uiNumberOfCurlyBraces == 0) // Match to the corresponding close curly
+			  {
+				break;
+			  }
+		  }
+  }
+  if(0 == uiNumberOfCurlyBraces)
+  {
+	  string whiteSpaceChars = " \t\n\r";
+	  unsigned int braceFollowsSemicolon1 = 0;
+	  unsigned int braceFollowsSemicolon2 = 0;
+
+	  braceFollowsSemicolon1 = SmartFind(aFile, ";", close_brace); // check if any semocolon exists after }
+	  braceFollowsSemicolon2 = aFile.find_first_not_of(whiteSpaceChars,close_brace+1); // Get the next character after close_brace
+
+	  if( (braceFollowsSemicolon1 == braceFollowsSemicolon2) && (braceFollowsSemicolon1 !=  string::npos) &&   (braceFollowsSemicolon2 !=  string::npos))
+	  {
+	   returnValue = true;
+	  }
+  }
+
+  return returnValue;
+}
+/*
+This function checks whether the function name is specified with template class definition
+
+@internalComponent
+@released
+@param nstart - starting offset of the function name string 
+@param nend - end offset of the function name string
+@return true -  If function name is specified with template class functtion definition
+@return false - If function name is not specified with template class functtion definition
+
+Following patterns are handled in this function:
+-----------------------------------------------
+
+Pattern 1: 
+
+  
+template <class T, class S, class L, class R>
+GLDEF_C void TestTDes<T,S,L,R>::Test1()
+{
+	T a(_TL("ABc"));
+}
+*/
+
+bool TLeaveScanModel::CheckForTemplateFunc(const string& aFile,uint nstart,uint nend)
+{
+	bool returnValue = false;
+	uint OpennAnglebracket = aFile.find_first_of("<", nstart); // advance start
+	if(nend == OpennAnglebracket ) // The first invalid char name is <
+	{
+		uint OpennParen = aFile.find_first_of("(", nstart); // advance start
+		uint CloseAnglebracket = SmartFind(aFile, ">::", nstart );
+		if( (CloseAnglebracket < OpennParen) && (CloseAnglebracket > OpennAnglebracket))
+		{
+			returnValue = true;
+		}
+	}
+	return returnValue;
+}
+
+// Seek out mathod functions and return their name and start/end bounds in the
+// string file.
+//
+enum TReturnTypes TLeaveScanModel::GetFunc(const string& aFile, string &aName, uint &start, uint &end)
+{
+  uint nstart = 0;//, cstart = 0;
+  uint initStart = start;
+  int realnstart = string::npos;
+  uint safety = 1000000;
+  string validNameChars = ":~abcdefghilkjmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
+  uint prevstart = string::npos;
+  FOREVER// do // forever 
+    {
+	if(
+		(start == string::npos) ||
+		(prevstart == start && prevstart != string::npos)
+	 )
+	{
+		return E_False;
+	}
+	prevstart = start;
+
+      if (safety-- == 0)
+	{
+	  cout << "ERROR: GetFunc context failure in " << iFileName << "\n";
+	  exit(6);
+	}
+
+	// move start along to 'real' double-colon
+	uint startColon = SmartFind(aFile, "::", start);
+	uint parenPostn = SmartFind(aFile, "(", start + 1);
+     
+	if (startColon == string::npos || startColon >= aFile.length() )
+	{
+		// Function Definition do not have any :: and function body contains
+  		nstart = start; 
+		// For 1st function, the value of start will be zero and for the
+		// second function onwards, it will start after the first function ends
+	}
+	else
+	{
+		uint Realstartpost  = GetRealStartPosition(aFile,parenPostn,0);
+		// If no real function name exists after double colon
+	//	if (Realstartpost == 0)
+	//		return E_False;
+		uint Realstartopnparen = SmartFind(aFile, "(", Realstartpost + 1); 
+
+		if(startColon < Realstartopnparen)
+		{
+			// If the double colon is used for function name then get function name which exists after ::
+			nstart = startColon;
+			//Get funcName before :: for "La :: La"
+			//step1 ':: L...'
+			uint fileLen = aFile.length();
+			int tmpnstart=nstart+2;
+			bool step1 = false;
+			while (tmpnstart<fileLen)
+			{
+				char curChar = aFile[tmpnstart];
+				if (curChar==' ' || curChar =='\n' || curChar=='\r' ||curChar=='\t')
+				{
+					tmpnstart++;
+				}
+				else if(curChar=='L')
+				{
+					step1=true;
+					break;
+				}
+				else
+				{
+					step1 = false;
+					break;
+				}
+			}
+			if(step1)
+			{
+				//step2 L...(<>)? :: L... -->skip all the blank
+				bool step2 = true;
+				tmpnstart = nstart-1;
+				while (tmpnstart>=0)
+				{
+					char curChar = aFile[tmpnstart];
+					if (curChar==' ' || curChar =='\n' || curChar=='\r' ||curChar=='\t')
+					{
+						tmpnstart--;
+					}
+					else
+					{
+						break;
+					}
+				}
+				if(tmpnstart<=0)
+				{
+					tmpnstart = 0;
+					step2 = false;
+				}
+				else
+				{
+					char curChar = aFile[tmpnstart];
+					if (curChar=='>')
+					{
+						tmpnstart = GetLeftTmpltParentBack(aFile,tmpnstart-1);
+						if(tmpnstart==string::npos)
+						{
+							//bad pattern
+							step2 =false;
+						}
+						else
+						{
+							tmpnstart --;
+						}
+					}
+					if(tmpnstart==string::npos)
+					{
+						//bad pattern
+						step2 =false;
+					}
+					else
+					{
+						
+						while (tmpnstart>=0)
+						{
+							curChar = aFile[tmpnstart];
+							if (curChar==' ' || curChar =='\n' || curChar=='\r' ||curChar=='\t')
+							{
+								tmpnstart--;
+							}
+							else
+							{
+								break;
+							}
+						}
+						if(tmpnstart <=0) 
+						{
+							tmpnstart=0;
+							step2=false;
+						}
+						while (tmpnstart>=0)
+						{
+							curChar = aFile[tmpnstart];
+							if (curChar=='_' || (curChar>='a' && curChar<='z') || (curChar>='A' && curChar<='Z') ||(curChar>='0' && curChar<='9'))
+							{
+								tmpnstart--;
+							}
+							else
+							{
+								break;
+							}
+						}
+						tmpnstart++;
+						if (tmpnstart<0)
+						{
+							tmpnstart=0;
+							step2=false;
+						}
+						if ( step2 && aFile[tmpnstart]=='L')
+						{
+							realnstart = tmpnstart;
+						}
+					}
+
+				}
+			}
+		}
+		else
+		{
+			// start looking for function name after '('
+			nstart = aFile.find_last_of(validNameChars,parenPostn-1);
+			if(nstart == string::npos)
+				return E_False;
+		}
+	}
+    
+	uint semiPos = SmartFind(aFile, ";", nstart + 1); 
+
+	if (semiPos == string::npos || semiPos >= aFile.length())
+		return E_False;
+
+	uint parenPos = SmartFind(aFile, "(", nstart + 1);
+    if (parenPos == string::npos || parenPos >= aFile.length()) 
+		return E_False;
+
+	start = SmartFind(aFile, "{", nstart + 1); // advance start
+	if (start == string::npos || start >= aFile.length())
+		return E_False;
+
+	uint nstart2 = SmartFind(aFile, "::", nstart + 1); // next fn
+	// Either (1) Second instance of Double collon is not there and first occurrence of double colon is valid
+	// or (2) second occurrence of double colon is inside the function and first occurrence of double colon is valid
+	
+	if((nstart2 == string::npos && startColon < parenPos && startColon < start)  || ( nstart2 > start && startColon < parenPos && startColon < start ))
+	{
+		// This variable will store the first paranthesis position in a temporary variable
+		// uint TempparenPos = parenPos;
+		uint Realstartpost  = GetRealStartPosition(aFile,parenPos,1 /*To indicate that a valid double colon exists*/);
+	
+		nstart = Realstartpost+1; // reset
+		
+		break;
+	}
+	// Either Second occurrence of Double-colon is invalid  
+	// or Second occurrence of Double-colon exists inside the function 
+	// while first occurrence of double colon is valid
+	else if (nstart2 == string::npos || nstart2 >= aFile.length() || (nstart2 != string::npos && nstart2 > start && startColon < parenPos && startColon < start))
+	{
+		// The opening parenthesis which comes fist after opening brace while moving
+ 		// in backward direction is a valid candidate for function name.
+		
+		// This variable will store the first paranthesis position
+		uint tempParenPos = aFile.find_last_of('(',start);
+		
+		
+		//void foo() throw () {;}
+		if(tempParenPos != string::npos)
+		{
+ 			uint throwPos = aFile.find("throw",initStart);
+			if(throwPos!=string::npos && throwPos>=initStart && throwPos<start)
+			{
+					tempParenPos = aFile.find_last_of('(',throwPos);
+					if(tempParenPos==string::npos || tempParenPos<initStart)
+					{
+						tempParenPos = aFile.find_last_of('(',throwPos);
+					}
+			}
+		}
+
+		if (tempParenPos == string::npos)
+		{
+			//FIX this pattern
+			//class A{};
+			//void foo(){fooL();}
+			if(start!=string::npos && semiPos!=string::npos && parenPos!=string::npos&&start<semiPos&&semiPos<parenPos)
+			{
+				start=semiPos+1;
+				return E_Continue;
+			}
+			//FIX this pattern
+			//class B;
+			//class B{};
+			//void foo(){fooL();}
+			else if(start!=string::npos && semiPos!=string::npos && parenPos!=string::npos&&start<parenPos&&semiPos<start)
+			{
+				int tmpRightBracket = GetRightBracket(aFile,start+1);
+				int tmpNextLeftBracket = GetLeftBracket(aFile,tmpRightBracket);
+				int tmpSemiPos = aFile.find(";",tmpRightBracket);
+				if(tmpRightBracket!=string::npos&&tmpNextLeftBracket!=string::npos&&tmpSemiPos!=string::npos)
+				{
+					if(tmpRightBracket<tmpSemiPos && tmpSemiPos<tmpNextLeftBracket)
+					{
+						//skip the content before B{};
+						start = tmpSemiPos;
+						return E_Continue;
+					}
+				}
+			}
+			//pattern:
+			//class temp
+			//{
+			//LData func();
+			//};
+			//LData func() 
+			//{
+			//	foo();
+			//}
+			if(start!=string::npos && semiPos!=string::npos && parenPos!=string::npos&&start<semiPos&&semiPos>parenPos)
+			{
+				int tmpRightBracket = GetRightBracket(aFile,semiPos);
+				if(tmpRightBracket!=string::npos)
+				{
+					start = tmpRightBracket;
+					return E_Continue;
+				}
+			}
+			
+			// No '(' found yet
+			return E_False;
+		}
+		
+
+		string whiteSpaceChars = " \t\n\r*&";
+
+		// ignore all tab and spaces and pointer between function name and opening parenthesis
+		uint nend = aFile.find_last_not_of(whiteSpaceChars, --tempParenPos);
+		uint currPos = aFile.find_last_of(whiteSpaceChars, nend);
+	
+		uint startOfBlock = SmartFind(aFile, "{", tempParenPos ); // advance start
+
+		if (startOfBlock == string::npos || startOfBlock >= aFile.length())
+ 			return E_False;
+
+		if (start < tempParenPos || nstart2 < tempParenPos)
+		{
+			start = startOfBlock;
+		}
+
+	 	if ((currPos != string::npos) && (currPos <  tempParenPos)) // fn1 before fn2
+			nstart = currPos+1; // reset
+	 	break;
+	}
+
+	if (semiPos < start) // semi came before brace = prototype
+		start = semiPos; 
+	else
+	if (nstart < nstart2 // fn1 before fn2
+	    && nstart2 < parenPos) // fn2 before paren 
+		start = nstart2; // reset
+	else
+		break;
+  } //while (true);
+  
+  // nstart should be left pointing to first of double colons
+  // start should point to curly brace
+
+  assert(aFile[start] == '{');
+  
+  // locate the end of the method name
+  nstart = aFile.find_first_of(validNameChars,nstart);
+  if(nstart == string::npos)
+	  return E_False;
+
+  int nend = aFile.find_first_not_of(validNameChars, nstart);
+  if(true == CheckForTemplateFunc(aFile,nstart,nend))
+  {
+	nend = aFile.find_first_of("(",nstart);
+  }
+  
+  if(realnstart!=string::npos && realnstart<nstart)
+  {
+	aName = aFile.substr(realnstart, nend - realnstart);
+  }
+  else
+  {
+	aName = aFile.substr(nstart, nend - nstart);
+  }
+  //operator
+  
+  if(aName.find("operator")!=string::npos)
+  {
+	  nend = aFile.find_first_of("(",nstart);
+	  while(nend>=0)
+	  {
+		  char tmpChar = aFile[nend];
+		  if(tmpChar == ' ' || tmpChar == '\n' ||tmpChar == '\t' ||tmpChar == 'r')
+		  {
+			  nend--;
+		  }
+		  else
+		  {
+			  break;
+		  }
+	  }
+	  aName = aFile.substr(nstart, nend - nstart);
+  }
+int typeEnd = aFile.find_last_of(validNameChars,nstart-1);
+int typeStart= aFile.find_last_of(" \t\n\r*&",typeEnd)+1;
+string type=TrimString(aFile.substr(typeStart, typeEnd - typeStart+1));
+  uint closeparenposn = aFile.find_first_of(")", nstart); // advance start
+
+  if(
+	 (false == IsFunctionNameStringNotAMacro(aFile,start,closeparenposn,nstart)) ||
+	 (false == IsSemiColonAndAssignmentOccurs(aFile,start,closeparenposn))
+	)
+  {
+	
+	start = SmartFind(aFile, "}", start); 
+	return E_Continue;
+  }
+  
+  // rewind nstart until non valid char found
+  safety = 1000000;
+  while (validNameChars.find_first_of(aFile[--nstart]) != string::npos)
+    {
+      if (safety-- == 0)
+	{
+	  cout << "ERROR: GetFunc context failure in " << iFileName << "\n";
+	  exit(7);
+	}
+    }
+  
+  nstart++;   // skip forward to acceptable character
+
+  // cut name out
+  if(realnstart!=string::npos && realnstart<nstart)
+  {
+	aName = aFile.substr(realnstart, nend - realnstart);
+  }
+  else
+  {
+	aName = aFile.substr(nstart, nend - nstart);
+  }
+  
+  // truncate the name with zero
+
+  if(realnstart!=string::npos && realnstart<nstart)
+  {
+	  aName[nend-realnstart] = 0;
+  }
+  else
+  {
+	  aName[nend-nstart] = 0;
+  }
+  aName = TrimString(aName);
+  uint NameSpaceinFunctionName = SmartFind(aName, "::",0);
+  // Continue processing when Either function name is in comment scope
+  // Or close curly corresponding to function name is followed by semicolon and pattern
+  // for scope resolution operator does not exists in function name
+  if(((true == IsInCommentScopeOrKeyword(aFile,aName,nstart,start))) || 
+	  ( (string::npos == NameSpaceinFunctionName) &&  ((true == CheckValidFuncName(aFile,start))))) 
+  {
+	  // Yes it is in comment scope
+	  start = SmartFind(aFile, "}", start); 
+	  return E_Continue;
+  }
+
+  if (Verbose)
+    cout << "Processing method " << iFileName << ": " << aName << "()\n";
+  
+  end = start+1;  // start was a curly brace, so place end inside the brace
+  int braceCount = 1;   // count the one we've just stepped over & prime loop
+  //uint sanity = 0;
+  uint lpos = end;
+  uint match[E_Last];
+  uint braceDepth = 1;
+
+  // keep progressing 'end' until braces match, end finishes up at brace+1
+  while (braceCount > 0)
+    {
+      if (Verbose > 1)
+	cout << ".";
+
+      // reset all types (in case we don't use all of them)
+      int counter;
+      for (counter = E_LCleanedUp; counter < E_Last; counter++)
+	match[counter] = string::npos;
+
+      match[E_OpenBrace]    = aFile.find("{",           lpos);
+      match[E_CloseBrace]   = aFile.find("}",           lpos);
+      match[E_BlockComment] = aFile.find("/*",          lpos);
+      match[E_LineComment]  = aFile.find("//",          lpos);
+      match[E_String]       = aFile.find("\"",          lpos);
+      match[E_Quote]        = aFile.find("\'",          lpos);
+
+      // Check for at least one match-type
+      bool nothingFound = true;
+      for(counter = E_LCleanedUp; counter < E_Last; counter++)
+	{
+	  if(match[counter] != string::npos) // if found an item
+	    nothingFound = false;
+	}
+
+      if(nothingFound) 
+	{
+	  if (Verbose > 1)
+	    cout << "\n";
+	  cout << "ERROR: " << iFileName << ":" << aName << " failed brace check.\n";
+	  exit(1);
+	}
+      
+      // Find the match-type which occurs first and set
+      // lps to its position
+      uint lowestMatchType = FindFirstMatchType(match);
+      lpos                 = match[lowestMatchType];
+      
+      switch(lowestMatchType)
+	{
+	case E_BlockComment:
+	  MoveToEndOfComment(aFile, lpos, string::npos); // lpos modified
+	  break;
+
+	case E_LineComment:
+	  MoveToEndOfLine(aFile, lpos, string::npos); // lpos modified
+	  break;
+
+	case E_OpenBrace:
+	  braceCount++;
+	  if (braceCount > (int)braceDepth)
+	    braceDepth = braceCount;
+	  lpos++;
+	  break;
+	  
+	case E_CloseBrace:
+	  braceCount--;
+	  lpos++;
+	  break;
+
+	case E_String:
+	  // we're sat on a quote, so advance
+	  lpos++;
+	  //	  Peek(file,lpos);
+	  lpos = SmartFindEndOfString(aFile, lpos, '\"');
+	  if (lpos != string::npos)
+	    lpos++; // skip closing quote
+	  break;
+	  
+	case E_Quote:
+	  lpos++;
+	  lpos = SmartFindEndOfString(aFile, lpos, '\'');
+	  if (lpos != string::npos)
+	    lpos++; // skip closing quote
+	  break;
+
+	default:
+	  if (Verbose > 1)
+	    cout << "\n";
+	  cout << "ERROR: " << iFileName << ":" << aName << " bad match type.\n";
+	  exit(1);
+	} //endsw
+      
+      if (lpos == string::npos || lpos == 0 || lpos > aFile.length())
+	{
+	  if (Verbose > 1)
+	    cout << "\n";
+	  cout << "ERROR: " << iFileName << ":" << aName << " failed brace check (EOF).\n";
+	  exit(1);
+	}
+      
+    } //endwhile
+
+  // advance 'end'
+  end = lpos;
+
+  if (braceDepth > 10)
+    {
+      if (Verbose > 1)
+	cout << "\n";
+      cout << "WARNING: " << iFileName << ":" << aName << " unexpectedly large brace depth.\n";
+    }
+  return E_True;
+}
+
+// Diagnostic function for displaying the contents of a string
+// starting at 'pos'
+//
+void TLeaveScanModel::Peek(const string aStr, uint aPos)
+{
+#define PEEKBUFFSIZE 20
+  static char peekBuf[PEEKBUFFSIZE];
+  int posn = aPos;
+  int remaining = aStr.length() - posn;
+  
+  if (remaining > (PEEKBUFFSIZE - 1))
+    remaining = PEEKBUFFSIZE;
+  
+  for (int i = 0; i < remaining; i++)
+    peekBuf[i] = aStr[i+posn];
+  
+  peekBuf[remaining] = 0;
+  
+  cout << "-------- Peek -----------\n" << peekBuf << "\n";
+  cout << "-------------------------\n";
+#undef PEEKBUFFSIZE
+}
+
+// Given an array of match types, work out which one actually comes first
+// in the string. Effectively this function returns the match type with the
+// lowest 'pos' value.
+//
+uint TLeaveScanModel::FindFirstMatchType(uint aMatchSet[])
+{
+  // load indexOfLowestMatch with the item which comes first in the fn
+  int lowestMatch = 0;
+  for(int i = E_LCleanedUp; i < E_Last; i++) 
+    {
+      if((aMatchSet[lowestMatch] == string::npos) // if didn't find one
+	 ||(aMatchSet[lowestMatch] > aMatchSet[i] && aMatchSet[i] != string::npos))
+	lowestMatch = i;
+    }
+  //  cout << "Lowest match found: " << (int)lowestMatch << "\n";
+  return lowestMatch;
+}
+
+//
+// Given a string, see if it looks like a macro (e.g. is capitalised)
+//
+bool  TLeaveScanModel::IdentifyMacro(const string& str, const uint aPos)
+{
+  string validNameChars = ":~abcdefghilkjmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
+  string LowerNameChars = "abcdefghilkjmnopqrstuvwxyz";
+
+  // backwind until not valid
+  int start = str.find_last_not_of(validNameChars, aPos);
+
+  // check for any lower case between start and pos
+  int lower = str.find_first_of(LowerNameChars, start);
+
+  bool result = false;
+  if (lower < (int)aPos)
+    result = false; // lower case == not macro
+  else
+    result = true;
+  return result;
+}
+
+// Given a method function bound, search thorough it looking for what appear to be
+// leaving functions (unless it's a leaver itself).
+//
+// Returns false if error was detected signifying that caller should dump the 
+// error string.
+//
+bool TLeaveScanModel::CheckFunc(const string& aFile, string &aName, 
+				uint start, uint end, bool& aIsLeaver)
+{
+  // entry criteria: name points to the container function name (after double-colon) which
+  // is now null-terminated.
+  // end is the bound for the end of the function (closing curly brace)
+  string extraTypes="CDX";
+  // Look for container name ending in L, or LC, LD, or LX
+  bool isLCFunc =false;
+  aName = TrimString(aName);
+  
+  string className="";
+    className = GetClassName( start);
+    if(className!="")
+    {
+    	  aName = className+"::"+aName;
+    }
+	
+  if (Verbose > 1)
+    {
+      cout << "Evaluating code:\n";
+      Peek(aFile, start);
+    }
+
+  if (aName[aName.length()-1] == 'L' || 
+      (aName[aName.length()-2] == 'L' && string::npos != extraTypes.find(aName[aName.length()-1]) ) )
+    //return true; // happy - we can exit since this container is marked as a leaver
+    aIsLeaver = true; // container is marked Leaver - used to return here
+  else if(IsLClassCtor(aName))
+  {
+	  aIsLeaver = true;
+  }
+  
+  else
+    aIsLeaver = false; // container not marked Leaver
+  
+  if (aName[aName.length()-1] == 'C' && aName[aName.length()-2] == 'L' )
+  {
+	 isLCFunc =true;
+  }
+  //CheckFuncDecl
+  //CheckFuncParam
+  int classNamePos = aFile.rfind(aName, start);
+  if(classNamePos == string::npos)
+  {
+	  uint coloncolonPos =  aName.find("::");
+	  if(coloncolonPos != string::npos)
+	  {
+		  string shortFuncName = aName.substr(coloncolonPos+2);
+		  classNamePos = aFile.rfind(shortFuncName,start);
+	  }
+  }
+  string funcParam = GetFunctionParam(aFile, classNamePos-1);
+  if(funcParam != "")
+  {
+  	if(funcParam.find("LString")!=string::npos||(funcParam.find("LData")!=string::npos))
+	{
+  		if(!aIsLeaver)
+  		{
+  			cout<<GetErrorLineHead(aFile,classNamePos)<<aName + " uses LString/LData class as parameter"<<endl;	
+  		}
+	}
+  }
+  //CheckFuncHead
+  string funcHead = GetFunctionHead(aFile, classNamePos-1);
+  if(funcHead != "")
+  {
+	 if(funcHead.find("LString")!=string::npos||(funcHead.find("LData")!=string::npos))
+	 {
+	  	if(!aIsLeaver) 
+	  	{
+	  		cout<<GetErrorLineHead(aFile,classNamePos)<<aName + " returns LString/LData class"<<endl;	
+	  	}
+	 }
+  }
+  // remainder of function exists to deal with non-leaving container
+  bool ok      = true;
+  uint bodyLen = end - start;
+  iBody        = aFile.substr(start, bodyLen); // bound the string to end
+
+  uint lpos = 0; 
+  uint match[E_Last]; // create some search-result slots
+  string extraTypesAndSpace=" CDX";
+
+  bool keepProcessing = true; // keep going unless we run out of data or bail
+  uint sanity = 1000000;
+
+  while (lpos < bodyLen && keepProcessing == true) 
+    {
+      if (sanity-- == 0)
+	{
+	  cout << "\nERROR: " << iFileName << ": " << aName << " context failure.\n";
+	  exit(4);
+	}
+      if (Verbose > 1)
+	cout << "?";
+      // Scans for a whole set of items from position lpos.
+      // string::npos returned if not found
+
+      // reset all types (in case we don't use all of them)
+      int counter;
+      for (counter = E_LCleanedUp; counter < E_Last; counter++)
+	match[counter] = string::npos;
+
+      match[E_Ell]          = iBody.find("L",           lpos); 
+      match[E_Trap]         = iBody.find("TRAP",        lpos); 
+      match[E_BlockComment] = iBody.find("/*",          lpos);
+      match[E_LineComment]  = iBody.find("//",          lpos);
+      match[E_Eleave]       = iBody.find("ELeave",      lpos);
+      match[E_UserEleave]   = iBody.find("User::Leave", lpos);
+      match[E_String]       = iBody.find("\"",          lpos);
+      match[E_Quote]        = iBody.find("\'",          lpos);
+      match[E_OrLeave]		= iBody.find("OR_LEAVE",	lpos);
+      match[E_LCleanedUp]	= iBody.find("LCleanedup",	lpos);
+      match[E_LString]		= iBody.find("LString",		lpos);
+      match[E_LManaged]		= iBody.find("LManaged",	lpos);
+      match[E_LData]		= iBody.find("LData",	    lpos);
+      
+      // Check for at least one match-type
+      bool doBreak = true;
+      for(counter = E_LCleanedUp; counter < E_Last; counter++)
+	{
+	  if(match[counter] != string::npos) // if found an item
+	    doBreak = false; 
+	}
+
+      if(doBreak) 
+	break; // found nothing of interest in this method function
+      
+      // Find the match-type which occurs first and set
+      // lps to its position
+      uint lowestMatchType = FindFirstMatchType(match);
+      lpos                 = match[lowestMatchType];
+      
+      switch(lowestMatchType) // what type was it?
+	{
+	case E_BlockComment:
+	  MoveToEndOfComment(iBody, lpos, bodyLen); // lpos modified
+	  break;
+
+	case E_LineComment:
+	  MoveToEndOfLine(iBody, lpos, bodyLen); // lpos modified
+	  break;
+
+	case E_Trap:
+	  if (! MoveToEndOfTrapHarness(iBody, lpos, bodyLen)) // lpos modified
+	    {
+              iErrorString     = aName + " structure Fault-Unclosed bracket after TRAP harness.";
+              iPositionOfError = lpos;
+	      keepProcessing   = false; // bail
+	    }
+	  break;
+
+	case E_Eleave:
+	  ok               = false;
+	  iErrorString     = aName + " calls new(ELeave).";
+	  iPositionOfError = match[E_Eleave];
+	  keepProcessing   = false; // bail
+	  break;
+	case E_OrLeave:
+		ok               = false;
+		iErrorString     = aName + " calls OR_LEAVE.";
+		iPositionOfError = match[E_OrLeave];
+		keepProcessing   = false; // bail
+		break;
+	case E_LCleanedUp:
+		ok               = false;
+		iErrorString     = aName + " uses LCleanedup* class.";
+		iPositionOfError = match[E_LCleanedUp];
+		keepProcessing   = false; // bail
+		break;
+	case E_LString:
+		ok               = false;
+		iErrorString     = aName + " uses LString* class.";
+		iPositionOfError = match[E_LString];
+		keepProcessing   = false; // bail
+		break;
+	case E_LManaged:
+		ok               = false;
+		iErrorString     = aName + " uses LManaged* class.";
+		iPositionOfError = match[E_LManaged];
+		keepProcessing   = false; // bail
+		break;
+	
+	case E_LData:
+			ok               = false;
+			iErrorString     = aName + " uses LData* class.";
+			iPositionOfError = match[E_LData];
+			keepProcessing   = false; // bail
+			break;
+			
+	case E_UserEleave:
+	  ok               = false;
+	  iErrorString     = aName + " calls User::Leave() or User::LeaveIfError().";
+	  iPositionOfError = match[E_UserEleave];
+	  AppendCommentToErrorString(bodyLen);
+	  keepProcessing   = false; // bail
+	  break;
+	  
+	
+	case E_Ell:
+	  // Found an L, but is there an underbar before it, 
+	  // AND (one of 'CDX ' AND a brace OR just a brace) _L[CDX ](
+	  if ((iBody[lpos - 1] != '_') &&
+	      (((string::npos != extraTypesAndSpace.find(iBody[lpos + 1])) 
+		&& (iBody[lpos + 2] == '(')) || (iBody[lpos + 1] == '(')) ) 
+	    {
+	      if (IdentifyMacro(iBody, lpos))
+		{
+		  ok = false;
+		  iErrorString = aName + " may employ a macro.";
+		  iPositionOfError = match[E_Ell];
+		  if(!AppendCommentToErrorString(bodyLen))
+		    keepProcessing = false; // keep going if possible
+		  lpos++;
+		  break; // don't bail - false alarm
+		}
+	      else
+		{
+		  if (Verbose > 1)
+		    {
+		      cout << "Leaver found: \n";
+		      Peek(iBody, lpos);
+		    }
+		}
+	      ok = false;
+	      iErrorString = aName + " calls a function that can leave.";
+	      iPositionOfError = match[E_Ell];
+	      if(!AppendCommentToErrorString(bodyLen))
+		keepProcessing = false; // keep going if possible
+	    }
+	  lpos++; // move on over the L
+	  break;
+	  
+	case E_String:
+	  lpos++;
+	  lpos = SmartFindEndOfString(iBody, lpos, '\"');
+	  if (lpos == string::npos)
+	    keepProcessing = false;
+	  else
+	    lpos++; // skip closing quote
+	  break;
+	  
+	case E_Quote:
+	  lpos++;
+	  lpos = SmartFindEndOfString(iBody, lpos, '\'');
+	  if (lpos == string::npos)
+	    keepProcessing = false;
+	  else
+	    lpos++; // skip closing quote
+	  break;
+
+	default:
+	  cout << "\nERROR: " << iFileName << ": " << aName << " unexpected match type.\n";
+	  exit(1);
+
+	} // endsw
+	//LCleanedup and LManaged cann't be TRAPed
+	/*
+	if (match[E_LCleanedUp]==string::npos && match[E_LManaged]==string::npos)
+	{
+	}
+	if(match[E_LCleanedUp]!=string::npos && match[E_LManaged]==string::npos)
+	{
+		ok               = false;
+		iErrorString     = aName + " uses LCleanedup class.";
+		iPositionOfError = match[E_LCleanedUp];
+		keepProcessing   = false; // bail
+		break;
+	}
+	else if(match[E_LManaged]!=string::npos && match[E_LCleanedUp]==string::npos)
+	{
+		ok               = false;
+		iErrorString     = aName + " uses LManaged* class.";
+		iPositionOfError = match[E_LManaged];
+		keepProcessing   = false; // bail
+		break;
+	}
+	else if(match[E_LCleanedUp]<match[E_LManaged])
+	{
+		ok               = false;
+		iErrorString     = aName + " uses LCleanedup class.";
+		iPositionOfError = match[E_LCleanedUp];
+		keepProcessing   = false; // bail
+		break;
+	}
+	else if(match[E_LCleanedUp]>match[E_LManaged])
+	{
+		ok               = false;
+		iErrorString     = aName + " uses LManaged* class.";
+		iPositionOfError = match[E_LManaged];
+		keepProcessing   = false; // bail
+		break;
+	}
+	*/
+    //check:An LCleanedup class is used in the same function body as the Classic cleanup stack API
+    if(match[E_LCleanedUp]!=string::npos)
+      {
+    	uint newLCPos = iBody.find("NewLC");
+		uint pushLPos = string::npos; //Cleanedup::PushL()-->find Cleanedup
+		uint bodyLen = iBody.length();
+		for(uint tmpPos = 0;tmpPos<bodyLen;)
+		{
+			pushLPos = iBody.find("CleanupStack",tmpPos);
+			if (pushLPos == string::npos)
+			{
+				break;
+			}
+			if(pushLPos>0)
+			{
+				if(iBody[pushLPos-1]=='L')
+				{
+					tmpPos++;
+					pushLPos = string::npos;
+					continue;
+				}
+				else
+				{
+					break;
+				}
+			}
+			else
+			{
+				break;
+			}
+		}
+		
+		//uint new
+    	uint lcleanedUpPos = match[E_LCleanedUp];
+    	if(newLCPos!=string::npos && pushLPos!=string::npos)
+    	{
+    		if(newLCPos<pushLPos)
+    		{
+    			cout<<GetErrorLineHead(aFile,start+newLCPos)<<aName<<" uses NewLC method with LCleanedup* class.\n";
+    			break;
+    		}
+    		else
+    		{
+    			cout<<GetErrorLineHead(aFile,start+pushLPos)<<aName<<" uses classic CleanupStack method with LCleanedup* class.\n";
+    			break;
+    		}
+    	}
+    	else if(newLCPos!=string::npos)
+    	{
+    		cout<<GetErrorLineHead(aFile,start+newLCPos)<<aName<<" uses NewLC method with LCleanedup* class.\n";
+    		break;
+    	}
+    	else if(pushLPos!=string::npos)
+    	{
+    		cout<<GetErrorLineHead(aFile,start+pushLPos)<<aName<<" uses classic CleanupStack with LCleanedup* class.\n";
+    		break;
+    	}
+    	
+      }
+    } // endwhile
+  
+  if (Verbose > 1)
+    cout << "END\n";
+
+  return ok;
+}
+
+//
+// Move an index forward to the start of a close-comment
+//
+void TLeaveScanModel::MoveToEndOfComment(const string& aStr, uint& aIndex, uint aLen)
+{
+  uint endOfComment=aStr.find("*/",aIndex);
+  aIndex=(endOfComment == string::npos ? aLen : endOfComment+2);
+}
+
+//
+// Move an index forward to the EOL (\n)
+//
+void TLeaveScanModel::MoveToEndOfLine(const string& aStr, uint& aIndex, uint aLen)
+{
+  uint endOfLine=aStr.find('\n',aIndex);
+  aIndex=(endOfLine==string::npos ? aLen : endOfLine);
+}
+
+//
+// Move an index forward to a closing quote (specified by x)
+//
+void TLeaveScanModel::MoveToEndOfString(const string& aStr, uint& aIndex, uint aLen, char aQuote)
+{
+  uint endOfLine=aStr.find(aQuote,aIndex);
+  aIndex=(endOfLine==string::npos ? aLen : endOfLine);
+}
+
+//
+// Move to end of a trap harness
+//
+bool TLeaveScanModel::MoveToEndOfTrapHarness(const string& aStr, uint& aIndex, uint aLen)
+{
+  uint bracketLevel=1;
+  uint closeBracket;
+  uint openBracket=aStr.find('(',aIndex);
+  bool cleanExit=true;
+  uint newIndex;
+  for(newIndex = openBracket; bracketLevel;)
+    {
+      closeBracket=aStr.find(')',newIndex+1);
+      openBracket=aStr.find('(',newIndex+1);
+      if (openBracket<closeBracket && openBracket!=string::npos)
+	{
+	  bracketLevel++;
+	  newIndex=openBracket;
+	}
+      else if ((closeBracket<openBracket && closeBracket!=string::npos) 
+	       || (closeBracket!=string::npos && openBracket==string::npos)) 
+	{
+	  bracketLevel--;
+	  newIndex=closeBracket;
+	}
+      else //bad structure
+	{
+	  cleanExit=false;
+	  break;
+	}
+    }
+  aIndex=(cleanExit ? newIndex : aLen);
+  return cleanExit;
+}
+
+//
+// Report the current error - note works on class member iText
+//
+void TLeaveScanModel::ReportErrorLineAndString(uint aStart)
+{
+  int positionInBody=aStart+iPositionOfError;
+  int positionOfNextLine=iText.find('\n',positionInBody+1);
+  if(positionOfNextLine==string::npos)
+  positionOfNextLine=iText.length()-1; //the first char could be '\n'
+  int positionOfLine=-1;
+  int lineNum;
+  for(lineNum=0 ;positionOfLine<positionOfNextLine;lineNum++)
+    positionOfLine=iText.find('\n',positionOfLine+1);
+ 
+  cout << iFileName <<"("<< lineNum << ") : " << iErrorString << "\n";
+}
+
+//calculate filename ,fileline
+string TLeaveScanModel::GetErrorLineHead(const string& aText, uint aPos)
+{
+	int lineNum=1;
+	char curChar=0;
+	//i did not count '\r'
+	for(int curPos=0;curPos<=aPos;curPos++)
+	{
+		curChar = aText[curPos];
+		if(curChar=='\n')
+		{
+			lineNum++;
+		}
+	}
+	stringstream   sstrm;
+	sstrm<<iFileName << string("(")<<lineNum<<string(") : ");
+	return sstrm.str();
+}
+//Get a class name from class list
+//may return wrong name if there are inner classes
+string TLeaveScanModel::GetClassName(uint aStart)
+{
+	list<ClassMeta>::iterator iter; 
+	for(iter=iClassList.begin();iter!=iClassList.end();iter++) 
+	{ 
+		if(iter->startPos<=aStart && iter->endPos >= aStart)
+		{
+			return iter->className;
+		}
+	}
+	return "";
+}
+//
+// Add to the current error string - note works on class member iBody
+//
+bool TLeaveScanModel::AppendCommentToErrorString(uint aEnd)
+{
+  bool qualified = true;
+  uint commentPosition   = iBody.find("//",iPositionOfError+1);
+  uint endOfLinePosition = iBody.find('\n',iPositionOfError+1);
+  if((commentPosition < endOfLinePosition) && (commentPosition != string::npos))
+    iErrorString+=" QUALIFIED WITH-> "+iBody.substr(commentPosition,endOfLinePosition-commentPosition);
+  else if(endOfLinePosition==string::npos && commentPosition!=string::npos)
+    iErrorString+=" QUALIFIED WITH-> "+iBody.substr(commentPosition,aEnd-commentPosition);
+  else //no comment
+    {
+      iErrorString+=" UnQualified.";
+      qualified = false;
+    }
+  return qualified;
+}
+
+//
+// Find the end of a string, but cope with escaped quotes
+//
+uint TLeaveScanModel::SmartFindEndOfString(const string& aStr, uint aPos, char aQuote)
+{
+  FOREVER//while(true)
+    {
+       MoveToEndOfString(aStr, aPos, string::npos, aQuote);
+      if (aPos == string::npos) // end of fn
+	  return aPos;
+
+      if (aStr[aPos - 1] != '\\')
+	return aPos;
+
+      // looks like we have an escaped quote
+      if (aStr[aPos - 2] == '\\')
+	{ // escape was itself quoted, so string end is real
+	  return aPos;	
+	}
+      else
+	{ // quote is escaped - carry on
+	  if (Verbose > 1)
+	    cout << "\n";
+	  cout << "WARNING: " << iFileName << ": detected quoted string.\n";
+	  aPos++;
+	  continue;
+	}
+    } //while
+}
+
+//
+// Find a target string from a given start position, but ignore targets buried
+// within comments, or strings.
+//
+uint  TLeaveScanModel::SmartFind(const string& aStr, const string& aTarget, uint aStart)
+{
+  uint found,cstart;
+  FOREVER//while(1)
+    {
+      //      cout << "Searching for target from: " << aStart << "\n";
+      // record found target 
+      found = aStr.find(aTarget, aStart);
+      if (found == string::npos)
+	  return(string::npos);
+
+      // cout << "Target candidate found at: " << found << "\n";
+      // look for earlier comment
+      cstart = aStr.find("//", aStart);
+
+      if (cstart < found) // earlier
+	{
+	  aStart = cstart; // reset start to after comment
+	  // cout << "Earlier comment found at: " << start << "\n";
+	  MoveToEndOfLine(aStr, aStart, string::npos);
+	  // cout << "Start advanced to: " << aStart << "\n";
+	  if (aStart == string::npos)
+	    return(aStart);
+	  else
+	    continue; // start search again
+	}
+      
+      // do the same for block comments
+      cstart = aStr.find("/*", aStart);
+      if (cstart < found)
+	{
+	  aStart = cstart;
+	  // cout << "Earlier block found at: " << aStart << "\n";
+	  MoveToEndOfComment(aStr, aStart, string::npos);
+	  // cout << "Start advanced to: " << aStart << "\n";
+	  if (aStart == string::npos)
+	    return(aStart);
+	  else
+	    continue;
+	}
+      
+      cstart = aStr.find("\"", aStart);
+
+      if (cstart < found)
+	{
+	  aStart = cstart + 1;
+	  MoveToEndOfString(aStr, aStart, string::npos, '\"');
+	  if (aStart == string::npos)
+	    return(aStart);
+	  else
+	    {
+	      aStart++;
+	      continue;
+	    }
+	}
+
+      cstart = aStr.find("\'", aStart);
+      if (cstart < found)
+	{
+	  aStart = cstart + 1;
+	  MoveToEndOfString(aStr, aStart, string::npos, '\'');
+	  if (aStart == string::npos)
+	    return(aStart);
+	  else
+	    {
+	      aStart++;
+	      continue;
+	    }
+	}
+      return(found); // quit loop
+    } // endwhile
+}
+
+
+/*
+ * Decide the "class" is keyword
+ * e.g
+ *  class -> true
+ *  Aclass ->false
+ *  classA ->false
+ */
+bool TLeaveScanModel::IsClassKeyword(const string& aText, uint aBegin, uint aEnd)
+{
+	bool tmpBefore =false;
+	bool tmpAfter =false;
+	int len = aText.size();
+	if(aBegin==0)
+	{
+		tmpBefore = true;
+	}
+	else
+	{
+		char tmpChar = aText[aBegin-1];
+		if(tmpChar==' ' || tmpChar=='\n' || tmpChar=='\r' || tmpChar=='\t' || tmpChar=='{'|| tmpChar=='}'|| tmpChar==';')
+		{
+			tmpBefore = true;
+		}
+	}
+	if(aEnd==len-1)
+	{
+		tmpAfter = true;
+	}
+	else
+	{
+		char tmpChar = aText[aEnd+1];
+		if(tmpChar==' ' || tmpChar=='\n' || tmpChar=='\r' || tmpChar=='{' || tmpChar=='('|| tmpChar==':')
+		{
+			tmpAfter = true;
+		}
+	}
+	return tmpAfter&&tmpBefore;
+}
+/**
+ * combine escaped lines to one line.
+ */
+string TLeaveScanModel::CombineLine(const string& aText)
+{
+
+	if(aText.size()<0) return string("");
+	int curPos = 0;
+	int curState = PPSTATE_NORMAL;
+	int firstPos = 0;
+	int stringSize = aText.size();
+	int newlineCount=0;
+	string newText("");
+	while(curPos< stringSize)
+	{
+		//remove "\"
+		switch(curState)
+		{
+		case PPSTATE_NORMAL:
+		{
+			char curChar=aText[curPos];
+			if(curChar=='\\')
+			{
+				// '\\\n" | "\\\r"
+				if(stringSize>(curPos+1)&&IsNewLine(aText[curPos+1]))
+				{
+					curState= PPSTATE_ESCAPED_LINE;				
+					newText.append(aText.substr(firstPos,curPos-firstPos));
+					curPos+=1;
+					newlineCount+=1;
+					
+				}
+				else if(IsLastChar(curPos,stringSize))
+				{
+					curPos++;
+					firstPos++;
+				}
+				else
+				{
+					curPos++;
+				}
+			}
+			else if(IsNewLine(curChar))
+			{
+				if (newlineCount>0)
+				{
+					newText.append(aText.substr(firstPos,curPos-firstPos));
+					while(newlineCount>= 0)
+					{
+						newText.append("\n");
+						newlineCount--;
+					}
+					newlineCount=0;
+					curPos++;
+					firstPos=curPos;
+				}
+				else
+				{
+					curPos++;
+				}
+			}
+			else
+			{
+				curPos++;
+			}
+		}
+			break;
+		case PPSTATE_ESCAPED_LINE:
+			if(stringSize-curPos>1)
+			{
+				if(
+					(aText[curPos]=='\n'&&aText[curPos+1]=='\r')
+					||
+					(aText[curPos]=='\r'&&aText[curPos+1]=='\n')
+					)
+				{
+					curPos+=2;
+					firstPos=curPos;
+					curState=PPSTATE_NORMAL;
+				}
+				else if(IsNewLine(aText[curPos]))
+				{
+					curPos+=1;
+					firstPos=curPos;
+					curState=PPSTATE_NORMAL;
+				}
+			}
+			else
+			{
+				//EOF
+				return newText;
+			}
+		
+		}
+	}
+	newText.append(aText.substr(firstPos,curPos-firstPos));
+	return newText;
+}
+
+/**
+ * C Preprocess
+ * a.remove single line comment
+ * b.remove mul-lines comment
+ * c.remove #command
+ * d.struct,NONSHARABLE_CLASS,NONSHARABLE_STRUCT --> class
+ * e.string literal -> blank string
+ */
+string TLeaveScanModel::PreProcess(const string& aText)
+{
+	string afterCombine = CombineLine(aText);
+	//cout<<"before:"<<endl<<afterCombine<<endl;
+	if(afterCombine.size()<0) return string("");
+	
+	int curPos = 0;
+	int curState = PPSTATE_NORMAL;
+	int firstPos = 0;
+	int stringSize = aText.size();
+	int newlineCount=0;
+	int blankCount=2;
+	string newText("");
+	while(curPos< stringSize)
+	{
+		switch(curState)
+		{
+			case PPSTATE_NORMAL:
+            {
+				char curChar = afterCombine[curPos];
+				if(curChar=='/')
+				{
+					if(HasEnoughChar(curPos,stringSize,1))
+					{
+						if('/'==afterCombine[curPos+1])
+						{
+							curState=PPSTATE_SINGLE_COMMENT;
+							newText.append(afterCombine.substr(firstPos,curPos-firstPos));
+							curPos+=2;
+						}
+						else if('*'==afterCombine[curPos+1])
+						{
+							curState=PPSTATE_MUL_COMMENT;
+							newText.append(afterCombine.substr(firstPos,curPos-firstPos));
+							curPos+=2;
+						}
+						else
+						{
+							curPos++;
+						}
+					}
+					else
+					{
+						curPos++;
+					}
+				}
+				else if(curChar=='"')
+				{
+					if(curPos>0&&(afterCombine[curPos-1]!='\\'&&afterCombine[curPos-1]!='\''))
+					{
+						curState=PPSTATE_STRING_LITERAL;
+						newText.append(afterCombine.substr(firstPos,curPos-firstPos+1));
+						
+					}
+					curPos+=1;
+				}
+				else if(curChar=='#')
+				{
+					//if # is the first non-blank char of line, comment this line
+					bool checkSharp=true;
+					for(int i=curPos-1;i>=0;i--)
+					{
+						char tmpChar = afterCombine[i];
+						if(tmpChar==' '||tmpChar=='\t'||tmpChar=='\f')
+						{
+							continue;
+						}
+						else if(tmpChar=='\n' || tmpChar=='\t')
+						{
+							break;
+						
+						}
+						else
+						{
+							checkSharp=false;
+							break;
+						}
+					}
+					if(checkSharp)
+					{
+						curState=PPSTATE_SHARP_COMMENT;
+						newText.append(afterCombine.substr(firstPos,curPos-firstPos));
+					}
+					curPos+=1;
+				}
+				//struct,NONSHARABLE_CLASS,NONSHARABLE_STRUCT --> class
+				else if(HasEnoughChar(curPos,stringSize,5))
+				{
+					
+					if(curChar=='s'&&afterCombine[curPos+1]=='t'&&afterCombine[curPos+2]=='r'&&afterCombine[curPos+3]=='u'&&afterCombine[curPos+4]=='c'&&afterCombine[curPos+5]=='t'&&IsClassKeyword(aText,curPos,curPos+5))
+					{
+						newText.append(afterCombine.substr(firstPos,curPos-firstPos));
+						newText.append("class ");
+						curPos+=6;
+						firstPos=curPos;
+					}
+					else if(curChar=='N'&&HasEnoughChar(curPos,stringSize,11)&&afterCombine[curPos+1]=='O'&&afterCombine[curPos+2]=='N'&&afterCombine[curPos+3]=='S'&&afterCombine[curPos+4]=='H'&&afterCombine[curPos+5]=='A'&&afterCombine[curPos+6]=='R'&&afterCombine[curPos+7]=='A'&&afterCombine[curPos+8]=='B'&&afterCombine[curPos+9]=='L'&&afterCombine[curPos+10]=='E'&&afterCombine[curPos+11]=='_')
+					{
+						if(HasEnoughChar(curPos,stringSize,5))
+						{
+							if(afterCombine[curPos+12]=='C'&&afterCombine[curPos+13]=='L'&&afterCombine[curPos+14]=='A'&&afterCombine[curPos+15]=='S'&&afterCombine[curPos+16]=='S'&&IsClassKeyword(aText,curPos,curPos+16))
+							{
+								newText.append(afterCombine.substr(firstPos,curPos-firstPos));
+								newText.append("class");
+								for(int i=0;i<12;i++)
+								{
+									newText.append(" ");
+								}
+								curPos+=17;
+								firstPos=curPos;
+								break;
+							}
+						}
+						if(HasEnoughChar(curPos,stringSize,6))
+						{
+							if(afterCombine[curPos+12]=='S'&&afterCombine[curPos+13]=='T'&&afterCombine[curPos+14]=='R'&&afterCombine[curPos+15]=='U'&&afterCombine[curPos+16]=='C'&&afterCombine[curPos+17]=='T'&&IsClassKeyword(aText,curPos,curPos+17))
+							{
+								newText.append(afterCombine.substr(firstPos,curPos-firstPos));
+								newText.append("class");
+								for(int i=0;i<13;i++)
+								{
+									newText.append(" ");
+								}
+								curPos+=18;
+								firstPos=curPos;
+								break;
+							}
+						}
+						curPos++;
+						
+					}//end of nonsharable
+					else
+					{
+						curPos++;
+					}
+				}
+				
+				else
+				{
+					curPos++;
+				}
+				break;
+            }
+			case PPSTATE_SHARP_COMMENT:
+			case PPSTATE_SINGLE_COMMENT:
+			{
+				while(curPos< stringSize)
+				{
+					if(IsNewLine(afterCombine[curPos]))
+					{
+						if(stringSize-curPos>1)
+						{
+										if(
+											(afterCombine[curPos]=='\n'&&afterCombine[curPos+1]=='\r')
+											||
+											(afterCombine[curPos]=='\r'&&afterCombine[curPos+1]=='\n')
+											)
+										{
+											curPos+=2;									
+										}
+										else 
+										{
+											curPos+=1;
+										}
+										firstPos=curPos;
+										curState=PPSTATE_NORMAL;
+										newText.append("\n");
+										break;
+						}
+						else
+						{					
+							newText.append("\n");
+							return newText;
+						}
+					}
+					else
+					{
+						curPos++;
+					}
+				}
+				firstPos=curPos;
+			
+				break;
+			}
+			case PPSTATE_MUL_COMMENT:
+			{
+				blankCount=2;
+				while(curPos< stringSize)
+				{
+					if(!HasEnoughChar(curPos,stringSize,1))
+					{
+						return newText;
+					}
+					if(afterCombine[curPos]=='*' && afterCombine[curPos+1]=='/')
+					{
+						curPos+=2;
+						firstPos=curPos;
+						curState=PPSTATE_NORMAL;
+						blankCount+=2;
+						break;
+					}
+					else if(IsNewLine(afterCombine[curPos]))
+					{
+						if(HasEnoughChar(curPos,stringSize,1))
+						{
+							if(
+									(afterCombine[curPos]=='\n'&&afterCombine[curPos+1]=='\r')
+									||
+									(afterCombine[curPos]=='\r'&&afterCombine[curPos+1]=='\n')
+								)
+							{
+										curPos+=2;				
+							}
+							else
+							{
+								curPos+=1;
+							}
+						}
+						else 
+						{
+									curPos+=1;
+						}					
+						while (blankCount-->0)
+						{
+							newText.append(" ");
+						}
+						newText.append("\n");				
+						blankCount=0;
+					}
+					else
+					{
+						curPos++;
+						blankCount++;
+					}
+				}
+				firstPos=curPos;
+				while (blankCount-->0)
+				{
+						newText.append(" ");
+				}
+				blankCount=0;
+			
+				break;
+			}
+			case PPSTATE_STRING_LITERAL:
+				blankCount=0;
+				while(curPos< stringSize)
+								{
+									
+									if((afterCombine[curPos]=='"' )&& (afterCombine[curPos-1]!='\\'))
+									{
+										curPos+=1;
+										firstPos=curPos;
+										while (blankCount-->0)
+										{
+											newText.append(" ");
+										}
+										newText.append("\"");
+										curState=PPSTATE_NORMAL;
+										break;
+									}
+									else
+									{
+										if(curPos>1 && (afterCombine[curPos]=='"' )&& (afterCombine[curPos-1]=='\\')&&(afterCombine[curPos-2]=='\\'))
+										{
+											curPos+=1;
+										    firstPos=curPos;
+											while (blankCount-->0)
+											{
+													newText.append(" ");
+											}
+											newText.append("\"");
+											curState=PPSTATE_NORMAL;
+											break;
+										}
+										else
+										{
+											curPos++;
+											blankCount++;
+										}
+									}
+								}
+				break;
+		}
+	}
+	newText.append(afterCombine.substr(firstPos,curPos-firstPos));
+	return newText;
+}
+/*
+ * Get next matched '{'
+ */
+int TLeaveScanModel::GetLeftBracket(const string& aText,uint pos)
+{
+	int len =aText.size();
+	if(pos>=len)
+	{
+		return string::npos;
+	}
+	while(pos<len)
+	{
+		if(aText[pos]=='{')
+		{
+			return pos;
+		}
+		pos++;
+	}
+	return string::npos;
+}
+/*
+ * Get next matched '}'
+ */
+int TLeaveScanModel::GetRightBracket(const string& aText,uint pos)
+{
+	int len = aText.size();
+	if(pos>=len)
+	{
+		return string::npos;
+	}
+	int parentCount = 1;
+	while(pos<len)
+		{
+			if(aText[pos]=='{')
+			{
+				parentCount++;
+			}
+			else if (aText[pos]=='}' )
+			{
+				parentCount--;
+				if(parentCount==0)
+				{
+					return pos;
+				}
+			}
+			pos++;
+		}
+		return string::npos;
+	
+}
+/*
+ Get next '('
+ */
+int TLeaveScanModel::GetLeftParenthesis(const string& aText,uint pos)
+{
+	int len =aText.size();
+	if(pos>=len)
+	{
+		return string::npos;
+	}
+	while(pos<len)
+	{
+		char curChar = aText[pos];
+		if(curChar=='(')
+		{
+			return pos;
+		}
+		pos++;
+	}
+	return string::npos;
+}
+
+/*
+ * Get next matched ')'
+ */
+int TLeaveScanModel::GetRightParenthesis(const string& aText,uint pos)
+{
+	int len = aText.size();
+		if(pos>=len)
+		{
+			return string::npos;
+		}
+	int parentCount = 1;
+	while(pos<len)
+		{
+			char curChar = aText[pos];
+			if(curChar=='(')
+			{
+				parentCount++;
+			}
+			else if (curChar==')' )
+			{
+				parentCount--;
+				if(parentCount==0)
+				{
+					return pos;
+				}
+			}
+			pos++;
+		}
+		return string::npos;
+}
+
+/*
+ Get next '<' by pair
+ */
+int TLeaveScanModel::GetLeftTmpltParentBack(const string& aText,uint pos)
+{
+	int count=1;
+	if (pos<=0)
+	{
+		return string::npos;
+	}
+	while(pos>0)
+	{
+		char curChar = aText[pos];
+		if(curChar=='<')
+		{
+			count--;
+			if (count <= 0)
+				return pos;
+		}
+		else if(curChar=='>')
+		{
+			count++;
+		}
+		pos--;
+	}
+	return string::npos;
+}
+
+/*
+ * Get next matched '>'
+ */
+int TLeaveScanModel::GetRightTmpltParent(const string& aText,uint pos)
+{
+	int len = aText.size();
+		if(pos>=len)
+		{
+			return string::npos;
+		}
+	int parentCount = 1;
+	while(pos<len)
+		{
+			char curChar = aText[pos];
+			if(curChar=='<')
+			{
+				parentCount++;
+			}
+			else if (curChar=='>' )
+			{
+				parentCount--;
+				if(parentCount==0)
+				{
+					return pos;
+				}
+			}
+			pos++;
+		}
+		return string::npos;
+}
+
+/*
+ *Get the start and end position of a class
+ */
+list<ClassMeta> TLeaveScanModel::GetClass(const string& aFile)
+{
+	int len= aFile.size();
+	int startPos=0;
+	int nextClassPos=-1;
+	list<ClassMeta> classList;
+	//struct ,NONSHARABLE_CLASS,NONSHARABLE_STRUCT should be parsed to 'class' in pp stage
+	while((nextClassPos = aFile.find("class",startPos))!=string::npos)
+	{
+		
+
+		char classSuffix = aFile[nextClassPos+5]; //the char after class
+		if(classSuffix!=' '&& classSuffix!='\n' && classSuffix!='\r' && classSuffix!='\t'&& classSuffix!=':'&&classSuffix!='{')
+		{
+			nextClassPos++;
+			startPos=nextClassPos;
+			continue;
+		}
+		/*no use*/
+		/*
+		if(nextClassPos>0)
+		{
+			char classPrfix = aFile[nextClassPos-1];
+			if (classPrfix =='_' || (classPrfix>='a' && classPrfix<='z') || (classPrfix>='A' && classPrfix<='Z') || (classPrfix>='0' && classPrfix<='9'))
+			{
+				nextClassPos++;
+				startPos=nextClassPos;
+				continue;
+			}
+		}
+		*/
+		if(nextClassPos >0 )
+		{
+			char classPrefix = aFile[nextClassPos-1];
+			if(classPrefix!=' '&& classPrefix!='\n' && classPrefix!='\r' && classPrefix!='\t'&& classPrefix!='{'&& classPrefix!='>'&& classPrefix!='}')
+			{
+				nextClassPos++;
+				startPos=nextClassPos;
+				continue;
+			}
+		}
+		
+		//pattern: template< ...class...>
+		int checkTemplate = nextClassPos-1;
+		bool isTemplateClass = false;
+		while(checkTemplate >= 0)
+		{
+			char checkTempChar = aFile[checkTemplate];
+			if(checkTempChar==' '|| checkTempChar=='\n' || checkTempChar=='\r' ||checkTempChar=='\t')
+			{
+				checkTemplate --;
+			}
+			else if(checkTempChar=='>') //template<> class
+			{
+				break;
+			}
+			else if(checkTempChar=='<')
+			{
+				isTemplateClass =true;
+				break;
+			}
+			else if(checkTempChar==',') //template<typename a, class T>
+			{
+				isTemplateClass =true;
+				break;	
+			}
+			else
+			{
+				break;
+			}
+		}
+		if(isTemplateClass)
+		{
+			startPos = nextClassPos+1;
+			continue;
+		}
+
+		int classStart = GetLeftBracket(aFile,nextClassPos);
+		if(classStart==-1)
+		{
+			break;  //there is no more class-body, so we can break dircetly
+		}
+		//skip this pattern
+		//class a;
+		uint semiPos = aFile.find(";",nextClassPos);
+		//such as this pattern: 
+		//class a;
+		//class b{};
+		if(semiPos!=string::npos&&semiPos<classStart)
+		{
+			startPos = semiPos;
+			continue;
+		}
+
+		uint classEnd = GetRightBracket(aFile,classStart+1);
+		if(classEnd == -1)
+		{
+			classEnd = len-1;
+		}
+		
+		//get class name
+		int curClassNamePos = classStart-1;
+		char curClassChar = 0;
+		//find pattern:
+		//class a:publlc b{...
+		uint colonPos = aFile.find(":",nextClassPos);
+		while(colonPos!=string::npos && colonPos<curClassNamePos)
+		{
+			if(colonPos != string::npos && colonPos < classStart)
+			{
+				uint secondColonPos = aFile.find(":",colonPos+1);
+				if(secondColonPos != string::npos && secondColonPos!=(colonPos+1))
+				{
+					curClassNamePos = colonPos-1;
+					break;
+				}
+				else if(secondColonPos == string::npos)
+				{
+					curClassNamePos = colonPos-1;
+					break;
+				}
+				//find ::
+				else
+				{
+					colonPos = aFile.find(":",colonPos+2);
+				}
+			}
+		}
+		//skip white spaces
+		while(curClassNamePos >=  nextClassPos)
+		{
+			curClassChar = aFile[curClassNamePos];
+			if(curClassChar ==' ' || curClassChar =='\t' || curClassChar =='\n' ||curClassChar=='\r' ||curClassChar==')')
+			{
+				curClassNamePos--;
+			}
+			else
+			{
+				break;
+			}
+		}
+		int classNameEnd = curClassNamePos;
+		while(curClassNamePos>=nextClassPos)
+		{
+			curClassChar = aFile[curClassNamePos];
+			if(curClassChar ==' ' || curClassChar =='\t' || curClassChar =='\n' ||curClassChar=='\r'||curClassChar==':'||curClassChar=='(')
+			{
+				break;
+			}
+			else
+			{
+				curClassNamePos--;
+			}
+		}
+		int classNameStart = curClassNamePos+1; //cur is a blank
+		string curClassName = TrimString(aFile.substr(classNameStart,classNameEnd-classNameStart+1));
+		if (curClassName == "class")
+		{
+			curClassName = "anonymous-class";
+		}
+		ClassMeta curClass;
+		curClass.startPos=classStart;
+		curClass.endPos=classEnd;
+		curClass.className = curClassName;
+		classList.push_back(curClass);
+		startPos=nextClassPos+1;
+	}
+	return classList;
+}
+
+/*
+ * parse the class and check it
+ * */
+void TLeaveScanModel::CheckClass(const string& aText ,const string& aClassName , uint start,uint end)
+{
+	start=start+1;
+	int curPos = start;
+	end=end-1;
+	if(end<=start) return;
+	//int colonCount=0;
+	int curStart= curPos;
+	int curEnd = curStart;
+	int curType = E_NA;
+	int curLine = 0; // wrong!!!
+	int len = aText.size();
+	string functionHead="";
+	string functionArgu="";
+	string functionBody="";
+	string memberDef="";
+	
+	for(curPos = start;curPos<=end;curPos++)
+	{
+		char curChar = aText[curPos];
+		switch(curChar)
+		{
+		case ':':
+			if (aText[curPos+1]==':')//  a '::'
+			{
+				//skip second :
+				curPos+=1;
+			}
+			//such as ctor_init_list
+			else if(curType == E_MemberFunctionDecl || curType==E_MemberFunctionDef)
+			{
+				//nothing
+			}
+			else //such as "public:"  ->ignore
+			{
+				curStart = curPos+1;
+			}
+			break;
+		case '{':
+			if(curType ==E_MemberFunctionDecl )
+			{
+				curType = E_MemberFunctionDef;
+			}
+			else
+			{
+				curType = E_Enum;
+			}		
+			curEnd = GetRightBracket(aText,curPos+1);
+			functionBody = aText.substr(curPos,curEnd-curPos+1);
+			//check in class function
+			if(E_MemberFunctionDef==curType)
+			{
+				CheckInClassFunc(aText,aClassName,functionHead,curPos,curEnd);
+			}
+			curPos = curEnd;
+			curStart =curPos;
+			curType = E_NA;
+			break;
+		case '(':
+			curType = E_MemberFunctionDecl;
+			curEnd = GetRightParenthesis(aText,curPos+1);		
+			functionHead = aText.substr(curStart,curPos-curStart);
+			functionArgu = aText.substr(curPos,curEnd-curPos+1);
+			curPos = curEnd;
+			curStart =curPos;
+			
+			break;
+		case ';':
+			if(curType == E_NA)
+			{
+				curType = E_MemberData;
+			}
+			//check point
+			if (curType == E_MemberData)
+			{
+				memberDef = aText.substr(curStart,curPos-curStart);
+				if(memberDef.find("LCleanedup")!=string::npos)
+				{
+					iErrorString = "class "+aClassName+" defines a data member with LCleanedup* type.\n";
+					cout<<GetErrorLineHead(aText, curPos)<<iErrorString;	
+				}
+			}
+			else if(curType == E_MemberFunctionDecl)
+			{
+				string funcName = GetFunctNameFromFuncHead(functionHead);
+				string extraTypes="CDX";
+				bool isLeaver = false;
+				if (funcName[funcName.length()-1] == 'L' || 
+				      (funcName[funcName.length()-2] == 'L' && string::npos != extraTypes.find(funcName[funcName.length()-1]) ) )
+				{
+					isLeaver = true; // container is marked Leaver - used to return here
+				}
+				else if(IsLClassCtor(aClassName+"::"+funcName))
+				{
+					isLeaver = true;
+				}
+				else
+				    isLeaver = false; // container not marked Leaver
+				  
+				
+				if(functionHead.find("LString")!=string::npos ||functionHead.find("LData")!=string::npos)
+				{
+					iErrorString = aClassName+"::"+funcName+" returns LString/LData class.\n";
+					if(!isLeaver) cout<<GetErrorLineHead(aText, curPos)<<iErrorString;
+				}
+				if(functionArgu.find("LString")!=string::npos ||functionArgu.find("LData")!=string::npos)
+				{
+					iErrorString = aClassName+"::"+funcName+"  uses LString/LData class as parameter.\n";
+					if(!isLeaver) cout<<GetErrorLineHead(aText, curPos)<<iErrorString;
+				}
+			}
+			//set up next check
+			curStart = curPos;
+			curType =E_NA;
+			break;
+		case 'c':
+			//check if 'class' and skip the inner class
+			if (HasEnoughChar(curPos,len,5))
+			{
+				if ( aText[curPos+1]=='l' && aText[curPos+2]=='a'  && aText[curPos+3]=='s'  && aText[curPos+4]=='s' )
+				{
+					char delimiter = aText[curPos+5];
+					//exclude pattern: void classa ()
+					if (!((delimiter >='0' && delimiter <='9') || (delimiter>='a' && delimiter<='z') || (delimiter>='A' && delimiter<='Z') ||(delimiter=='_')))
+					{
+						delimiter = aText[curPos-1];
+						//exclude pattern: void aclass()
+						if(curPos>0 && !((delimiter >='0' && delimiter <='9') || (delimiter>='a' && delimiter<='z') || (delimiter>='A' && delimiter<='Z') ||(delimiter=='_')))
+						{
+							//pattern: template<class T> Ltemp(T x){}
+							uint templatePos = aText.find("template",curStart);
+							if(templatePos != string::npos && templatePos < curPos)
+							{
+								continue;
+							}
+							else
+							{
+								int tmpLeft = GetLeftBracket(aText,curPos+4);
+								int tempRight = GetRightBracket(aText,tmpLeft+1);
+								curPos = tempRight;
+								curStart = curPos;
+								curType = E_NA;
+							}
+						}
+					}
+					
+				}			
+			}
+			//ignore
+			break;
+		default:
+			//curPos++;
+			break;
+		}
+		//curPos++;
+	}
+}
+/*
+ * Is a ctor of L class
+ * */
+bool TLeaveScanModel::IsLClassCtor(const string& aName)
+{
+	
+	//if(aName[0]=='L'&&aName.find("::")!=string::npos)%
+	//{
+	//	return true;
+	//}
+	uint colonPos = aName.find("::");
+	if(colonPos == string::npos)
+	{
+		return false;
+	}
+	string s1 = aName.substr(0,colonPos);
+	string s2 = aName.substr(colonPos+2);
+	s1.erase(s1.find_last_not_of(" \t\n\r")+1);
+	s1.erase(0,s1.find_first_not_of(" \t\n\r"));
+
+	s2.erase(s2.find_last_not_of(" \t\n\r")+1);
+	s2.erase(0,s2.find_first_not_of(" \t\n\r"));
+	
+
+	uint tmpltPos = s1.find('<');
+	if(tmpltPos!=string::npos)
+	{
+		s1 = s1.substr(0,tmpltPos);
+	}
+	if(s1[0]!='L')
+	{
+		return false;
+	}
+	if(s1.find(s2)!=string::npos)
+	{
+		uint s1Len = s1.length();
+		uint s2Len = s2.length();
+		//s1=LAL
+		//s2=LA
+		if(s2Len>0 && s1Len > s2Len)
+		{
+			char diffChar = s1[s2Len];
+			if( (diffChar>='a' && diffChar<='z') || (diffChar>='A' && diffChar<='Z') 
+				||(diffChar>='0' && diffChar<='9') || (diffChar=='_'))
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+	if(s2.find("operator")==0)
+	{
+		return true;
+	}
+	if(s2.find("new")==0)
+	{
+		return true;
+	}
+
+	return false;
+}
+/*
+* Is sometiing defined in class scope?
+*/
+bool TLeaveScanModel::IsInClassScope(uint pos)
+{
+	if (pos == string::npos)
+	{
+		return false;
+	}
+	list<ClassMeta>::iterator iter; 
+	for(iter=iClassList.begin();iter!=iClassList.end();iter++) 
+	{ 
+		if(iter->startPos<=pos && iter->endPos >= pos)
+		{
+			return true;
+		}
+	}
+	return false;
+
+}
+/*
+ * Try to get the function name from a function head
+ * */
+string TLeaveScanModel::GetFunctNameFromFuncHead(const string& aFuncHead)
+{
+	string funcName;
+	int len = aFuncHead.length();
+	int curPos=len-1;
+	char curChar;
+	int nameStart = -1;
+	int nameEnd;
+	//skip white spaces
+	while(curPos>=0)
+	{
+		curChar = aFuncHead[curPos];
+		if(curChar==' ' || curChar=='\t' ||curChar=='\n'||curChar=='\r')
+		{
+			curPos--;
+		}
+		else
+		{
+			break;
+		}	
+	}
+	if(curChar == '>')
+	{
+		int templateBalance = 1;
+		curPos--;
+		while(curPos>=0)
+		{
+			curChar = aFuncHead[curPos];
+			
+			if(curChar=='>')
+			{
+				templateBalance++;
+			}
+			else if(curChar =='<')
+			{
+				templateBalance--;
+			}
+			curPos--;
+			if(templateBalance==0)
+			{
+				break;
+			}
+			
+		}
+	}
+	if(curPos<=0) return "";
+	
+	nameEnd = curPos;
+	if(aFuncHead.find("operator")!=string::npos)
+	{
+		int tmpNameStart = aFuncHead.find("operator");
+		char delimiter = aFuncHead[tmpNameStart+8];
+		if (!((delimiter >='0' && delimiter <='9') || (delimiter>='a' && delimiter<='z') || (delimiter>='A' && delimiter<='Z') ||(delimiter=='_')))
+		{
+			if(tmpNameStart>0)
+			{
+				delimiter = aFuncHead[tmpNameStart-1];
+				if (!((delimiter >='0' && delimiter <='9') || (delimiter>='a' && delimiter<='z') || (delimiter>='A' && delimiter<='Z') ||(delimiter=='_')))
+				{
+					nameStart = tmpNameStart;
+				}
+			}
+			if(tmpNameStart==0)
+			{
+				nameStart = tmpNameStart;
+			}
+		}				
+	}
+	if(nameStart == -1)
+	{
+		while(curPos>=0)
+		{
+			curChar = aFuncHead[curPos];
+			if(curChar==' ' || curChar=='\t' ||curChar=='\n'||curChar=='\r'||curChar=='>')
+			{
+				nameStart = curPos+1;
+				if(nameStart<0)
+				{
+					nameStart = 0;
+				}
+				break;
+				
+			}
+			else
+			{
+				curPos--;
+			}	
+			
+		}
+		if(curPos<0)
+		{
+			nameStart = 0;
+		}
+	}
+	funcName = aFuncHead.substr(nameStart,nameEnd-nameStart+1);
+	return funcName;
+
+	
+}
+/*
+ * Get the Param string of a function decl
+ * aStart usually is the position of '{'
+ * */
+string TLeaveScanModel::GetFunctionParam(const string& aText, uint aStart)
+{
+	int curPos = aStart;
+	if(curPos == string::npos)
+	{
+			return "";
+	}
+	int leftParenthesis  = GetLeftParenthesis(aText, curPos);
+	int rightParenthesis = GetRightParenthesis(aText, leftParenthesis+1);
+	
+	if(leftParenthesis==string::npos || rightParenthesis==string::npos)
+	{
+		return "";
+	}
+	else if(rightParenthesis>leftParenthesis) 
+	{
+		return aText.substr(leftParenthesis+1, rightParenthesis-leftParenthesis-1);
+	}
+	return "";
+	
+	
+}
+
+/*Get the string from last member decl to aStart*/
+string TLeaveScanModel::GetFunctionHead(const string& aText, uint aStart)
+{
+	int curPos = aStart;
+	char curChar;
+	if(curPos==string::npos || curPos<=0)
+	{
+		return "";
+	}
+	while(curPos >= 0)
+	{
+		curChar = aText[curPos];
+		if(curChar == '{' || curChar == '}' || curChar == ';')
+		{
+			break;
+		}
+		curPos--;
+	}
+	if(curPos<0)
+	{
+		curPos = 0;
+	}
+        
+	int tempPos = string::npos;
+	if( (aText.rfind("public",aStart)!=string::npos)||(aText.rfind("protected",aStart))!=string::npos ||(aText.rfind("private",aStart))!=string::npos)
+	{
+		tempPos = aText.rfind(':',aStart);
+                 
+	}
+        if(tempPos>curPos)
+	{
+		curPos = tempPos;
+	}
+	return aText.substr(curPos,aStart-curPos);
+
+}
+/*Chech the function decl/define in a class*/
+void TLeaveScanModel::CheckInClassFunc(const string& aText , const string& aClassName, const string& aFuncName, uint start,uint end)
+{
+	bool isLeaver;
+	bool clean;
+	string funcName = TrimString(GetFunctNameFromFuncHead(aFuncName));
+	string qualifiedFuncName = aClassName+"::"+funcName;
+	clean = CheckFunc(aText, funcName, start, end, isLeaver);
+	bool isLCFunc =false;
+	if(funcName[funcName.length()-1] == 'C' && funcName[funcName.length()-2] == 'L')
+	{
+	    isLCFunc = true;
+	}
+	if (isLeaver) // was a leaving container(safe) and no leavers found
+	{
+	
+	    if (clean)
+	    {
+	    	iPositionOfError=0;
+	    	iErrorString = "Warning - " + funcName + " appears to contain no leavers.";
+	        ReportErrorLineAndString(start);	  
+	    }
+	    else if(isLCFunc)
+    	  {
+    	      
+			  uint lcleanedupPos = iErrorString.find("LCleanedup");
+			  if(lcleanedupPos!=string::npos)
+				{
+    	    	  uint callPos = iErrorString.find(" calls ");
+				  uint lcleanedupPosInFuncName = funcName.find("LCleanedup");
+				  if(callPos!=string::npos && lcleanedupPosInFuncName!=string::npos && lcleanedupPos<callPos)
+				  {;}
+				  else
+				  {
+					iErrorString = "LCleanedup class is used in a function suffixed LC";
+    	    		ReportErrorLineAndString(start);
+				  }
+				}
+    	  }
+
+	    // any leavers info can be supressed here since container was leaver
+	  }
+	  else // wasn't a leaving container 
+	  {
+	    if (!clean) // was dirty, so report
+	    	ReportErrorLineAndString(start);
+	  }
+};
+
+//
+// Some test functions (for when leavescan parses its own source code)
+//
+void TLeaveScanModel::Test1()
+{
+  Test2L();
+}
+
+void TLeaveScanModel::Test2L()
+{
+  Test1();
+}
+
+#define TEST2L Test2L
+void TLeaveScanModel::Test3()
+{
+  TEST2L();
+}
+
+void TLeaveScanModel::Test4()
+{
+  Test2L(); // qualify me
+};
+
+
+
+// warnings back to default levels
+//#pragma warning (pop) 
+