apicompatanamdw/compatanalysercmd/headeranalyser/src/CPPParser.cpp
changeset 3 ebe3f8f03b59
parent 0 638b9c697799
--- a/apicompatanamdw/compatanalysercmd/headeranalyser/src/CPPParser.cpp	Thu Apr 22 17:15:08 2010 +0530
+++ b/apicompatanamdw/compatanalysercmd/headeranalyser/src/CPPParser.cpp	Mon Apr 26 16:28:13 2010 +0530
@@ -45,6 +45,8 @@
 const int KMaxFilenameLength = 512;
 const int KMaxDirLength=1024;
 
+#define MAX_ARRAY_COUNT 200
+
 // The C++ parser executable
 #ifdef __WIN__
 static const char* GCCXML_COMMAND = "ha_gccxml_cc1plus ";
@@ -466,124 +468,533 @@
 // CPPParser::HandleExports
 // ----------------------------------------------------------------------------
 //
+
 int CPPParser::HandleExports(string aFilename, string aVersion)
 {
-    int ret = 0;
-    string ofilename = aFilename + ".2";
-    
-    ifstream input(aFilename.c_str(), ios::in);
-    ofstream output(ofilename.c_str(), ios::out);
-    iOutputFilename = ofilename;
-    char c;
-    string toflush = "";
-    unsigned int matches = 0;
-    string tofind = STR_EXPORT_HACK;
-    string attribstr = STR_ATTRIBUTE_STR;
-    string outputBuffer;
-    outputBuffer.reserve(PREPROCESS_BUFFERSIZE);
-    int state = EStateSearching;
-    bool purevirtual = false;
-    bool possiblepurevirtual = false;
-    while (input.get(c))
-    {
-        if (outputBuffer.length() >= PREPROCESS_BUFFERSIZE)
-        {
-            output << outputBuffer;
-            outputBuffer = "";
-        }
-        if (state == EStateSearching)
-        {
-            if (c == tofind.at(matches))
-            {
-                matches++;
-                toflush += c;
-            } else 
-            {
-                matches = 0;
-                if (!toflush.empty())
-                {
-                    outputBuffer += toflush;
-                    toflush = "";
-                }
-                outputBuffer += c;
-            }
-            if (matches == tofind.length())
-            {
-                toflush = "";
-                state = EStateReplacing;
-                matches = 0;
-            }
-        } else if (state == EStateReplacing)
-        {
-            if (c == '=')
-            {
-                if (possiblepurevirtual == true && !toflush.empty())
-                {
-                    outputBuffer += toflush;
-                    toflush = "";
-                }
-                possiblepurevirtual = true;
-                toflush += c;
-            } else if (possiblepurevirtual == true && c!= ';')
-            {
-                if (c == ' ')
-                {
-                    toflush += c;
-                } else if (c == '\t')
-                {
-                    toflush += c;
-                } else if (c == '0')
-                {
-                    toflush += c;
-                    purevirtual = true;
-                } else
-                {
-                    outputBuffer += toflush;
-                    outputBuffer += c;
-                    toflush = "";
-                    possiblepurevirtual = false;
-                    purevirtual = false;
-                }
-            } else if (c == ';')
-            {
-                state = EStateSearching;
-                if (purevirtual)
-                {
-                } else if (possiblepurevirtual)
-                {
-                    outputBuffer += toflush;
-                    toflush = "";
-                }
+	int ret = 0;
+	string ofilename = aFilename + ".2";
+
+	ifstream input(aFilename.c_str(), ios::in);
+	ofstream output(ofilename.c_str(), ios::out);
+	iOutputFilename = ofilename;
+	char c;
+	string toflush = "";
+	string flush = "";
+	unsigned int matches = 0;
+	string tofind = STR_EXPORT_HACK;
+	string attribstr = STR_ATTRIBUTE_STR;
+	string outputBuffer;
+	outputBuffer.reserve(PREPROCESS_BUFFERSIZE);
+	int state = EStateSearching;
+	char stackArray[MAX_ARRAY_COUNT] = {'\0'};
+	int arryPos = 0;
+	
+	string isClass = "class";
+	string isEnum = "enum";
+	string isStruct = "struct";
+	string isUnion = "union";
+	string isInline = "inline";
+
+	unsigned int clsPos = 0;
+	unsigned int enmPos = 0;
+	unsigned int strctPos = 0;
+	unsigned int inlinePos = 0;
+	unsigned int unionPos = 0;
+	char arraychar = '\0';
+
+	unsigned int bufPos = 0;
+	
+	string temp;
+	string buf;
+	
+	bool possibleVirtualFunc = false;
+	bool virtualFunc = false;
+	bool ignorecheck = false;
+	while (input.get(c))
+	{
+		ignorecheck = false;
+		if (outputBuffer.length() >= PREPROCESS_BUFFERSIZE)
+		{
+			output << outputBuffer;
+			outputBuffer = "";
+		}
+       // Get the bufferpos
+		bufPos = (unsigned int)outputBuffer.length()-1;
+
+		// delete buf (class\enum\struct) entry if next letter is not space
+ 		if ( buf.length() > 0 && state == EStateReplacing && (c != ' ' && c != '\t' && int(c) != 10))
+		{
+			buf = "";
+		}
+		if( c == isClass.at(clsPos))
+		{
+			if( clsPos == 0 ) // searching for class keyword with space before and after
+			{
+				if(outputBuffer == "" || outputBuffer.at(bufPos) == ' ' || outputBuffer.at(bufPos) == '\t'
+					|| int(outputBuffer.at(bufPos)) == 10 || int(outputBuffer.at(bufPos)) == 32 )
+					clsPos++;
+			}
+			else
+				clsPos++;
+		}			
+			
+		else
+			clsPos = 0;
+		if (clsPos == isClass.length()) // keyword found 
+		{
+			clsPos = 0;
+			buf = isClass;
+			ignorecheck = true; // in the current iteration don't match buf string with class\enum\struct keyword
+			                    // as keyword may be part of some word like " classification" 
+		}
+
+		if( c == isUnion.at(unionPos))
+		{
+			if( unionPos == 0 ) // searching for union keyword with space before and after
+			{
+				if(outputBuffer == "" || outputBuffer.at(bufPos) == ' ' || outputBuffer.at(bufPos) == '\t'
+					|| int(outputBuffer.at(bufPos)) == 10 || int(outputBuffer.at(bufPos)) == 32 )
+					unionPos++;
+			}
+			else
+				unionPos++;
+		}			
+			
+		else
+			unionPos = 0;
+		if (unionPos == isUnion.length()) // keyword found 
+		{
+			unionPos = 0;
+			buf = isUnion;
+			ignorecheck = true; // in the current iteration don't match buf string with class\enum\struct\union keyword
+			                    // as keyword may be part of some word like " classification" 
+		}
+
+		if(c == isStruct.at(strctPos))// searching for struct keyword with space before and after
+		{
+			if( strctPos == 0 )
+			{
+				if(outputBuffer == "" || outputBuffer.at(bufPos) == ' ' || outputBuffer.at(bufPos) == '\t'
+					|| int(outputBuffer.at(bufPos)) == 10 )
+					strctPos++;
+			}
+			else
+				strctPos++;
+		}
+		else
+			strctPos = 0;
+
+		if(strctPos == isStruct.length())
+		{
+			strctPos = 0;
+			buf = isStruct;
+			ignorecheck = true; // in the current iteration don't match buf string with class\enum\struct keyword
+			                    // as keyword may be part of some word like " structural" 
+		}
+
+		if(c == isEnum.at(enmPos) )// searching for enum keyword with space before and after
+		{
+			if( enmPos == 0 )
+			{
+				if(outputBuffer == "" || outputBuffer.at(bufPos) == ' ' || outputBuffer.at(bufPos) == '\t'
+					|| int(outputBuffer.at(bufPos)) == 10 )
+					enmPos++;
+			}
+			else
+				enmPos++;
+		}
+		else
+			enmPos = 0;
+
+		if( enmPos == isEnum.length())
+		{
+			enmPos = 0;
+			buf = isEnum;
+			ignorecheck = true;// in the current iteration don't match buf string with class\enum\struct keyword
+			                    // as keyword may be part of some word like " enumuration" 
+		}
+
+		if (state == EStateSearching)
+		{
+			memset(stackArray,'\0',MAX_ARRAY_COUNT);
+			if (c == tofind.at(matches))
+			{
+				matches++;
+				toflush += c;
+			} else 
+			{
+				matches = 0;
+				if (!toflush.empty())
+				{
+					outputBuffer += toflush;
+					toflush = "";
+				}
+				outputBuffer += c;
+				
+				if(buf.length() > 0 && ignorecheck == false && (c != ' ' && c != '\t' 
+					&& int(c) != 10 ))
+				{
+					buf = "";
+					arraychar = '\0';
+				}
+			}
+			if (matches == tofind.length())
+			{
+				toflush = "";
+				state = EStateReplacing; // export keyword match found, so make the stae as replacing
+				matches = 0;
+			}
+		} else if (state == EStateReplacing)
+		{  
+			// under a exported class,for a function the exported keyword is present,it should be deleted.
+			if (c == tofind.at(matches))
+			{
+				matches++;
+				toflush += c;
+				if (matches == tofind.length())
+				{
+					toflush = "";
+					matches = 0;					
+				}
+				continue;
+			} else 
+			{
+				matches = 0;
+				if (!toflush.empty())
+				{
+					outputBuffer += toflush;
+					toflush = "";
+				}		
+			}
+			
+		
+			if(c == isInline.at(inlinePos))
+			{
+				if( inlinePos == 0 )// searching for inline keyword with space before and after
+				{
+					if(outputBuffer == "" || outputBuffer.at(bufPos) == ' ' || outputBuffer.at(bufPos) == '\t'
+						|| int(outputBuffer.at(bufPos)) == 10 )
+						inlinePos++;
+				}
+				else
+					inlinePos++;
+			}		
+			else
+				inlinePos = 0;
+			
+			if( inlinePos == isInline.length())
+			{
+				inlinePos = 0;
+				buf = isInline;
+
+			}
+
+			if ( buf.length() > 0 && (c == ' ' || c == '\t' || int(c) == 10))
+			{
+				if (buf == isClass)
+				{
+					arraychar = 'c';
+				}
+				if (buf == isStruct )
+				{
+					arraychar = 's';
+				}
+				if (buf == isEnum)
+				{
+					arraychar = 'e';
+				}
+				if(buf == isUnion)
+				{
+					arraychar = 'u';
+				}
+				if(buf == isInline) 
+				{
+					stackArray[arryPos] = 'i'; // place inline keyword in stack
+					arryPos++;
+				}
+				
+				buf = "";
+				if(temp.length() > 0) 
+					temp = "";
+			}
+			else if (c == '{')
+			{
+				// place the keyword in stack for class\enum\struct
+				if(arraychar != '\0')
+				{
+					stackArray[arryPos] = arraychar;
+					arraychar = '\0';
+					arryPos++;
+				}				
+				stackArray[arryPos] = c;				
+                arryPos++;
 
-                outputBuffer += " ";
-                outputBuffer += attribstr;
-                if (!toflush.empty())
-                {
-                    outputBuffer += " ";
-                    outputBuffer += toflush;
-                    toflush = "";
-                }
-                possiblepurevirtual = false;
-                purevirtual = false;
-                outputBuffer += ';';
-            } else
-            {
-                outputBuffer += c;
-            }
-        } else if (state == EStateReplaceDone)
-        {
+				if(temp.length() > 0) 
+					temp = "";
+			}
+			else if(c== '}')
+			{
+				temp = "";
+				bool ignore = false;
+				// can be end of class\enum\struct				
+				for (int i = arryPos-1; i >= 0; i-- )
+				{
+
+					if (stackArray[i] == '{' ) 
+					{
+						if( stackArray[i-1] != 'c' && stackArray[i-1] != 's' 
+							&& stackArray[i-1] != 'e' && stackArray[i-1] != 'u')
+							// check if the function is inline
+						{
+
+							ignore = true;
+							break;
+						}
+					}
+				}
+				if(ignore == false)
+					temp = c;
+				
+				stackArray[arryPos] = c;
+                arryPos++;
+
+				if(temp == "")
+				{
+					int openbraceCount = 0;
+					int closebracecount = 0;
+
+					// if it is end of a function then delete the entry from stack
+					// and it is ofcourse not a exported function, 
+					//will definitely be a inline function with or without "inline" keyword
+					bool deleteEntry = false;
+					int setpos = 0;
+					// get the pos after class\struct\enum started
+					for(int i = arryPos; i >= 0; i--)
+					{
+						if(stackArray[i] == '{')
+						{
+							deleteEntry = true;
+							if (stackArray[i-1] == 'c' || stackArray[i-1] == 's' 
+								|| stackArray[i-1] == 'e' || stackArray[i-1] == 'u')
+							{
+								setpos = i+1;								
+								break;
+							}							
+						}
+					}
+					// find the end pos of the non exported function by matching the open and close flower brace count.
+					if(deleteEntry)
+					{
+						deleteEntry = false;
+						for(int i = setpos; i <= arryPos; i++ )
+						{						
+							if(stackArray[i] == '{')
+								openbraceCount++;
+							else if(stackArray[i] == '}')
+								closebracecount++;
+						}
+						if(openbraceCount > 0 && openbraceCount == closebracecount )
+						{
+							deleteEntry = true;// need to delete the non exported function entry from stack now
+						}
+					}
+					// noe delete the non exported entry and re arrange the stack
+					if(deleteEntry)
+					{
+						for(int pos = setpos; pos <= arryPos; pos++ )
+							stackArray[pos] = '\0';
+
+						arryPos = setpos;
+					}
+				}
+				
+			}
+			else if ( (c == '=' && stackArray[arryPos-1] == ')') ||
+                      (c == '0' && stackArray[arryPos-1] == '=') ||
+					  (c == '(' || c == ')' )||
+					  ( possibleVirtualFunc == true ||virtualFunc == true)
+					 ) // can be a virtual function or normal function which might be exported
+			{
+				if(temp.length() > 0) 
+					temp = "";
+
+				if( (possibleVirtualFunc == true && (  c!= '0' && c != ' ' && c != '\t' && int(c) != 10) ) ||
+					(virtualFunc == true && (c!= ';' && c != ' ' && c != '\t' && int(c) != 10)) )
+				{ // if other than space and '0', then set posVirtual func to false
+					// or if other than space and ';', then set Virtual func to false
+					outputBuffer += flush;
+					outputBuffer += c;
+					flush = "";
+					possibleVirtualFunc = false;
+					virtualFunc = false;
+					continue;
+				}
 
-        }
+				else if( c == '=') // possible virtual function
+				{
+					flush = c;
+					possibleVirtualFunc = true;
+					virtualFunc = false;
+					stackArray[arryPos] = c;
+					arryPos++;
+					continue;
+				}
+				else if (possibleVirtualFunc == true)
+				{				
+					flush += c;
+					if ( c == '0')
+					{
+						virtualFunc = true; // pure virtual function
+						possibleVirtualFunc = false;
+						stackArray[arryPos] = c;
+						arryPos++;
+					}					
+					continue;
+				}
+				else if (c == '(' || c == ')')
+				{
+					flush = "";
+					stackArray[arryPos] = c;
+					arryPos++;
+				}
+				
+			} 
+			
+			if (c == ';')
+			{
+				arraychar = '\0';
+				// first check for inline function and delete the entry from stack for this func
+				bool isinline = false;
+				bool nonExpFun = false;
+				bool removeEntry = false;
+
+				for (int i = arryPos-1; i >= 0; i-- )
+				{
+					if ( stackArray[i] == 'i') // inline function with inline keyword
+						isinline = true;
+					
+					else if (stackArray[i] == '{')// check if the function is inline
+					{
+						if (stackArray[i-1] != 'c' && stackArray[i-1] != 's' 
+							  && stackArray[i-1] != 'e' && stackArray[i-1] != 'u')
+							nonExpFun = true;
+					}
+				}
+
+				// end of struct/class/enum
+				if (stackArray[arryPos-1] == '}' && temp == "}"   ) 
+				{
+					//if(!isinline && !nonExpFun)
+					{
+					int cnt = arryPos-1;
+					bool flag = false;
+					for (int i = cnt; i>=0; i--)
+					{
+						if (stackArray[i] == 'c' || stackArray[i] == 's' 
+							   || stackArray[i] == 'e' || stackArray[i] == 'u')
+						{
+							flag = true;
+						}	
+						stackArray[i] = '\0';		
+						arryPos--;
+						if( flag )	
+						{
+							break;
+						}
+					}
+					outputBuffer += c;
+					temp = "";
 
-    }
-    if (outputBuffer.length() != 0)
-    {
-        output << outputBuffer;
-    }
-    return ret;
+					if(stackArray[0] == '\0') // check if exported class\struct is ended .. 
+						                      // set state to searching and continue;
+						state = EStateSearching;
+					continue;
+					}
+				}				
+				
+				if(stackArray[arryPos-1] == '('&& nonExpFun == false && isinline == false) 
+					// not function, can be a for loop, so reset the stackArray ...
+				{				
+					outputBuffer += c;
+					removeEntry = true;
+				}
+				else if(stackArray[arryPos-1] == ')'  ) 
+					// some exported function can be "abcd( xyz(0), pqr(0))"
+				{	
+					if( nonExpFun == false && isinline == false )
+					{
+						outputBuffer += " ";
+						outputBuffer += attribstr;
+					}
+					outputBuffer += c;	
+					if (nonExpFun == false)
+					removeEntry = true;
+				}			
+				else if( (stackArray[arryPos-1] == '0' && stackArray[arryPos-2] == '=' && virtualFunc == true) )
+				{ // can be a virtual function or normal function which is definitely exported
+					if(!isinline && !nonExpFun)
+					{
+						outputBuffer += " ";
+						outputBuffer += attribstr;
+						outputBuffer += " ";
+					}					
+					outputBuffer += flush;					
+					outputBuffer += c;
+					flush = "";
+					if(nonExpFun == false)
+						removeEntry = true;
+					virtualFunc = false;
+				}
+				else	
+				{
+					outputBuffer += c;
+				}
+
+				if(removeEntry == true)
+				{
+					int cnt = arryPos-1;
+					bool flag = false;
+					for (int i = cnt; i>=0; i--)
+					{
+						if (stackArray[i] == '{' && 
+							(stackArray[i-1] == 'c' || stackArray[i-1] == 's' 
+							|| stackArray[i-1] == 'e' || stackArray[i-1] == 'u') )
+							flag = true;
+
+						if(flag == false)
+						{
+							stackArray[i] = '\0';	
+							arryPos--;
+						}
+					}
+				}
+	
+				if(stackArray[0] == '\0')
+					state = EStateSearching;				
+			} 
+			else
+			{
+				if(  virtualFunc == true )
+				{
+					outputBuffer += flush;					
+					flush = "";
+                    virtualFunc = false;
+				}
+				outputBuffer += c;
+			}
+		} else if (state == EStateReplaceDone)
+		{
+
+		}
+
+	}
+	if (outputBuffer.length() != 0)
+	{
+		output << outputBuffer;
+	}
+	return ret;
 }
 
-
 // ----------------------------------------------------------------------------
 // CPPParser::ReplaceExport
 // ----------------------------------------------------------------------------