13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "symbolTable.h" 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_ci#include <fstream> 193af6ab5fSopenharmony_ci#include <iostream> 203af6ab5fSopenharmony_ci#include <util/helpers.h> 213af6ab5fSopenharmony_ci 223af6ab5fSopenharmony_cinamespace panda::es2panda::util { 233af6ab5fSopenharmony_ciconst std::string SymbolTable::FIRST_LEVEL_SEPERATOR = "|"; 243af6ab5fSopenharmony_ciconst std::string SymbolTable::SECOND_LEVEL_SEPERATOR = ";"; 253af6ab5fSopenharmony_ciconst size_t FUNCTION_ITEM_NUMBER = 3; 263af6ab5fSopenharmony_ciconst size_t MODULE_ITEM_NUMBER = 1; 273af6ab5fSopenharmony_ci 283af6ab5fSopenharmony_cibool SymbolTable::Initialize(int targetApiVersion, std::string targetApiSubVersion) 293af6ab5fSopenharmony_ci{ 303af6ab5fSopenharmony_ci targetApiVersion_ = targetApiVersion; 313af6ab5fSopenharmony_ci targetApiSubVersion_ = targetApiSubVersion; 323af6ab5fSopenharmony_ci if (!symbolTable_.empty() && !ReadSymbolTable(symbolTable_)) { 333af6ab5fSopenharmony_ci std::cerr << "Failed to open the symbol table file'" << std::endl; 343af6ab5fSopenharmony_ci return false; 353af6ab5fSopenharmony_ci } 363af6ab5fSopenharmony_ci 373af6ab5fSopenharmony_ci if (!dumpSymbolTable_.empty()) { 383af6ab5fSopenharmony_ci std::fstream fs; 393af6ab5fSopenharmony_ci fs.open(panda::os::file::File::GetExtendedFilePath(dumpSymbolTable_), 403af6ab5fSopenharmony_ci std::ios_base::out | std::ios_base::trunc); 413af6ab5fSopenharmony_ci if (!fs.is_open()) { 423af6ab5fSopenharmony_ci std::cerr << "Failed to create or open the output symbol table file '" 433af6ab5fSopenharmony_ci << dumpSymbolTable_ << "' during symbol table initialization." << std::endl 443af6ab5fSopenharmony_ci << "This error could be due to invalid file path, lack of write permissions, " 453af6ab5fSopenharmony_ci << "or the file being in use by another process." << std::endl; 463af6ab5fSopenharmony_ci return false; 473af6ab5fSopenharmony_ci } 483af6ab5fSopenharmony_ci fs.close(); 493af6ab5fSopenharmony_ci } 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_ci return true; 523af6ab5fSopenharmony_ci} 533af6ab5fSopenharmony_ci 543af6ab5fSopenharmony_civoid SymbolTable::ReadRecordHashFunctionNames(const std::string &recordName, const std::string &funcInternalName, 553af6ab5fSopenharmony_ci const std::string &specialFuncIndex) 563af6ab5fSopenharmony_ci{ 573af6ab5fSopenharmony_ci auto recordHashFunctionNames = originRecordHashFunctionNames_.find(recordName); 583af6ab5fSopenharmony_ci if (specialFuncIndex == "0") { 593af6ab5fSopenharmony_ci // 0: not anonymous, special or duplicate function 603af6ab5fSopenharmony_ci if (recordHashFunctionNames == originRecordHashFunctionNames_.end()) { 613af6ab5fSopenharmony_ci std::unordered_map<std::string, std::string> functionIndexNameMap {}; 623af6ab5fSopenharmony_ci originRecordHashFunctionNames_.insert({recordName, functionIndexNameMap}); 633af6ab5fSopenharmony_ci } 643af6ab5fSopenharmony_ci } else { 653af6ab5fSopenharmony_ci if (recordHashFunctionNames != originRecordHashFunctionNames_.end()) { 663af6ab5fSopenharmony_ci recordHashFunctionNames->second.insert({specialFuncIndex, funcInternalName}); 673af6ab5fSopenharmony_ci } else { 683af6ab5fSopenharmony_ci std::unordered_map<std::string, std::string> functionIndexNameMap {{specialFuncIndex, funcInternalName}}; 693af6ab5fSopenharmony_ci originRecordHashFunctionNames_.insert({recordName, functionIndexNameMap}); 703af6ab5fSopenharmony_ci } 713af6ab5fSopenharmony_ci } 723af6ab5fSopenharmony_ci} 733af6ab5fSopenharmony_ci 743af6ab5fSopenharmony_cibool SymbolTable::ReadSymbolTable(const std::string &symbolTable) 753af6ab5fSopenharmony_ci{ 763af6ab5fSopenharmony_ci std::ifstream ifs; 773af6ab5fSopenharmony_ci std::string line; 783af6ab5fSopenharmony_ci ifs.open(panda::os::file::File::GetExtendedFilePath(symbolTable)); 793af6ab5fSopenharmony_ci if (!ifs.is_open()) { 803af6ab5fSopenharmony_ci std::cerr << "Failed to open the symbol table file '" 813af6ab5fSopenharmony_ci << symbolTable << "' during symbol table reading." << std::endl 823af6ab5fSopenharmony_ci << "Please check if the file exists, the path is correct, " 833af6ab5fSopenharmony_ci << "and your program has the necessary permissions to access the file." << std::endl; 843af6ab5fSopenharmony_ci return false; 853af6ab5fSopenharmony_ci } 863af6ab5fSopenharmony_ci 873af6ab5fSopenharmony_ci while (std::getline(ifs, line)) { 883af6ab5fSopenharmony_ci auto itemList = GetStringItems(line, FIRST_LEVEL_SEPERATOR); 893af6ab5fSopenharmony_ci 903af6ab5fSopenharmony_ci if (itemList.size() == FUNCTION_ITEM_NUMBER) { 913af6ab5fSopenharmony_ci // read function info 923af6ab5fSopenharmony_ci struct OriginFunctionInfo info(&allocator_); 933af6ab5fSopenharmony_ci auto funcItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR); 943af6ab5fSopenharmony_ci auto classItems = GetStringItems(itemList[1], SECOND_LEVEL_SEPERATOR); 953af6ab5fSopenharmony_ci auto lexItems = GetStringItems(itemList[2], SECOND_LEVEL_SEPERATOR); 963af6ab5fSopenharmony_ci 973af6ab5fSopenharmony_ci info.recordName = funcItems[0].substr(0, funcItems[0].find_last_of(".")); 983af6ab5fSopenharmony_ci info.funcInternalName = funcItems[1]; 993af6ab5fSopenharmony_ci // 2: use the third element of the function as the hash of the function 1003af6ab5fSopenharmony_ci info.funcHash = funcItems[2]; 1013af6ab5fSopenharmony_ci 1023af6ab5fSopenharmony_ci // 2 is to process each class name and its corresponding hash value 1033af6ab5fSopenharmony_ci for (size_t i = 0; i < classItems.size(); i = i + 2) { 1043af6ab5fSopenharmony_ci info.classHash.insert(std::pair<std::string, std::string>(classItems[i], classItems[i + 1])); 1053af6ab5fSopenharmony_ci } 1063af6ab5fSopenharmony_ci // 3 is to process a complete lexical environment entry 1073af6ab5fSopenharmony_ci for (size_t i = 0; i < lexItems.size(); i = i + 3) { 1083af6ab5fSopenharmony_ci auto name = std::string(lexItems[i]); 1093af6ab5fSopenharmony_ci auto slot = std::atoi(std::string(lexItems[i + 1]).c_str()); 1103af6ab5fSopenharmony_ci auto type = std::atoi(std::string(lexItems[i + 2]).c_str()); 1113af6ab5fSopenharmony_ci info.lexenv.insert({slot, std::pair<std::string, int>(name, type)}); 1123af6ab5fSopenharmony_ci } 1133af6ab5fSopenharmony_ci 1143af6ab5fSopenharmony_ci originFunctionInfo_.insert(std::pair<std::string, OriginFunctionInfo>(info.funcInternalName, info)); 1153af6ab5fSopenharmony_ci if (util::Helpers::IsDefaultApiVersion(targetApiVersion_, targetApiSubVersion_)) { 1163af6ab5fSopenharmony_ci // index of function in its record's special function array 1173af6ab5fSopenharmony_ci std::string specialFuncIndex{funcItems[3]}; 1183af6ab5fSopenharmony_ci ReadRecordHashFunctionNames(info.recordName, info.funcInternalName, specialFuncIndex); 1193af6ab5fSopenharmony_ci } 1203af6ab5fSopenharmony_ci } else if (itemList.size() == MODULE_ITEM_NUMBER) { 1213af6ab5fSopenharmony_ci // read module info 1223af6ab5fSopenharmony_ci auto moduleItems = GetStringItems(itemList[0], SECOND_LEVEL_SEPERATOR); 1233af6ab5fSopenharmony_ci originModuleInfo_.insert(std::pair<std::string, std::string>(moduleItems[0], moduleItems[1])); 1243af6ab5fSopenharmony_ci } else { 1253af6ab5fSopenharmony_ci std::cerr << "Failed to read the symbol table line: '" << line 1263af6ab5fSopenharmony_ci << "' from the symbol table file '" << symbolTable << "' due to unrecognized format." << std::endl 1273af6ab5fSopenharmony_ci << "Please verify the format of the symbol table." << std::endl; 1283af6ab5fSopenharmony_ci } 1293af6ab5fSopenharmony_ci } 1303af6ab5fSopenharmony_ci return true; 1313af6ab5fSopenharmony_ci} 1323af6ab5fSopenharmony_ci 1333af6ab5fSopenharmony_civoid SymbolTable::FillSymbolTable(const std::stringstream &content) 1343af6ab5fSopenharmony_ci{ 1353af6ab5fSopenharmony_ci std::lock_guard<std::mutex> lock(m_); 1363af6ab5fSopenharmony_ci symbolTableContent_ << content.rdbuf(); 1373af6ab5fSopenharmony_ci} 1383af6ab5fSopenharmony_ci 1393af6ab5fSopenharmony_civoid SymbolTable::WriteSymbolTable() 1403af6ab5fSopenharmony_ci{ 1413af6ab5fSopenharmony_ci std::fstream fs; 1423af6ab5fSopenharmony_ci fs.open(panda::os::file::File::GetExtendedFilePath(dumpSymbolTable_), 1433af6ab5fSopenharmony_ci std::ios_base::app | std::ios_base::in); 1443af6ab5fSopenharmony_ci if (fs.is_open()) { 1453af6ab5fSopenharmony_ci fs << symbolTableContent_.str(); 1463af6ab5fSopenharmony_ci fs.close(); 1473af6ab5fSopenharmony_ci } 1483af6ab5fSopenharmony_ci} 1493af6ab5fSopenharmony_ci 1503af6ab5fSopenharmony_cistd::vector<std::string_view> SymbolTable::GetStringItems(std::string_view input, const std::string &separator) 1513af6ab5fSopenharmony_ci{ 1523af6ab5fSopenharmony_ci std::vector<std::string_view> items; 1533af6ab5fSopenharmony_ci size_t curPos = 0; 1543af6ab5fSopenharmony_ci size_t lastPos = 0; 1553af6ab5fSopenharmony_ci 1563af6ab5fSopenharmony_ci while ((curPos = input.find(separator, lastPos)) != std::string_view::npos) { 1573af6ab5fSopenharmony_ci auto token = input.substr(lastPos, curPos - lastPos); 1583af6ab5fSopenharmony_ci if (!token.empty()) { 1593af6ab5fSopenharmony_ci items.push_back(token); 1603af6ab5fSopenharmony_ci } 1613af6ab5fSopenharmony_ci lastPos = curPos + separator.size(); 1623af6ab5fSopenharmony_ci } 1633af6ab5fSopenharmony_ci 1643af6ab5fSopenharmony_ci auto tail = input.substr(lastPos); 1653af6ab5fSopenharmony_ci if (!tail.empty()) { 1663af6ab5fSopenharmony_ci items.push_back(tail); 1673af6ab5fSopenharmony_ci } 1683af6ab5fSopenharmony_ci 1693af6ab5fSopenharmony_ci return items; 1703af6ab5fSopenharmony_ci} 1713af6ab5fSopenharmony_ci} // namespace panda::es2panda::util