blob: df296f1376f9095bd5b9b0865e61e21bfd9c6a64 [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: FileContent.cpp
* Author: alain
*
* Created on June 8, 2017, 8:22 PM
*/
#include "SourceCompile/SymbolTable.h"
#include "Design/TimeInfo.h"
#include "Design/DesignElement.h"
#include "Library/Library.h"
#include "ErrorReporting/ErrorContainer.h"
#include "Design/FileContent.h"
#include <queue>
#include <iostream>
#include <stack>
#include <string.h>
using namespace SURELOG;
FileContent::~FileContent() {}
NodeId FileContent::getRootNode() {
if (m_objects.size() == 0) {
return 0;
}
return m_objects[0].m_sibling;
}
SymbolId& FileContent::getFileId(NodeId id) { return m_objects[id].m_fileId; }
std::string FileContent::getFileName(NodeId id) {
SymbolId fileId = m_objects[id].m_fileId;
return m_symbolTable->getSymbol(fileId);
}
std::string FileContent::printObjects() {
std::string text;
NodeId index = 0;
if (m_library) text += "LIB: " + m_library->getName() + "\n";
std::string fileName = m_symbolTable->getSymbol(m_fileId);
if (strstr(fileName.c_str(), "builtin.sv"))
return "";
text += "FILE: " + fileName + "\n";
for (auto object : m_objects) {
text += object.print(m_symbolTable, index, GetDefinitionFile(index));
text += "\n";
index++;
}
return text;
}
unsigned int FileContent::getSize() { return m_objects.size(); }
std::string FileContent::printSubTree(NodeId uniqueId) {
std::string text;
for (auto s : collectSubTree(uniqueId)) {
text += s + "\n";
}
return text;
}
void FileContent::insertObjectLookup(std::string name, NodeId id,
ErrorContainer* errors) {
NameIdMap::iterator itr = m_objectLookup.find(name);
if (itr == m_objectLookup.end()) {
m_objectLookup.insert(std::make_pair(name, id));
} else {
Location loc(errors->getSymbolTable()->registerSymbol(getFileName(id)),
Line(id), 0, errors->getSymbolTable()->registerSymbol(name));
Location loc2(
errors->getSymbolTable()->registerSymbol(getFileName((*itr).second)),
Line((*itr).second), 0);
Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_DESIGN_UNIT, loc, loc2);
errors->addError(err);
}
}
ModuleDefinition* FileContent::getModuleDefinition(
const std::string& moduleName) {
ModuleNameModuleDefinitionMap::iterator itr =
m_moduleDefinitions.find(moduleName);
if (itr != m_moduleDefinitions.end()) {
return (*itr).second;
}
return NULL;
}
DesignComponent* FileContent::getComponentDefinition(
const std::string& componentName) {
DesignComponent* comp = (DesignComponent*)getModuleDefinition(componentName);
if (comp) return comp;
comp = (DesignComponent*)getProgram(componentName);
if (comp) return comp;
comp = (DesignComponent*)getClassDefinition(componentName);
if (comp) return comp;
return NULL;
}
Package* FileContent::getPackage(const std::string& name) {
PackageNamePackageDefinitionMultiMap::iterator itr =
m_packageDefinitions.find(name);
if (itr == m_packageDefinitions.end()) {
return NULL;
} else {
return (*itr).second;
}
}
Program* FileContent::getProgram(const std::string& name) {
ProgramNameProgramDefinitionMap::iterator itr =
m_programDefinitions.find(name);
if (itr == m_programDefinitions.end()) {
return NULL;
} else {
return (*itr).second;
}
}
ClassDefinition* FileContent::getClassDefinition(const std::string& name) {
ClassNameClassDefinitionMultiMap::iterator itr =
m_classDefinitions.find(name);
if (itr == m_classDefinitions.end()) {
return NULL;
} else {
return (*itr).second;
}
}
std::vector<std::string> FileContent::collectSubTree(NodeId index) {
std::vector<std::string> text;
text.push_back(
m_objects[index].print(m_symbolTable, index, GetDefinitionFile(index)));
if (m_objects[index].m_child) {
for (auto s : collectSubTree(m_objects[index].m_child)) {
text.push_back(" " + s);
}
}
if (m_objects[index].m_sibling) {
for (auto s : collectSubTree(m_objects[index].m_sibling)) {
text.push_back(s);
}
}
return text;
}
void FileContent::SetDefinitionFile(NodeId index, SymbolId def) {
m_definitionFiles.insert(std::make_pair(index, def));
}
SymbolId FileContent::GetDefinitionFile(NodeId index) {
auto itr = m_definitionFiles.find(index);
if (itr != m_definitionFiles.end()) return (*itr).second;
return 0;
}
VObject& FileContent::Object(NodeId index) { return m_objects[index]; }
NodeId FileContent::UniqueId(NodeId index) { return index; }
SymbolId& FileContent::Name(NodeId index) { return m_objects[index].m_name; }
NodeId& FileContent::Child(NodeId index) { return m_objects[index].m_child; }
NodeId& FileContent::Sibling(NodeId index) {
return m_objects[index].m_sibling;
}
NodeId& FileContent::Definition(NodeId index) {
return m_objects[index].m_definition;
}
NodeId& FileContent::Parent(NodeId index) { return m_objects[index].m_parent; }
VObjectType FileContent::Type(NodeId index) {
return (VObjectType)m_objects[index].m_type;
}
unsigned int& FileContent::Line(NodeId index) {
return m_objects[index].m_line;
}
NodeId FileContent::sl_get(NodeId parent, VObjectType type) {
if (!m_objects.size()) return 0;
if (parent > m_objects.size() - 1) return 0;
VObject current = Object(parent);
if (current.m_type == type) return parent;
NodeId id = current.m_child;
while (id) {
current = Object(id);
if (current.m_type == type) {
return id;
}
id = current.m_sibling;
}
return InvalidNodeId;
}
NodeId FileContent::sl_parent(NodeId parent, std::vector<VObjectType> types,
VObjectType& actualType) {
if (!m_objects.size()) return 0;
if (parent > m_objects.size() - 1) return 0;
VObject current = Object(parent);
for (auto type : types)
if (current.m_type == type) {
actualType = type;
return parent;
}
NodeId id = current.m_parent;
while (id) {
current = Object(id);
for (auto type : types)
if (current.m_type == type) {
actualType = type;
return id;
}
id = current.m_parent;
}
return InvalidNodeId;
}
NodeId FileContent::sl_parent(NodeId parent, VObjectType type) {
if (!m_objects.size()) return 0;
if (parent > m_objects.size() - 1) return 0;
VObject current = Object(parent);
if (current.m_type == type) return parent;
NodeId id = current.m_parent;
while (id) {
current = Object(id);
if (current.m_type == type) {
return id;
}
id = current.m_parent;
}
return InvalidNodeId;
}
std::vector<NodeId> FileContent::sl_get_all(NodeId parent, VObjectType type) {
std::vector<NodeId> objects;
if (!m_objects.size()) return objects;
if (parent > m_objects.size() - 1) return objects;
VObject current = Object(parent);
if (current.m_type == type) objects.push_back(parent);
NodeId id = current.m_child;
while (id) {
current = Object(id);
if (current.m_type == type) {
objects.push_back(id);
}
id = current.m_sibling;
}
return objects;
}
std::vector<NodeId> FileContent::sl_get_all(NodeId parent,
std::vector<VObjectType>& types) {
std::vector<NodeId> objects;
if (!m_objects.size()) return objects;
if (parent > m_objects.size() - 1) return objects;
VObject current = Object(parent);
for (auto type : types) {
if (current.m_type == type) {
objects.push_back(parent);
break;
}
}
NodeId id = current.m_child;
while (id) {
current = Object(id);
for (auto type : types) {
if (current.m_type == type) {
objects.push_back(id);
break;
}
}
id = current.m_sibling;
}
return objects;
}
NodeId FileContent::sl_collect(NodeId parent, VObjectType type) {
if (!m_objects.size()) return 0;
if (parent > m_objects.size() - 1) return 0;
VObject current = Object(parent);
if (current.m_type == type) return parent;
NodeId id = current.m_child;
while (id) {
NodeId idsub = sl_collect(id, type);
if (idsub != InvalidNodeId) {
return idsub;
}
current = Object(id);
if (current.m_type == type) {
return id;
}
id = current.m_sibling;
}
return InvalidNodeId;
}
std::vector<NodeId> FileContent::sl_collect_all(NodeId parent, VObjectType type,
bool first) {
std::vector<NodeId> objects;
if (!m_objects.size()) return objects;
if (parent > m_objects.size() - 1) return objects;
VObject current = Object(parent);
NodeId id = current.m_child;
if (!id) id = current.m_sibling;
if (!id) return objects;
std::stack<NodeId> stack;
stack.push(id);
while (stack.size()) {
id = stack.top();
stack.pop();
current = Object(id);
if (current.m_type == type) {
objects.push_back(id);
if (first) return objects;
}
if (current.m_sibling) stack.push(current.m_sibling);
if (current.m_child) stack.push(current.m_child);
}
return objects;
}
std::vector<NodeId> FileContent::sl_collect_all(NodeId parent,
std::vector<VObjectType>& types,
bool first) {
std::vector<NodeId> objects;
if (!m_objects.size()) return objects;
if (parent > m_objects.size() - 1) return objects;
VObject current = Object(parent);
NodeId id = current.m_child;
if (!id) id = current.m_sibling;
if (!id) return objects;
std::stack<NodeId> stack;
stack.push(id);
while (stack.size()) {
id = stack.top();
stack.pop();
current = Object(id);
// std::cout << "COLLECT:" << current.print (m_symbolTable, id,
// GetDefinitionFile(id)) << std::endl;
for (auto type : types) {
if (current.m_type == type) {
objects.push_back(id);
if (first) return objects;
break;
}
}
if (current.m_sibling) stack.push(current.m_sibling);
if (current.m_child) stack.push(current.m_child);
}
return objects;
}
NodeId FileContent::sl_collect(NodeId parent, VObjectType type,
VObjectType stopPoint) {
NodeId result = InvalidNodeId;
if (!m_objects.size()) return result;
if (parent > m_objects.size() - 1) return result;
VObject current = Object(parent);
NodeId id = current.m_child;
if (!id) id = current.m_sibling;
if (!id) return result;
std::stack<NodeId> stack;
stack.push(id);
while (stack.size()) {
id = stack.top();
stack.pop();
current = Object(id);
if (current.m_type == type) {
return id;
}
if (current.m_sibling) stack.push(current.m_sibling);
if (current.m_child) {
if (stopPoint != current.m_type)
if (current.m_child) stack.push(current.m_child);
}
}
return result;
}
std::vector<NodeId> FileContent::sl_collect_all(
NodeId parent, std::vector<VObjectType>& types,
std::vector<VObjectType>& stopPoints, bool first) {
std::vector<NodeId> objects;
if (!m_objects.size()) return objects;
if (parent > m_objects.size() - 1) return objects;
VObject current = Object(parent);
NodeId id = current.m_child;
if (!id) id = current.m_sibling;
if (!id) return objects;
std::stack<NodeId> stack;
stack.push(id);
while (stack.size()) {
id = stack.top();
stack.pop();
current = Object(id);
// std::cout << "COLLECT:" << current.print (m_symbolTable, id,
// GetDefinitionFile(id)) << std::endl;
for (auto type : types) {
if (current.m_type == type) {
objects.push_back(id);
if (first) return objects;
break;
}
}
if (current.m_sibling) stack.push(current.m_sibling);
if (current.m_child) {
if (stopPoints.size()) {
bool stop = false;
for (auto t : stopPoints) {
if (t == current.m_type) {
stop = true;
break;
}
}
if (!stop)
if (current.m_child) stack.push(current.m_child);
} else {
if (current.m_child) stack.push(current.m_child);
}
}
}
return objects;
}
bool FileContent::diffTree(std::string& diff, NodeId root, FileContent* oFc,
NodeId oroot) {
diff = "";
VObject current1 = Object(root);
NodeId id1 = current1.m_child;
if (!id1) id1 = current1.m_sibling;
VObject current2 = oFc->Object(oroot);
NodeId id2 = current2.m_child;
if (!id2) id2 = current2.m_sibling;
if ((id1 && (!id2)) || ((!id1) && id2)) return true;
std::stack<NodeId> stack1;
std::stack<NodeId> stack2;
stack1.push(id1);
stack2.push(id2);
while (stack1.size()) {
if (!stack2.size()) return true;
id1 = stack1.top();
id2 = stack2.top();
stack1.pop();
stack2.pop();
current1 = Object(id1);
current2 = oFc->Object(id2);
if (current1.m_type != current2.m_type) {
return true;
}
std::string symb1;
std::string symb2;
if (current1.m_name) symb1 = Name(id1);
if (current2.m_name) symb2 = oFc->Name(id2);
if (current1.m_name || current2.m_name)
if (symb1 != symb2) return true;
if (current1.m_sibling) stack1.push(current1.m_sibling);
if (current1.m_child) stack1.push(current1.m_child);
if (current2.m_sibling) stack2.push(current2.m_sibling);
if (current2.m_child) stack2.push(current2.m_child);
}
if (stack2.size()) return true;
return false;
}