JD2022-TU1/main/tools/legacy/ProjectScanner/ProjectScanner/ParseCPP.cpp

922 lines
No EOL
19 KiB
C++

#include "stdafx.h";
#if 0
bool bCharIsSpace(char _c)
{
return (
(_c == ' ') ||
(_c == 10) ||
(_c == 13) ||
(_c == '\t')
);
}
void RemoveAllRedundentSpaces(char* pWord)
{
Restart:
int i = 0;
while(pWord[i] != 0)
{
if (bCharIsSpace(pWord[i]))
{
if (bCharIsSpace(pWord[i+1]))
{
int copyto = i;
int copyfrom = i+1;
while(TRUE)
{
char c = pWord[copyfrom++];
pWord[copyto++] = c;
if (c == 0)
{
goto Restart;
}
}
}
}
i++;
}
i = 0;
while(pWord[i] != 0)
{
if (bCharIsSpace(pWord[i]))
{
pWord[i] = ' ';
}
i++;
}
}
void CleanupWord(char* pWord)
{
int index = (int)(strlen(pWord))-1;
while(pWord[index] == ' ') pWord[index--] = 0;
}
void CleanupArgType(char* pWord)
{
// Don't change the order of these tests !!!
// Look for "="
int i = 0;
while(pWord[i] != 0)
{
if (pWord[i] == '=')
{
pWord[i] = 0;
break;
}
i++;
}
// Look for "volatile"
i=0;
while(pWord[i] != 0)
{
if (!strncmp(&pWord[i], "volatile", 8))
{
pWord[i+8] = 0;
return;
}
i++;
}
// Look for "__restrict"
i=0;
while(pWord[i] != 0)
{
if (!strncmp(&pWord[i], "__restrict", 10))
{
pWord[i+10] = 0;
return;
}
i++;
}
// Look for "restrict"
i=0;
while(pWord[i] != 0)
{
if (!strncmp(&pWord[i], "restrict", 8))
{
pWord[i+8] = 0;
return;
}
i++;
}
// Look for "&, *, >"
i=0;
while(pWord[i] != 0)
{
if (
(pWord[i] == '&') ||
(pWord[i] == '*') ||
(pWord[i] == '>')
)
{
char tchar = pWord[i];
pWord[i+1] = 0;
if (i>0)
{
if (bCharIsSpace(pWord[i-1]))
{
i--;
while ((i>0) && (bCharIsSpace(pWord[i])))
{
i--;
}
pWord[i+1] = tchar;
pWord[i+2] = 0;
}
}
return;
}
i++;
}
// Treat spaces
int len = (int)strlen(pWord);
for (i=0; i<len; i++)
{
if (bCharIsSpace(pWord[i]))
{
int iFirstSpace = i;
while (bCharIsSpace(pWord[i++]));
if(i>=len)
{
return;
}
if ((pWord[i] != '*') && (pWord[i] != '&') && (pWord[i] != '>'))
{
pWord[iFirstSpace] = 0;
}
else
{
pWord[iFirstSpace] = pWord[i];
pWord[iFirstSpace+1] = 0;
}
return;
}
}
}
void HideQualifiers(char* Word)
{
int index=-1;
if (!strncmp(Word, "const", 5))
{
index = 5;
}
if (!strncmp(Word, "static", 6))
{
index = 6;
}
if (!strncmp(Word, "unsigned", 8))
{
index = 8;
}
if (!strncmp(Word, "signed", 6))
{
index = 6;
}
if (index>0)
{
while(bCharIsSpace(Word[index]))
{
Word[index] = '$';
index++;
}
}
}
void RestoreQualifiers(char* Word)
{
int index=-1;
if (!strncmp(Word, "const", 5))
{
index = 5;
}
if (!strncmp(Word, "static", 6))
{
index = 6;
}
if (!strncmp(Word, "unsigned", 8))
{
index = 8;
}
if (!strncmp(Word, "signed", 6))
{
index = 6;
}
if (index>0)
{
while(Word[index] == '$')
{
Word[index] = ' ';
index++;
}
}
}
void FullArgCleanup(char *_Word)
{
RemoveAllRedundentSpaces(_Word);
HideQualifiers(_Word);
CleanupArgType(_Word);
CleanupWord(_Word);
RestoreQualifiers(_Word);
if (!strcmp(_Word, "...")) *_Word = 0;
if (!strcmp(_Word, "void")) *_Word = 0;
}
FunctionArg::FunctionArg()
{
m_szArgType = NULL;
m_szArgName = NULL;
m_pNext = NULL;
}
FunctionArg::~FunctionArg()
{
if (m_szArgType) MemoryHandler::Free (m_szArgType);
if (m_szArgName) MemoryHandler::Free (m_szArgName);
}
Function::Function()
{
m_szType = NULL;
m_szName = NULL;
m_pArgs = NULL;
m_pNext = NULL;
m_szClassName = NULL;
}
Function::~Function()
{
if (m_szType) MemoryHandler::Free(m_szType);
if (m_szName) MemoryHandler::Free(m_szName);
if (m_szClassName) MemoryHandler::Free(m_szClassName);
FunctionArg* pArg = m_pArgs;
while(pArg)
{
FunctionArg* pDel = pArg;
pArg = pArg->m_pNext;
delete pDel;
}
}
FunctionArg& Function::AddArg()
{
if (m_pArgs == NULL)
{
m_pArgs = new FunctionArg();
return *m_pArgs;
}
FunctionArg* pArg = m_pArgs;
while(pArg->m_pNext)
{
pArg = pArg->m_pNext;
}
pArg->m_pNext = new FunctionArg();
return *pArg->m_pNext;
}
int Function::iGetArgCount()
{
FunctionArg* pArg = m_pArgs;
int iArgIndex = 0;
while (pArg)
{
iArgIndex++;
pArg = pArg->m_pNext;
}
return iArgIndex;
}
char* Function::szGetArgName(unsigned __int32 _uiArgIndex)
{
FunctionArg* pArg = m_pArgs;
__int32 uiArgIndex = 0;
while (pArg)
{
if (uiArgIndex == _uiArgIndex)
{
return pArg->m_szArgName;
}
pArg = pArg->m_pNext;
uiArgIndex++;
}
assert(uiArgIndex == 0);
return NULL;
}
ParseCPP::~ParseCPP()
{
Function* pf = m_pFunctions;
while (pf)
{
Function* pDel = pf;
pf = pf->m_pNext;
delete pDel;
}
}
Function& ParseCPP::AddFunction()
{
if (m_pFunctions == NULL)
{
m_pFunctions = new Function();
return *m_pFunctions;
}
Function* pfunc = m_pFunctions;
while(pfunc->m_pNext)
{
pfunc = pfunc->m_pNext;
}
pfunc->m_pNext = new Function();
return *pfunc->m_pNext;
}
ParseCPP::ParseCPP()
{
/*
#define TEST_ARGTYPE(_str) strcpy(Test,_str);FullArgCleanup(Test);
char Test[256];
TEST_ARGTYPE("int volatile nvint")
TEST_ARGTYPE("int volatile ")
TEST_ARGTYPE("const char * restrict filename")
TEST_ARGTYPE("const char * restrict")
TEST_ARGTYPE("const char * __restrict filename")
TEST_ARGTYPE("const char * __restrict")
TEST_ARGTYPE("const char * __restrict hop = 2")
TEST_ARGTYPE("const int")
TEST_ARGTYPE("const int zob")
TEST_ARGTYPE("const char* zob ")
TEST_ARGTYPE("const char* ")
TEST_ARGTYPE("const char * zob ")
TEST_ARGTYPE("const char * ")
TEST_ARGTYPE("char* toto ")
TEST_ARGTYPE("char* ")
TEST_ARGTYPE("char * toto ")
TEST_ARGTYPE("char * ")
TEST_ARGTYPE("char &toto ")
TEST_ARGTYPE("char &")
TEST_ARGTYPE("char&")
TEST_ARGTYPE("int zob = 2")
TEST_ARGTYPE("int zob= 2")
TEST_ARGTYPE("int")
TEST_ARGTYPE("int=2")
TEST_ARGTYPE("int =2")
TEST_ARGTYPE("unsigned int =2")
TEST_ARGTYPE("unsigned int zob=2")
TEST_ARGTYPE("template <zob> zob ")
*/
m_pFunctions = NULL;
}
bool bIsCPPInstruction(const char* pString)
{
if (!strcmp(pString, "if")) // if() instruction
{
return TRUE;
}
if (!strcmp(pString, "for")) // for() instruction
{
return TRUE;
}
if (!strcmp(pString, "while")) // while() instruction
{
return TRUE;
}
return FALSE;
}
bool bIsLyNMacro(const char* pString)
{
if (!strcmp(pString, "TEST"))
{
return TRUE;
}
if (!strcmp(pString, "MEM_Check"))
{
return TRUE;
}
return FALSE;
}
void ParseCPP::RetrieveArgs(TextBuffer &buf, Function& func, unsigned __int32 uiOpenParenthesisOffset, unsigned __int32 uiClosingParenthesisOffset)
{
char SkipSpaces[6] = {'\t', '\r', ' ', 10, 13, 0};
char ArgNameDelimiter[12] = {'(', '>', '<', '*', '&', '\t', '\r', ' ', ',', 10, 13, 0};
buf.uiReadOffset = uiOpenParenthesisOffset+ 1;
while (buf.uiReadOffset < uiClosingParenthesisOffset)
{
if (!buf.SkipCharacters(1, SkipSpaces))
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
unsigned __int32 uiLastOfs = buf.uiReadOffset;
char CommaOrParenthesis[3] = {')', ',', 0};
if (buf.FindOneChar(1, CommaOrParenthesis))
{
bool bLastArgReached = buf.GetChar() == ')';
unsigned __int32 uiNextSearch = buf.uiReadOffset + 1;
buf.uiReadOffset--;
if (!buf.SkipCharacters(-1, SkipSpaces))
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
unsigned __int32 uiEndArg = buf.uiReadOffset;
if (!buf.FindOneChar(-1, ArgNameDelimiter))
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
buf.uiReadOffset++;
if (buf.uiReadOffset < uiLastOfs)
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
unsigned __int32 uiTypeNameSize = buf.uiReadOffset - uiLastOfs;
assert(buf.uiReadOffset >= uiLastOfs);
if (uiTypeNameSize == 0)
{
if (!strncmp(buf.GetAdrs(), "...", 3)) // special case for va_lists handling: no need to look for arg name or arg trype
{
return;
}
if (!strncmp(buf.GetAdrs(), "void", 4)) // special case for "void" arg type
{
return;
}
if (bIsCPPInstruction(func.m_szName)) return;
if (bIsLyNMacro(func.m_szName)) return;
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
FunctionArg& arg = func.AddArg();
arg.m_szArgType = (char*)MemoryHandler::Alloc(uiTypeNameSize + 1);
memset(arg.m_szArgType, 0, uiTypeNameSize + 1);
memcpy(arg.m_szArgType, &buf.pAdrs[uiLastOfs], uiTypeNameSize);
FullArgCleanup(arg.m_szArgType);
uiEndArg++;
unsigned __int32 uiArgNameSize = uiEndArg - buf.uiReadOffset;
assert(uiEndArg >= buf.uiReadOffset);
if (uiArgNameSize == 0)
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
arg.m_szArgName = (char*)MemoryHandler::Alloc(uiArgNameSize + 1);
memset(arg.m_szArgName, 0, uiArgNameSize + 1);
memcpy(arg.m_szArgName, &buf.pAdrs[buf.uiReadOffset], uiArgNameSize);
if (bLastArgReached)
{
break;
}
buf.uiReadOffset = uiNextSearch;
}
}
if (func.m_szClassName && func.m_szName)
{
char funcFullName[256];
sprintf_s(funcFullName, 255, "%s::%s", func.m_szClassName, func.m_szName);
WriteHTML::AddFunction(funcFullName);
FuncArgs2HTML(func.m_szClassName, func.m_szName);
WriteHTML::EndFunction();
}
}
void ParseCPP::RetrieveArgsTypes(TextBuffer &buf, Function& func, unsigned __int32 uiOpenParenthesisOffset, unsigned __int32 uiClosingParenthesisOffset)
{
char SkipSpaces[6] = {'\t', '\r', ' ', 10, 13, 0};
char ArgNameDelimiter[12] = {'(', '>', '<', '*', '&', '\t', '\r', ' ', ',', 10, 13, 0};
char BetweenArgsDelimiter[3] = {'(', ',', 0};
buf.uiReadOffset = uiOpenParenthesisOffset+ 1;
while (buf.uiReadOffset < uiClosingParenthesisOffset)
{
if (!buf.SkipCharacters(1, SkipSpaces))
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
unsigned __int32 uiLastOfs = buf.uiReadOffset;
char CommaOrParenthesis[3] = {')', ',', 0};
if (buf.FindOneChar(1, CommaOrParenthesis))
{
bool bLastArgReached = buf.GetChar() == ')';
unsigned __int32 uiNextSearch = buf.uiReadOffset + 1;
buf.uiReadOffset--;
if (!buf.SkipCharacters(-1, SkipSpaces))
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
unsigned __int32 uiEndArg = buf.uiReadOffset; // last character before coma or parenthesis
if (!buf.FindOneChar(-1, BetweenArgsDelimiter))
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
buf.uiReadOffset++;
buf.SkipCharacters(1, SkipSpaces);
if (buf.uiReadOffset < uiLastOfs)
{
Error::Log("Error looking for function args");
int iBreakPointHere = 0; // chiure
return;
}
unsigned __int32 uiStartArg = buf.uiReadOffset; // first character after coma or parenthesis
int iCandSize = uiEndArg - uiStartArg;
if (iCandSize >= 0)
{
char* szTypeCandidate = (char*)MemoryHandler::Alloc(iCandSize + 2);
memset(szTypeCandidate, 0, iCandSize + 2);
memcpy(szTypeCandidate, &buf.pAdrs[uiStartArg], iCandSize + 1);
FullArgCleanup(szTypeCandidate);
if (*szTypeCandidate != 0)
{
FunctionArg& arg = func.AddArg();
arg.m_szArgType = szTypeCandidate;
}
}
buf.uiReadOffset = uiNextSearch;
}
}
}
void ParseCPP::RetrieveNames(TextBuffer &buf, unsigned __int32 uiClosingParenthesisOffset)
{
char SkipSpaces[6] = {'\t', '\r', ' ', 10, 13, 0};
char Delimiters[10] = {'\t', '\r', ' ', 10, 13, '*', '&', '>', ':', 0};
bool bLookForClassName = FALSE;
unsigned __int32 uiOpenParenthesisOffset = buf.uiReadOffset--;
if (buf.SkipCharacters(-1, SkipSpaces))
{
OffsetInTextBuffer uiStartOfWord(buf.uiReadOffset, &buf);
if (buf.FindOneChar(-1, Delimiters))
{
if ((buf.pAdrs[buf.uiReadOffset] == ':') && (buf.pAdrs[buf.uiReadOffset-1] == ':'))
{
bLookForClassName = TRUE;
}
OffsetInTextBuffer uiPotentialClassName(buf.uiReadOffset-2, &buf);
OffsetInTextBuffer uiEndOfWord(buf.uiReadOffset+1, &buf);
unsigned __int32 iSize = uiStartOfWord.value - uiEndOfWord.value + 2;
if (iSize == 0)
{
Error::Log("Null length function name");
int iBreakPointHere = 0; // chiure
return;
}
Function& func = AddFunction();
func.m_szName = (char*)MemoryHandler::Alloc(iSize);
memset(func.m_szName, 0, iSize);
memcpy(func.m_szName, &buf.pAdrs[uiEndOfWord.value], iSize - 1);
if (bLookForClassName)
{
buf.uiReadOffset = uiPotentialClassName.value;
if (buf.FindOneChar(-1, Delimiters))
{
buf.uiReadOffset++;
if (uiPotentialClassName.value > buf.uiReadOffset)
{
unsigned __int32 uiClassNameSize = uiPotentialClassName.value - buf.uiReadOffset + 1;
func.m_szClassName = (char*)MemoryHandler::Alloc(uiClassNameSize + 1);
memset(func.m_szClassName, 0, uiClassNameSize + 1);
memcpy(func.m_szClassName, buf.GetAdrs(), uiClassNameSize);
}
else
{
if ((*buf.GetAdrs() == ':') && (*(buf.GetAdrs()+1) == ':'))
{
return;
}
Error::Log("Bad class name length");
int iBreakPointHere = 0; // chiure
return;
}
}
}
RetrieveArgs(buf, func, uiOpenParenthesisOffset, uiClosingParenthesisOffset);
}
}
}
bool ParseCPP::bFoundPotentialFunction(TextBuffer &buf, unsigned __int32 _uiMinOffset)
{
char SkipSpaces[6] = {'\t', '\r', ' ', 10, 13, 0};
if (!buf.FindOneChar(1, ")"))
{
return FALSE;
}
unsigned __int32 uiClosingParenthesisOffset = buf.uiReadOffset++;
if (!buf.SkipCharacters(1, SkipSpaces))
{
return FALSE;
}
if (buf.GetChar() != '{')
{
return TRUE;
}
unsigned __int32 uiOpenBracketOffset = buf.uiReadOffset;
buf.uiReadOffset = uiClosingParenthesisOffset;
char* pDelimiter = buf.FindCorrespondingDelimiter(-1, ')', '(');
if ((!pDelimiter) ||(buf.uiReadOffset <= _uiMinOffset))
{
Error::Log("no matching opening parenthesis found");
int iBreakPointHere = 0;
buf.uiReadOffset = uiClosingParenthesisOffset + 1;
return TRUE;
}
else
{
RetrieveNames(buf, uiClosingParenthesisOffset);
buf.uiReadOffset = uiOpenBracketOffset;
if (!buf.FindCorrespondingDelimiter(1, '{', '}'))
{
Error::Log("no matching bracket found");
int iBreakPointHere = 0;
return TRUE;
}
buf.uiReadOffset++;
}
return TRUE;
}
void ParseCPP::ScanFile(const char* _szFileName)
{
//_szFileName = "c:\\dbg.txt";
WriteHTML::SetTargetFile(0);
WriteHTML::AddFile(_szFileName);
printf("ParseCPP Scanning file %s...\n", _szFileName);
TextBuffer buf(_szFileName);
buf.CleanupCPPComments();
char SkipSpaces[6] = {'\t', '\r', ' ', 10, 13, 0};
while(bFoundPotentialFunction(buf, buf.uiReadOffset));
}
void ParseCPP::PrintAll()
{
Function* pf = m_pFunctions;
while (pf)
{
printf("\n\n********** function found **********\n");
if (pf->m_szClassName)
{
printf("\t%s::%s\n", pf->m_szClassName, pf->m_szName);
}
else
{
printf("\t%s\n", pf->m_szName);
}
FunctionArg* pArg = pf->m_pArgs;
while (pArg)
{
printf("\t\tArg type: %s Arg Name: %s\n", pArg->m_szArgType, pArg->m_szArgName);
pArg = pArg->m_pNext;
}
pf = pf->m_pNext;
}
}
bool ParseCPP::bFunctionExists(const char* _szClass, const char* _szFunc)
{
Function* pf = m_pFunctions;
while (pf)
{
if (!strcmp(pf->m_szName, _szFunc))
{
if (pf->m_szClassName)
{
if (!strcmp(pf->m_szClassName, _szClass))
{
return TRUE;
}
}
int iBreakPointHere = 0; // same function name found, but not in same class. it that intended?
}
pf = pf->m_pNext;
}
return FALSE;
}
const char* ParseCPP::szGetArgName(const char* _szClass, const char* _szFunc, __int32 _argIndex)
{
Function* pf = m_pFunctions;
while (pf)
{
if (!strcmp(pf->m_szName, _szFunc))
{
if (pf->m_szClassName)
{
if (!strcmp(pf->m_szClassName, _szClass))
{
FunctionArg* pArg = pf->m_pArgs;
__int32 uiArgIndex = 0;
while (pArg)
{
if (uiArgIndex == _argIndex)
{
return pArg->m_szArgName;
}
pArg = pArg->m_pNext;
uiArgIndex++;
}
int iBreakPointHere = 0; // arg index does not exist
}
}
int iBreakPointHere = 0; // same function name found, but not in same class. it that intended?
}
pf = pf->m_pNext;
}
return NULL;
}
void ParseCPP::FuncArgs2HTML(const char* _szClass, const char* _szFunc)
{
Function* pf = m_pFunctions;
while (pf)
{
if (!strcmp(pf->m_szName, _szFunc))
{
if (pf->m_szClassName && _szClass)
{
if (!strcmp(pf->m_szClassName, _szClass))
{
FunctionArg* pArg = pf->m_pArgs;
while (pArg)
{
if (pArg->m_szArgType && pArg->m_szArgName)
{
char argdata[512];
strcpy_s(argdata, 512, pArg->m_szArgType);
strcat_s(argdata, 512, " ");
strcat_s(argdata, 512, pArg->m_szArgName);
WriteHTML::AddFunctionArg(argdata);
}
pArg = pArg->m_pNext;
}
return;
}
}
}
pf = pf->m_pNext;
}
}
static int DBG_AreFunctionsIdenticalIterCount = 0;
bool ParseCPP::AreFunctionsIdentical(Function& f1, Function& f2)
{
if (!strcmp(f1.m_szName, "Shadow_CopyBranches"))
{
int bp=0;
}
FunctionArg* pArg1 = f1.m_pArgs; // origin : Scanned H
FunctionArg* pArg2 = f2.m_pArgs; // origin : Scanned CPP
DBG_AreFunctionsIdenticalIterCount++;
if (DBG_AreFunctionsIdenticalIterCount == 251)
{
int aa=0;
}
while (pArg1)
{
if (!pArg2)
{
return FALSE; // different arg count
}
if ((pArg1->m_szArgType) && (pArg2->m_szArgType))
{
FullArgCleanup(pArg1->m_szArgType);
FullArgCleanup(pArg2->m_szArgType);
if (strcmp(pArg1->m_szArgType, pArg2->m_szArgType))
{
return FALSE; // different arg type
}
}
pArg1 = pArg1->m_pNext;
pArg2 = pArg2->m_pNext;
}
if (pArg2)
{
return FALSE; // different arg count
}
return TRUE; // identical
}
static int GetClosestFunctionIterCount = 0;
Function* ParseCPP::GetClosestFunction(const char* _szClassName, const char* _szFuncName, TextBuffer &buf, unsigned __int32 uiOpenParenthesisOffset, unsigned __int32 uiClosingParenthesisOffset)
{
GetClosestFunctionIterCount++;
if (GetClosestFunctionIterCount == 170)
{
int aa = 0;
}
Function func;
func.m_szClassName = (char*)MemoryHandler::Alloc(strlen(_szClassName) + 1);
strcpy(func.m_szClassName, _szClassName);
func.m_szName = (char*)MemoryHandler::Alloc(strlen(_szFuncName) + 1);
strcpy(func.m_szName, _szFuncName);
RetrieveArgsTypes(buf, func, uiOpenParenthesisOffset, uiClosingParenthesisOffset);
Function* pf = m_pFunctions;
Function* pBest = NULL;
Function* pNear = NULL; // for debug only
while (pf)
{
if ((pf->m_szClassName) && (!strcmp(_szClassName, pf->m_szClassName)))
{
if ((pf->m_szName) && (!strcmp(_szFuncName, pf->m_szName)))
{
if (!pNear) pNear = pf;
if (AreFunctionsIdentical(func, *pf))
{
assert(pf->iGetArgCount() == func.iGetArgCount());
if (pBest != NULL)
{
Error::Log("Several functions fit in CPP for function %s\n", pf->m_szName);
int iBreakPoint = 0; // several functionsthat fit!
}
pBest = pf;
}
}
}
pf = pf->m_pNext;
}
/* if (!pBest)
{
assert(!pNear); // oOps, no function found
}*/
return pBest;
}
#endif