blob: 34d0d8994401262ff0e28dce506d78c16a7ac2d2 [file] [log] [blame]
/*
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() {}