diff --git a/compiler/back-ends/c++-gen/gen-any.c b/compiler/back-ends/c++-gen/gen-any.c index 757c693..e5e8ef6 100644 --- a/compiler/back-ends/c++-gen/gen-any.c +++ b/compiler/back-ends/c++-gen/gen-any.c @@ -216,7 +216,7 @@ void PrintCxxAnyHashInitRoutine PARAMS((src, hdr, mods, m, r), FILE* src _AND_ F ValueDef* vd; Type* t; BasicValue* bv; - char anyId[512]; + char anyId[513]; char* typeName = NULL; /* REN -- end */ diff --git a/compiler/back-ends/c-gen/gen-any.c b/compiler/back-ends/c-gen/gen-any.c index 2b3e1f6..09cde42 100644 --- a/compiler/back-ends/c-gen/gen-any.c +++ b/compiler/back-ends/c-gen/gen-any.c @@ -229,7 +229,7 @@ void PrintCAnyHashInitRoutine(FILE* src, FILE* hdr, ModuleList* mods, Module* m, ValueDef* vd; Type* t; BasicValue* bv; - char anyId[256]; + char anyId[257]; char* typeName = NULL; /* REN -- end */ diff --git a/compiler/core/asn_commentparser.cpp b/compiler/core/asn_commentparser.cpp index 65a8282..9c8aeb6 100644 --- a/compiler/core/asn_commentparser.cpp +++ b/compiler/core/asn_commentparser.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifndef _WIN32 #include #endif @@ -32,6 +33,28 @@ bool isFiltered(const ETypeComment& comment) return false; } +bool isFiltered(const EStructMemberComment& comment) +{ + if (!gPrivateSymbols && comment.iPrivate) + return true; + + if (comment.i64Deprecated && gi64NoDeprecatedSymbols) + { + if (gi64NoDeprecatedSymbols == 1) + return true; + else if (gi64NoDeprecatedSymbols >= comment.i64Deprecated) + return true; + } + + return false; +} + +std::string ltrimspace(const std::string& s) +{ + size_t start = s.find_first_not_of(" "); + return (start == std::string::npos) ? "" : s.substr(start); +} + std::string ltrim(const std::string& s) { size_t start = s.find_first_not_of(WHITESPACE); @@ -140,7 +163,7 @@ extern "C" } // std::set SORTIERT, das darf aber bei dem explode nicht sein! -std::vector explode(std::string const& s, char delim, const bool bSkipEmpty = true) +std::vector explode(std::string const& s, char delim, const bool bSkipEmpty = true, const bool bTrim = true) { std::vector result; std::istringstream iss(s); @@ -148,7 +171,7 @@ std::vector explode(std::string const& s, char delim, const bool bS for (std::string token; std::getline(iss, token, delim);) { // leere tokens auslassen, brauchen wir nicht - auto element = trim(token); + auto element = bTrim ? trim(token) : token; if (!bSkipEmpty || element.size()) result.push_back(element); } @@ -417,13 +440,16 @@ int EAsnStackElementFile::ProcessLine(const char* szModuleName, const char* szRa return 0; } + if (m_strModuleASN1Name.empty()) + m_strModuleASN1Name = trim(szLine); + if (szLine.length() >= 5) { std::string strBegin = szLine.substr(szLine.length() - 5); if (strBegin == "BEGIN") { EAsnStackElementModule* el = new EAsnStackElementModule(m_pParser); - el->SetModuleProperties(m_strModuleName.c_str(), m_strModuleName.c_str(), m_CollectComments); + el->SetModuleProperties(m_strModuleName.c_str(), m_strModuleName.c_str(), m_strModuleASN1Name.c_str(), m_CollectComments); m_CollectComments.clear(); m_pParser->m_stack.push_back(el); @@ -439,10 +465,11 @@ int EAsnStackElementFile::ProcessLine(const char* szModuleName, const char* szRa return 0; } -void EAsnStackElementModule::SetModuleProperties(const char* szTypeName, const char* szCategory, std::list& listComments) +void EAsnStackElementModule::SetModuleProperties(const char* szTypeName, const char* szCategory, const char* szASN1ModuleName, std::list& listComments) { m_ModuleComment.strTypeName_UTF8 = szTypeName; m_ModuleComment.strCategory_UTF8 = szCategory; + m_ModuleComment.m_strASN1ModuleName = szASN1ModuleName; convertCommentList(listComments, &m_ModuleComment); } @@ -722,6 +749,10 @@ int EAsnStackElementSequence::ProcessLine(const char* szModuleName, const char* convertMemberCommentList(m_CollectComments, &member); m_comment.mapMembers[strMember] = member; + if (!isFiltered(member)) + m_strFilteredFileContent += m_strRawSourceFileIncrement; + m_strRawSourceFileIncrement.clear(); + std::string strBasicType1 = ""; if (iter != tokens.end()) { @@ -800,11 +831,15 @@ int EAsnStackElementSequence::ProcessLine(const char* szModuleName, const char* strKey += m_comment.strTypeName_UTF8; gComments.mapSequences[strKey] = m_comment; + m_strFilteredFileContent += m_strRawSourceFileIncrement; + if (isFiltered(m_comment)) + { + m_strFilteredFileContent.clear(); state = EElementState::end_and_filtered; + } else { - m_strFilteredFileContent += m_strRawSourceFileIncrement; state = EElementState::end; } m_strRawSourceFileIncrement.clear(); @@ -911,59 +946,15 @@ int EAsnCommentParser::ParseFileForComments(FILE* fp, const char* szModuleName, fprintf(errFileG, "WARNING - EAsnCommentParser inconsistent file syntax\n"); else if (m_stack.size() == 1) { - std::string strFileName; - if (gszOutputPath) - strFileName = gszOutputPath; - strFileName += szModuleName; - - auto pFile = m_stack.back(); + // Put the filtered content into the map + // The files have now been filtered in a first iteration + // We need to clean the imports after having parsed all files if (gFilterASN1Files) { - if (pFile->m_strFilteredFileContent.empty()) - { -#ifdef _WIN32 - _unlink(strFileName.c_str()); -#else - unlink(strFileName.c_str()); -#endif - } - else - { - // Add lines at the end of the file which havenīt had a element association - pFile->m_strFilteredFileContent += pFile->m_strRawSourceFileIncrement; - FILE* filteredFile = nullptr; -#ifdef _WIN32 - errno_t err = fopen_s(&filteredFile, strFileName.c_str(), "w"); - if (err != 0) - filteredFile = NULL; -#else - filteredFile = fopen(strFileName.c_str(), "w"); -#endif - if (filteredFile) - { - if (type == UTF8WITHBOM) - { - unsigned char bom[] = {0xEF, 0xBB, 0xBF}; - fwrite(bom, sizeof(unsigned char), 3, filteredFile); - } - const auto& strData = pFile->m_strFilteredFileContent; - auto strElements = explode(strData, '\n', false); - for (auto& strElement : strElements) - { - if (strElement.length() > 4 && strElement.substr(0, 5) == "-- ~ " || strElement.length() == 4 && strElement.substr(0, 4) == "-- ~") - continue; - strElement += "\n"; - if (type == ASCII) - { - auto strASCII = AsnStringConvert::UTF8ToAscii(strElement.c_str()); - fwrite(strASCII.c_str(), sizeof(char), strASCII.length(), filteredFile); - } - else - fwrite(strElement.c_str(), sizeof(char), strElement.length(), filteredFile); - } - fclose(filteredFile); - } - } + auto pFile = m_stack.back(); + // Add lines at the end of the file which havenīt had a element association + pFile->m_strFilteredFileContent += pFile->m_strRawSourceFileIncrement; + m_FilteredFileContents.push_back(EFilteredAsnFile(szModuleName, pFile->m_strFilteredFileContent, type)); } } @@ -979,6 +970,185 @@ int EAsnCommentParser::ParseFileForComments(FILE* fp, const char* szModuleName, return 0; // NO Error } +class ImportSegment +{ +public: + ImportSegment(const std::string& strModuleText, const std::vector& strImports) + { + m_strModuleText = strModuleText; + m_strASN1ModuleName = trim(strModuleText.substr(5)); + m_strImports = strImports; + } + std::string m_strModuleText; + std::string m_strASN1ModuleName; + std::vector m_strImports; +}; + +std::string EAsnCommentParser::FilterImports(const std::string& strImports) +{ + // Separate it based on the " FROM ModuleName" + std::list imports; + + // Split the blob into the segments that define the imports per source + size_t lastPos = 0; + while (true) + { + auto posBegin = strImports.find("FROM ", lastPos); + if (posBegin == std::string::npos) + break; + auto posEnd = strImports.find_first_of("\n;", posBegin); + if (posEnd == std::string::npos) + posEnd = strImports.length(); + else + posEnd++; + auto strModule = strImports.substr(posBegin, posEnd - posBegin); + auto strImportedText = strImports.substr(lastPos, posBegin - lastPos); + auto strImportElements = explode(strImportedText, ',', false, false); + imports.push_back(ImportSegment(strModule, strImportElements)); + lastPos = posEnd; + } + + // Iterate over the imports and check which are filtered + for (auto& imp : imports) + { + // Get the comment module name (We use the filename, instead of the ASN1 Module name) + // So we need to find the internal module name (filename) based on the longer asn 1 module name + std::string strModuleName; + for (const auto& [strName, module] : gComments.mapModules) + { + if (module.m_strASN1ModuleName == imp.m_strASN1ModuleName) + { + // if the import module is filtered remove the whole import list -> removes the import statement in the end + if (isFiltered(module)) + imp.m_strImports.clear(); + strModuleName = strName; + break; + } + } + if (strModuleName.empty()) + { + // The system could not find the internal module name for the asn1 module name + assert(FALSE); + continue; + } + + // iterate over the imports and remove the ones that are filtered + auto iterImport = imp.m_strImports.begin(); + while (iterImport != imp.m_strImports.end()) + { + std::string strLookupName = strModuleName; + strLookupName += "::"; + strLookupName += trim(*iterImport); + + auto iterSequence = gComments.mapSequences.find(strLookupName); + if (iterSequence == gComments.mapSequences.end()) + { + assert(FALSE); + continue; + } + + if (isFiltered(iterSequence->second)) + iterImport = imp.m_strImports.erase(iterImport); + else + iterImport++; + } + } + + // now reassemle the import statements + std::string strResult; + for (auto& imp : imports) + { + if (imp.m_strImports.empty()) + continue; + std::string strFilteredImport; + for (const auto& imp2 : imp.m_strImports) + { + if (!strFilteredImport.empty()) + strFilteredImport += ","; + strFilteredImport += imp2; + } + if (!strFilteredImport.empty() && strFilteredImport.back() != ' ') + strFilteredImport += ' '; + strResult += ltrimspace(strFilteredImport); + strResult += imp.m_strModuleText; + } + + return strResult; +} + +void EAsnCommentParser::FilterFiles() +{ + if (!gFilterASN1Files) + return; + + for (const auto& filteredFile : m_FilteredFileContents) + { + std::string strFileName; + strFileName = gszOutputPath; + strFileName += filteredFile.m_strModuleName; + + if (filteredFile.m_strFileContent.empty()) + { +#ifdef _WIN32 + _unlink(strFileName.c_str()); +#else + unlink(strFileName.c_str()); +#endif + continue; + } + + FILE* targtFile = nullptr; +#ifdef _WIN32 + errno_t err = fopen_s(&targtFile, strFileName.c_str(), "w"); + if (err != 0) + targtFile = NULL; +#else + targtFile = fopen(strFileName.c_str(), "w"); +#endif + if (targtFile) + { + if (filteredFile.m_eFileType == UTF8WITHBOM) + { + unsigned char bom[] = {0xEF, 0xBB, 0xBF}; + fwrite(bom, sizeof(unsigned char), 3, targtFile); + } + + std::string strFileContent = filteredFile.m_strFileContent; + auto posBegin = strFileContent.find("\nIMPORTS"); + if (posBegin != std::string::npos) + { + posBegin += 8; + auto posEnd = strFileContent.find(";", posBegin); + if (posEnd != std::string::npos) + { + posEnd--; + size_t posLast = posEnd - posBegin; + auto strImports = strFileContent.substr(posBegin, posLast); + strImports = FilterImports(strImports); + strFileContent.replace(posBegin, posLast, strImports.c_str()); + } + } + + auto strElements = explode(strFileContent, '\n', false, false); + for (auto& strElement : strElements) + { + if ((strElement.length() > 4 && strElement.substr(0, 5) == "-- ~ ") || (strElement.length() == 4 && strElement.substr(0, 4) == "-- ~")) + continue; + + strElement += "\n"; + if (filteredFile.m_eFileType == ASCII) + { + auto strASCII = AsnStringConvert::UTF8ToAscii(strElement.c_str()); + fwrite(strASCII.c_str(), sizeof(char), strASCII.length(), targtFile); + } + else + fwrite(strElement.c_str(), sizeof(char), strElement.length(), targtFile); + } + fclose(targtFile); + } + } +} + int EAsnCommentParser::ProcessLine(const char* szModuleName, const char* szLine) { int iResult = 1; // error diff --git a/compiler/core/asn_commentparser.h b/compiler/core/asn_commentparser.h index 45d4cfc..4de5b28 100644 --- a/compiler/core/asn_commentparser.h +++ b/compiler/core/asn_commentparser.h @@ -106,9 +106,13 @@ class EModuleComment : public ETypeComment // These elements shall be filtered when logging (currently only in the typescript rose stubs) // The elements are added through @logfilter in the beginning of the file ; delimited std::vector strLogFilter; + // Helper to get the LogFilters from the set in c int iCounter = 0; + // The ASN1 Mdoule name (first line of the module) + std::string m_strASN1ModuleName; + private: // Contains the version if the version has been evaluated for the module (checks the comments for @added field values) long long m_i64ModuleVersion = -1; @@ -121,15 +125,38 @@ void convertCommentList(std::list& commentList, ETypeComment* pType class EAsnStackElement; +class EFilteredAsnFile +{ +public: + EFilteredAsnFile(const std::string& strModuleName, const std::string& strFileContent, const EFILETYPE eFileType) + { + m_strModuleName = strModuleName; + m_strFileContent = strFileContent; + m_eFileType = eFileType; + } + std::string m_strModuleName; + std::string m_strFileContent; + enum EFILETYPE m_eFileType; +}; + class EAsnCommentParser { public: + // Parses a single file for comments int ParseFileForComments(FILE* fp, const char* szModuleName, const enum EFILETYPE type); + // Handles the second step in filtering files (remove the imports) + void FilterFiles(); std::list m_stack; private: int ProcessLine(const char* szModuleName, const char* szLine); + std::string FilterImports(const std::string& strImports); + + // Filtering of files is a two step process + // In the first approach we filter all the elements that are flagged filtered + // In the second approach we filter all imports that point to a private or deprecated object + std::list m_FilteredFileContents; }; // Element on the Parser Stack @@ -175,6 +202,7 @@ class EAsnStackElementFile : public EAsnStackElement virtual int ProcessLine(const char* szModuleName, const char* szSourceLine, std::string& szLine, std::string& szComment, EElementState& state) override; std::string m_strModuleName; + std::string m_strModuleASN1Name; private: std::list m_CollectComments; @@ -191,7 +219,7 @@ class EAsnStackElementModule : public EAsnStackElement virtual int ProcessLine(const char* szModuleName, const char* szRawSourceLine, std::string& szLine, std::string& szComment, EElementState& state) override; - void SetModuleProperties(const char* szTypeName, const char* szCategory, std::list& listComments); + void SetModuleProperties(const char* szTypeName, const char* szCategory, const char* szASN1ModuleName, std::list& listComments); bool isModuleFiltered() const; diff --git a/compiler/core/asn_comments.cpp b/compiler/core/asn_comments.cpp index 1c82043..9bd6985 100644 --- a/compiler/core/asn_comments.cpp +++ b/compiler/core/asn_comments.cpp @@ -7,13 +7,18 @@ extern "C" { // Once evaluated this int64 contains the highest minor module version of all loaded modules long long glMaxMinorModuleVersion = -1; + EAsnCommentParser parser; int ParseFileForComments(FILE* fp, const char* szModuleName, const enum EFILETYPE type) { - EAsnCommentParser parser; return parser.ParseFileForComments(fp, szModuleName, type); } + void FilterFiles() + { + parser.FilterFiles(); + } + const char* GetFirstModuleLogFileFilter(const char* szModuleName) { if (!szModuleName) diff --git a/compiler/core/asn_comments.h b/compiler/core/asn_comments.h index d9543b2..f4d2e71 100644 --- a/compiler/core/asn_comments.h +++ b/compiler/core/asn_comments.h @@ -57,6 +57,7 @@ extern "C" // Parse for Comments extern int ParseFileForComments(FILE* fp, const char* szModuleName, const enum EFILETYPE type); + extern void FilterFiles(); // Get LogFilter Attributes (if any) call recurring until it returns 0 extern const char* GetFirstModuleLogFileFilter(const char* szModuleName); diff --git a/compiler/core/snacc.c b/compiler/core/snacc.c index 7e54448..4d3f0b9 100644 --- a/compiler/core/snacc.c +++ b/compiler/core/snacc.c @@ -191,7 +191,7 @@ int genVersionFile = FALSE; int genTSESMCode = FALSE; int gFilterASN1Files = FALSE; -char gszOutputPath[100] = {0}; +char gszOutputPath[_MAX_PATH] = {0}; #ifdef WIN_SNACC /* Deepak: 14/Feb/2003 */ #define main Win_Snacc_Main @@ -698,8 +698,8 @@ int main PARAMS((argc, argv), int argc _AND_ char** argv) case 'o': if (argv[currArg + 1] != NULL) { - strcpy_s(gszOutputPath, 100, argv[currArg + 1]); - getDirectoryWithDelimiterFromPath(gszOutputPath, 99); + strcpy_s(gszOutputPath, _MAX_PATH - 1, argv[currArg + 1]); + getDirectoryWithDelimiterFromPath(gszOutputPath, _MAX_PATH - 1); if (!createDirectories(gszOutputPath)) snacc_exit("Failed to create directory %s", gszOutputPath); currArg++; @@ -919,15 +919,13 @@ int main PARAMS((argc, argv), int argc _AND_ char** argv) // We have the folder path. We need to copy the esnacc_whitelist.txt nd the interfaceversion.txt { char szTarget[_MAX_PATH] = {0}; - if (gszOutputPath) - strcat_s(szTarget, _MAX_PATH - 1, gszOutputPath); + strcat_s(szTarget, _MAX_PATH - 1, gszOutputPath); strcat_s(szTarget, _MAX_PATH - 1, "interfaceversion.txt"); copy_file(szPath, szTarget); } { char szTarget[_MAX_PATH] = {0}; - if (gszOutputPath) - strcat_s(szTarget, _MAX_PATH - 1, gszOutputPath); + strcat_s(szTarget, _MAX_PATH - 1, gszOutputPath); strcat_s(szTarget, _MAX_PATH - 1, "esnacc_whitelist.txt"); strcpy_s(szPath, _MAX_PATH - 1, szDirectory); strcat_s(szPath, _MAX_PATH - 1, "esnacc_whitelist.txt"); @@ -953,6 +951,7 @@ int main PARAMS((argc, argv), int argc _AND_ char** argv) // If we are filtering we now just need to write the contents of the file parser if (gFilterASN1Files) { + FilterFiles(); free(allMods); printf("Now exiting...\n"); return 0; @@ -1251,17 +1250,18 @@ Module* ParseAsn1File(const char* fileName, short ImportFlag, int parseComments) return NULL; } unsigned char szFileType[3] = {0}; + size_t readBytes = 0; #ifdef _WIN32 #ifdef _MSC_VER - fread_s(szFileType, 3, sizeof(char), 3, fPtr); + readBytes = fread_s(szFileType, 3, sizeof(char), 3, fPtr); #else // MingW, Clang, GCC - fread(szFileType, sizeof(char), 3, fPtr); + readBytes = fread(szFileType, sizeof(char), 3, fPtr); #endif #else - fread(szFileType, sizeof(char), 3, fPtr); + readBytes = fread(szFileType, sizeof(char), 3, fPtr); #endif - if (szFileType[0] == 0xef && szFileType[1] == 0xbb && szFileType[2] == 0xbf) // UTF8 + if (readBytes == 3 && szFileType[0] == 0xef && szFileType[1] == 0xbb && szFileType[2] == 0xbf) // UTF8 fileType = UTF8WITHBOM; else { diff --git a/version.h b/version.h index 3761955..74cbf86 100644 --- a/version.h +++ b/version.h @@ -1,8 +1,8 @@ #ifndef VERSION_H #define VERSION_H -#define VERSION "6.0.13" -#define VERSION_RC 6, 0, 13 +#define VERSION "6.0.14" +#define VERSION_RC 6, 0, 14 #define RELDATE "13.09.2024" #endif // VERSION_H