| /* | |
| 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> | |
| 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; | |
| } |