123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- #include "CDepChecker.h"
- #include "BeefySysLib/util/PerfTimer.h"
- #include "ClangHelper.h"
- #include "BeefySysLib/util/AllocDebug.h"
- USING_NS_BF;
- //////////////////////////////////////////////////////////////////////////
- static CDepChecker* gCDepChecker = NULL;
- static PerfManager gCDepPerfManager;
- static PerfManager* gPerfManagerPtr = NULL;
- CDepFile::~CDepFile()
- {
- delete mParser;
- }
- void CppParser::HandlePragma(const StringImpl& pragma, BfBlock* block)
- {
-
- }
- void CppParser::HandleDefine(const StringImpl& defineString, BfAstNode* paramNode)
- {
-
- }
- void CppParser::HandleUndefine(const StringImpl& name)
- {
-
- }
- MaybeBool CppParser::HandleIfDef(const StringImpl& name)
- {
- return MaybeBool_None;
- }
- MaybeBool CppParser::HandleProcessorCondition(BfBlock* paramNode)
- {
- return MaybeBool_None;
- }
- void CppParser::HandleInclude(BfAstNode* paramNode)
- {
- IncludeHelper(paramNode, false, false);
- }
- void CppParser::HandleIncludeNext(BfAstNode* paramNode)
- {
- IncludeHelper(paramNode, true, false);
- }
- bool CppParser::IncludeHelper(BfAstNode* paramNode, bool includeNext, bool scanOnly)
- {
- String name;
- bool isLocalInclude = false;
- auto checkNode = paramNode;
- if (auto identifier = BfNodeDynCast<BfIdentifierNode>(checkNode))
- {
- //EvaluatePreprocessor(identifier, NULL, &checkNode);
- return false;
- }
- if (auto token = BfNodeDynCast<BfTokenNode>(checkNode))
- {
- //TODO: DO THIS
- /*if (token->mToken == BfToken_LChevron)
- {
- auto curNode = checkNode->mNext;
- while (curNode != NULL)
- {
- if ((token = BfNodeDynCast<BfTokenNode>(curNode)))
- {
- if (token->mToken == BfToken_RChevron)
- break;
- }
- name += curNode->ToString();
- curNode = curNode->mNext;
- }
- }*/
- }
- else if (auto literalExpr = BfNodeDynCast<BfLiteralExpression>(checkNode))
- {
- if (literalExpr->mValue.mTypeCode == BfTypeCode_CharPtr)
- {
- name = String(literalExpr->GetSourceData()->mSrc + literalExpr->GetSrcStart() + 1, literalExpr->GetSourceData()->mSrc + literalExpr->GetSrcEnd() - 1);
- isLocalInclude = true;
- }
- }
- if (name.empty())
- return false;
- for (int i = 0; i < (int)name.length(); i++)
- if (name[i] == DIR_SEP_CHAR_ALT)
- name[i] = DIR_SEP_CHAR;
- String curDir = GetFileDir(mFileName);
- bool found = false;
- bool foundCurPath = false;
- for (int i = isLocalInclude ? -1 : 0; i < (int)mCDepChecker->mIncludeDirs.size(); i++)
- {
- String checkPath;
- if (i == -1)
- checkPath = curDir;
- else
- checkPath = mCDepChecker->mIncludeDirs[i];
- if (includeNext)
- {
- if (checkPath == curDir)
- {
- foundCurPath = true;
- continue;
- }
- if (!foundCurPath)
- continue;
- }
-
- checkPath = GetAbsPath(name, checkPath);
- #ifdef _WIN32
- checkPath = ToUpper(checkPath);
- #endif
- if (mCDepChecker->CachedFileExists(checkPath))
- {
- if (scanOnly)
- return true;
- bool isFromCache = false;
- found = true;
- CDepFile* cDepFile = mCDepChecker->LoadFile(checkPath, mCDepFile, &isFromCache);
- if (cDepFile != NULL)
- {
- for (auto refFileName : cDepFile->mFilesReferenced)
- mCDepFile->mFilesReferenced.insert(refFileName);
- }
-
- return true;
- }
- }
- //BF_ASSERT(found);
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- CDepChecker::CDepChecker()
- {
- mAbort = false;
- mCPPCount = 0;
- mFindHeaderIdx = -1;
- }
- void CDepChecker::SetCArgs(const char* cArgs)
- {
- int strStart = 0;
- for (int i = 0; cArgs[i] != (char)0; i++)
- {
- if (cArgs[i] == '\n')
- {
- String arg = String(cArgs + strStart, cArgs + i);
- if (strncmp(arg.c_str(), "-I", 2) == 0)
- {
- String includeDir = arg.Substring(2);
- includeDir = EnsureEndsInSlash(includeDir);
- #ifdef _WIN32
- includeDir = ToUpper(includeDir);
- #endif
- mIncludeDirs.push_back(includeDir);
- }
- else if (strncmp(arg.c_str(), "-D", 2) == 0)
- {
- }
- strStart = i + 1;
- }
- }
- }
- /*String CDepChecker::DetermineFilesReferenced(const StringImpl& fileName)
- {
- LoadFile(fileName);
- return "";
- }*/
- CDepFile* CDepChecker::LoadFile(const StringImpl& inFileName, CDepFile* fileFrom, bool* isFromCache, const char* contentOverride)
- {
- *isFromCache = false;
- if (mAbort)
- return NULL;
-
- AutoPerf autoPerf("LoadFile", gPerfManagerPtr);
- #ifdef _WIN32
- String fileName = ToUpper(inFileName);
- #else
- String fileName = inFileName;
- #endif
- if (mFindHeaderFileName.length() > 0)
- {
- if (fileFrom != NULL)
- {
- if ((mFindHeaderIdx == -1) && (fileName == mFindHeaderFileName))
- mFindHeaderIdx = fileFrom->mParser->mLineStart;
- return NULL;
- }
- }
- //Val128 val128 = cDepPreprocState->mBaseHash;
- //HASH128_MIXIN_STR(val128, fileName);
-
- CDepFile* dataCDep = NULL;
- auto depFileItr = mDepFileMap.find(fileName);
- if (depFileItr != mDepFileMap.end())
- {
- auto checkCDepFile = depFileItr->second;
- depFileItr++;
- dataCDep = checkCDepFile;
- if (checkCDepFile->mProcessing)
- {
- BF_ASSERT(fileFrom != NULL);
- // Propagate include files down the line once we finish processing cDepFile
- checkCDepFile->mDeferredDepSet.insert(fileFrom);
- for (auto childDep : fileFrom->mDeferredDepSet)
- checkCDepFile->mDeferredDepSet.insert(childDep);
- }
-
- *isFromCache = true;
- return checkCDepFile;
- }
-
- CDepFile* cDepFile = new CDepFile();
- cDepFile->mFilePath = fileName;
- cDepFile->mFilesReferenced.insert(fileName);
- cDepFile->mProcessing = true;
-
- bool fileAlreadyVisited = mFilesVisited.find(fileName) != mFilesVisited.end();
- if (!fileAlreadyVisited)
- mFilesVisited.insert(fileName);
- mDepFileMap.insert(CDepFileMap::value_type(fileName, cDepFile));
- BfPassInstance bfPassInstance(NULL);
- CppParser* newParser = new CppParser();
- cDepFile->mParser = newParser;
- //int64 fileTime = GetFileTimeWrite(fileName);
- //cDepFile->mFileTime = fileTime;
- int fileSize = 0;
-
- newParser->mAstAllocManager = &mAstAllocManager;
- newParser->mFileName = fileName;
- newParser->mFileAlreadyVisited = fileAlreadyVisited;
- newParser->mAborted = false;
- newParser->mCDepChecker = this;
- newParser->mCDepFile = cDepFile;
- if (dataCDep != NULL)
- {
- //OutputDebugStrF("CDep Reffing file: %s\n", fileName.c_str());
- newParser->RefSource(dataCDep->mFileData.mData, dataCDep->mFileData.mLength);
- cDepFile->mFileData = dataCDep->mFileData;
- }
- else
- {
- AutoPerf autoPerf("LoadFile LoadTextData", gPerfManagerPtr);
- CDepFileData fileData;
- fileData.mLength = 0;
-
- #ifdef IDE_C_SUPPORT
- if ((contentOverride == NULL) && (gClangUnsavedFiles != NULL))
- {
- AutoCrit autoCrit(gClangUnsavedFiles->mCritSect);
-
- for (auto& unsavedFile : gClangUnsavedFiles->mUnsavedFiles)
- {
- if (_stricmp(unsavedFile.Filename, fileName.c_str()) == 0)
- {
- fileData.mData = new char[unsavedFile.Length + 1];
- fileData.mData[unsavedFile.Length] = 0;
- memcpy(fileData.mData, unsavedFile.Contents, unsavedFile.Length);
- fileData.mLength = unsavedFile.Length;
- break;
- }
- }
- }
- #endif
- if (contentOverride != NULL)
- {
- newParser->RefSource(contentOverride, (int)strlen(contentOverride));
- }
- else
- {
- if (fileData.mData == NULL)
- {
- fileData.mData = Beefy::LoadTextData(fileName, &fileData.mLength);
- //BF_ASSERT(fileData.mData != NULL);
- }
- if (fileData.mData != NULL)
- newParser->RefSource(fileData.mData, fileData.mLength);
- }
- //OutputDebugStrF("CDep Loading file: %s\n", fileName.c_str());
-
-
- cDepFile->mFileData = fileData;
- if (fileData.mData != NULL)
- mDepFileData.push_back(fileData);
- }
- int maxIncludeDepth = 256;
- #ifdef _DEBUG
- maxIncludeDepth = 64;
- #endif
- if ((int)gCDepChecker->mIncludeStack.size() >= maxIncludeDepth) // Include stack blown?
- mAbort = true;
- gCDepChecker->mIncludeStack.push_back(cDepFile);
- {
- AutoPerf autoPerf("LoadFile Parse", gPerfManagerPtr);
- if (newParser->mSrc != NULL)
- newParser->Parse(&bfPassInstance);
- newParser->Close();
- }
- gCDepChecker->mIncludeStack.pop_back();
- //bool wasAborted = newParser->mAborted;
- bool wasAborted = false;
- //cDepPreprocState->mParsers.push_back(newParser);
- cDepFile->mProcessing = false;
- // We need to remove this because it wasn't really processed and won't have mFilesReferenced and such filled in
- if (wasAborted)
- {
- delete cDepFile;
- //auto itr = mDepFileMap.find(val128);
- mDepFileMap.erase(depFileItr);
- return NULL;
- }
- else
- {
- for (auto deferredFile : cDepFile->mDeferredDepSet)
- {
- for (auto refFile : cDepFile->mFilesReferenced)
- deferredFile->mFilesReferenced.insert(refFile);
- }
- }
- return cDepFile;
- }
- void CDepChecker::ClearCache()
- {
- mCPPCount = 0;
- for (auto pair : mDepFileMap)
- {
- delete pair.second;
- }
- mDepFileMap.clear();
- for (auto& depFileData : mDepFileData)
- {
- delete depFileData.mData;
- }
- mDepFileData.clear();
- mFileExistsCache.clear();
- }
- bool CDepChecker::CachedFileExists(const StringImpl& filePath)
- {
- AutoPerf autoPerf("CachedFileExists", gPerfManagerPtr);
- auto itr = mFileExistsCache.find(filePath);
- if (itr != mFileExistsCache.end())
- return itr->second;
- auto fileExists = FileExists(filePath);
- mFileExistsCache[filePath] = fileExists;
- return fileExists;
- }
- //////////////////////////////////////////////////////////////////////////
- /// Get the value the ATOMIC_*_LOCK_FREE macro should have for a type with
- /// the specified properties.
- static int GetLockFreeValue(int typeWidth, int typeAlign, int inlineWidth)
- {
- // Fully-aligned, power-of-2 sizes no larger than the inline
- // width will be inlined as lock-free operations.
- if (typeWidth == typeAlign && (typeWidth & (typeWidth - 1)) == 0 &&
- typeWidth <= inlineWidth)
- return 2; // "always lock free"
- // We cannot be certain what operations the lib calls might be
- // able to implement as lock-free on future processors.
- return 1; // "sometimes lock free"
- }
- static void FixFilePath(String& fileName)
- {
- for (int i = 0; i < (int)fileName.length(); i++)
- if (fileName[i] == DIR_SEP_CHAR_ALT)
- fileName[i] = DIR_SEP_CHAR;
- #ifdef _WIN32
- else
- fileName[i] = (char)::toupper((uint8)fileName[i]);
- #endif
- }
- static int gCheckCount = 0;
- BF_EXPORT const char* BF_CALLTYPE CDep_DetermineFilesReferenced(const char* fileNamePtr, const char* cArgs)
- {
- String& outString = *gTLStrReturn.Get();
- gCheckCount++;
- if (gCDepChecker == NULL)
- gCDepChecker = new CDepChecker();
- gCDepChecker->mCPPCount++;
- gPerfManagerPtr = &gCDepPerfManager;
- gCDepChecker->SetCArgs(cArgs);
- //gPerfManagerPtr->StartRecording();
- String fileName = fileNamePtr;
- FixFilePath(fileName);
- bool isFromCache;
- CDepFile* depFile = gCDepChecker->LoadFile(fileName, NULL, &isFromCache);
- BF_ASSERT(gCDepChecker->mIncludeStack.size() == 0);
- outString.clear();
- for (auto fileRef : depFile->mFilesReferenced)
- {
- if (!outString.empty())
- outString += "\n";
- outString += fileRef;
- }
- //OutputDebugStrF("%s Files Referenced: %s\n", fileNamePtr, outString.c_str());
- /*if ((_stricmp(fileNamePtr, "C:/Beef/IDE/mintest/cpp/test1.cpp") == 0) || (stricmp(fileNamePtr, "C:/Beef/IDE/mintest/cpp/test2.cpp") == 0))
- {
- //TODO: Temporary for testing
- BF_ASSERT(depFile->mFilesReferenced.size() > 1);
- }*/
-
- if (gPerfManagerPtr->IsRecording())
- {
- gPerfManagerPtr->StopRecording();
- gPerfManagerPtr->DbgPrint();
- }
- gCDepChecker->mAbort = false;
- gCDepChecker->mIncludeDirs.clear();
- gCDepChecker->mFilesVisited.clear();
- return outString.c_str();
- }
- BF_EXPORT int BF_CALLTYPE CDep_GetIncludePosition(const char* sourceFileName, const char* sourceContent, const char* headerFileNamePtr, const char* cArgs)
- {
- if (gCDepChecker == NULL)
- gCDepChecker = new CDepChecker();
- gPerfManagerPtr = &gCDepPerfManager;
- gCDepChecker->SetCArgs(cArgs);
-
- String fileName = sourceFileName;
- FixFilePath(fileName);
- String headerFileName = headerFileNamePtr;
- FixFilePath(headerFileName);
- gCDepChecker->mFindHeaderFileName = headerFileName;
- gCDepChecker->mFindHeaderIdx = -1;
- bool isFromCache;
- CDepFile* depFile = gCDepChecker->LoadFile(fileName, NULL, &isFromCache, sourceContent);
- BF_ASSERT(gCDepChecker->mIncludeStack.size() == 0);
-
- gCDepChecker->mAbort = false;
- gCDepChecker->mIncludeDirs.clear();
- gCDepChecker->mFilesVisited.clear();
- gCDepChecker->mFindHeaderFileName.clear();
-
- gCDepChecker->ClearCache();
- return gCDepChecker->mFindHeaderIdx;
- }
- void BfFullReportMemory();
- BF_EXPORT void BF_CALLTYPE CDep_ClearCache()
- {
- if (gCDepChecker != NULL)
- gCDepChecker->ClearCache();
- }
- BF_EXPORT void BF_CALLTYPE CDep_Shutdown()
- {
- delete gCDepChecker;
- gCDepChecker = NULL;
- }
- /*BF_EXPORT const char* BF_CALLTYPE CDep_DetermineFilesReferenced(const char* fileNamePtr, const char* cArgs)
- {
- for (int i = 0; i < 20; i++)
- {
- zCDep_DetermineFilesReferenced(fileNamePtr, cArgs);
- CDep_ClearCache();
- }
- return zCDep_DetermineFilesReferenced(fileNamePtr, cArgs);
- }
- */
|