| /* | |
| Copyright 2019 Alain Dargelas | |
| Licensed under the Apache License, Version 2.0 (the "License"); | |
| you may not use this file except in compliance with the License. | |
| You may obtain a copy of the License at | |
| http://www.apache.org/licenses/LICENSE-2.0 | |
| Unless required by applicable law or agreed to in writing, software | |
| distributed under the License is distributed on an "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| See the License for the specific language governing permissions and | |
| limitations under the License. | |
| */ | |
| /* | |
| * File: Cache.cpp | |
| * Author: alain | |
| * | |
| * Created on April 28, 2017, 9:32 PM | |
| */ | |
| #include <cstdio> | |
| #include <ctime> | |
| #include <sys/types.h> | |
| #include <sys/stat.h> | |
| #include <iostream> | |
| #include "SourceCompile/SymbolTable.h" | |
| #include "ErrorReporting/ErrorContainer.h" | |
| #include "Cache/Cache.h" | |
| #include "CommandLine/CommandLineParser.h" | |
| #include "flatbuffers/util.h" | |
| using namespace SURELOG; | |
| std::string ExecTimeStamp = std::string(__DATE__) + "-" + __TIME__; | |
| std::string Cache::getExecutableTimeStamp() { return ExecTimeStamp; } | |
| time_t Cache::get_mtime(const char* path) { | |
| struct stat statbuf; | |
| if (stat(path, &statbuf) == -1) { | |
| return -1; | |
| } | |
| return statbuf.st_mtime; | |
| } | |
| uint8_t* Cache::openFlatBuffers(std::string cacheFileName) { | |
| FILE* file = fopen(cacheFileName.c_str(), "rb"); | |
| if (file == NULL) return NULL; | |
| fseek(file, 0L, SEEK_END); | |
| unsigned int length = ftell(file); | |
| fseek(file, 0L, SEEK_SET); | |
| char* data = new char[length]; | |
| size_t l = fread(data, sizeof(char), length, file); | |
| fclose(file); | |
| if (length != l) { | |
| return NULL; | |
| } | |
| uint8_t* buffer_pointer = (uint8_t*)data; | |
| return buffer_pointer; | |
| } | |
| bool Cache::checkIfCacheIsValid(const SURELOG::CACHE::Header* header, | |
| std::string schemaVersion, | |
| std::string cacheFileName) { | |
| /* Schema version */ | |
| if (schemaVersion != header->m_flb_version()->c_str()) { | |
| return false; | |
| } | |
| /* Tool version */ | |
| if (CommandLineParser::getVersionNumber() != | |
| header->m_sl_version()->c_str()) { | |
| return false; | |
| } | |
| /* Timestamp Tool that created Cache vs tool date */ | |
| std::string execDate = getExecutableTimeStamp(); | |
| if (execDate != header->m_sl_date_compiled()->c_str()) { | |
| return false; | |
| } | |
| /* Timestamp Cache vs Orig File */ | |
| if (cacheFileName != "") { | |
| time_t ct = get_mtime(cacheFileName.c_str()); | |
| std::string fileName = header->m_file()->c_str(); | |
| time_t ft = get_mtime(fileName.c_str()); | |
| if (ft == -1) return false; | |
| if (ct == -1) return false; | |
| if (ct < ft) return false; | |
| } | |
| return true; | |
| } | |
| const flatbuffers::Offset<SURELOG::CACHE::Header> Cache::createHeader( | |
| flatbuffers::FlatBufferBuilder& builder, std::string schemaVersion, | |
| std::string origFileName) { | |
| auto fName = builder.CreateString(origFileName); | |
| auto sl_version = builder.CreateString(CommandLineParser::getVersionNumber()); | |
| auto sl_build_date = builder.CreateString(getExecutableTimeStamp()); | |
| auto sl_flb_version = builder.CreateString(schemaVersion); | |
| std::time_t t_result = std::time(nullptr); | |
| auto file_creation_date = builder.CreateString(std::to_string(t_result)); | |
| auto header = CACHE::CreateHeader(builder, sl_version, sl_flb_version, | |
| sl_build_date, file_creation_date, fName); | |
| return header; | |
| } | |
| bool Cache::saveFlatbuffers(flatbuffers::FlatBufferBuilder& builder, | |
| std::string cacheFileName) { | |
| const unsigned char* buf = builder.GetBufferPointer(); | |
| int size = builder.GetSize(); | |
| bool status = | |
| flatbuffers::SaveFile(cacheFileName.c_str(), (char*)buf, size, true); | |
| return status; | |
| } | |
| std::pair<flatbuffers::Offset< | |
| flatbuffers::Vector<flatbuffers::Offset<SURELOG::CACHE::Error>>>, | |
| flatbuffers::Offset< | |
| flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>>> | |
| Cache::cacheErrors(flatbuffers::FlatBufferBuilder& builder, | |
| SymbolTable& canonicalSymbols, | |
| ErrorContainer* errorContainer, SymbolTable* symbols, | |
| SymbolId subjectId) { | |
| std::vector<Error>& errors = errorContainer->getErrors(); | |
| std::vector<flatbuffers::Offset<SURELOG::CACHE::Error>> error_vec; | |
| for (unsigned int i = 0; i < errors.size(); i++) { | |
| Error& error = errors[i]; | |
| std::vector<Location>& locs = error.getLocations(); | |
| if (locs.size()) { | |
| bool matchSubject = false; | |
| for (unsigned int j = 0; j < locs.size(); j++) { | |
| if (locs[j].m_fileId == subjectId) { | |
| matchSubject = true; | |
| break; | |
| } | |
| } | |
| if (matchSubject) { | |
| std::vector<flatbuffers::Offset<SURELOG::CACHE::Location>> location_vec; | |
| for (unsigned int j = 0; j < locs.size(); j++) { | |
| Location& loc = locs[j]; | |
| SymbolId canonicalFileId = | |
| canonicalSymbols.registerSymbol(symbols->getSymbol(loc.m_fileId)); | |
| SymbolId canonicalObjectId = | |
| canonicalSymbols.registerSymbol(symbols->getSymbol(loc.m_object)); | |
| auto locflb = | |
| CACHE::CreateLocation(builder, canonicalFileId, loc.m_line, | |
| loc.m_column, canonicalObjectId); | |
| location_vec.push_back(locflb); | |
| } | |
| auto locvec = builder.CreateVector(location_vec); | |
| auto err = CACHE::CreateError(builder, locvec, error.getType()); | |
| error_vec.push_back(err); | |
| } | |
| } | |
| } | |
| /* Cache all the symbols */ | |
| for (auto itr = symbols->getSymbols().begin(); | |
| itr != symbols->getSymbols().end(); itr++) { | |
| canonicalSymbols.registerSymbol(*itr); | |
| } | |
| auto symbolVec = builder.CreateVectorOfStrings(canonicalSymbols.getSymbols()); | |
| auto errvec = builder.CreateVector(error_vec); | |
| return std::make_pair(errvec, symbolVec); | |
| } | |
| void Cache::restoreErrors( | |
| const flatbuffers::Vector<flatbuffers::Offset<SURELOG::CACHE::Error>>* | |
| errorsBuf, | |
| const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>* | |
| symbolsBuf, | |
| SymbolTable& canonicalSymbols, ErrorContainer* errorContainer, | |
| SymbolTable* symbols) { | |
| for (unsigned int i = 0; i < symbolsBuf->Length(); i++) { | |
| const std::string symbol = symbolsBuf->Get(i)->c_str(); | |
| canonicalSymbols.registerSymbol(symbol); | |
| } | |
| for (unsigned int i = 0; i < errorsBuf->Length(); i++) { | |
| auto errorFlb = errorsBuf->Get(i); | |
| std::vector<Location> locs; | |
| for (unsigned int j = 0; j < errorFlb->m_locations()->Length(); j++) { | |
| auto locFlb = errorFlb->m_locations()->Get(j); | |
| SymbolId translFileId = symbols->registerSymbol( | |
| canonicalSymbols.getSymbol(locFlb->m_fileId())); | |
| SymbolId translObjectId = symbols->registerSymbol( | |
| canonicalSymbols.getSymbol(locFlb->m_object())); | |
| Location loc(translFileId, locFlb->m_line(), locFlb->m_column(), | |
| translObjectId); | |
| locs.push_back(loc); | |
| } | |
| Error err((ErrorDefinition::ErrorType)errorFlb->m_errorId(), locs); | |
| errorContainer->addError(err, false); | |
| } | |
| } | |
| Cache::Cache() {} | |
| Cache::Cache(const Cache& orig) {} | |
| Cache::~Cache() {} |