From: jusung Date: Fri, 3 Mar 2023 02:17:07 +0000 (+0900) Subject: Support 'import' keyword X-Git-Tag: accepted/tizen/unified/20230420.153149~11 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=caebc9f226364dc6cbe94947e897bfce43b98b39;p=platform%2Fcore%2Fappfw%2Ftidl.git Support 'import' keyword Change-Id: I7f382e90717c6de66937675d680504d3ecc9620a Signed-off-by: jusung --- diff --git a/idlc/ast/parser.cc b/idlc/ast/parser.cc index 5f2991c6..a074863e 100644 --- a/idlc/ast/parser.cc +++ b/idlc/ast/parser.cc @@ -76,15 +76,24 @@ int Parser::GetVersion() const { } bool Parser::ParseFromFile(const std::string& path) { - std::ifstream inFile(path); + pr_.reset(new Preprocessor(path)); + if (pr_->Process() == false) { + pr_.reset(); + std::cerr << "[TIDL:Parser] error" << std::endl; + return false; + } + + std::ifstream inFile(pr_->GetInputPath()); std::string str((std::istreambuf_iterator(inFile)), std::istreambuf_iterator()); - path_ = path; - return Parse(str); + bool ret = Parse(str); + pr_.reset(); + + return ret; } void Parser::ReportError(const std::string& err, unsigned line) { - std::cerr << path_ << ":" << line << ": " << err << std::endl; + pr_->ReportError("[TIDL:Parser] error " + err, line); error_ = true; } diff --git a/idlc/ast/parser.h b/idlc/ast/parser.h index eba8211f..20fb6a11 100644 --- a/idlc/ast/parser.h +++ b/idlc/ast/parser.h @@ -22,6 +22,7 @@ #include #include "idlc/ast/document.h" +#include "idlc/ast/preprocessor.h" namespace tidl { @@ -47,13 +48,13 @@ class Parser { private: void* scanner_; std::shared_ptr doc_; - std::string path_; bool error_; bool beta_enable_; bool cion_enable_; bool mqtt_enable_; bool group_enable_; int ver_; + std::unique_ptr pr_; }; } // namespace tidl diff --git a/idlc/ast/preprocessor.cc b/idlc/ast/preprocessor.cc new file mode 100644 index 00000000..44dba0bb --- /dev/null +++ b/idlc/ast/preprocessor.cc @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "idlc/ast/preprocessor.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace tidl { + +Preprocessor::Preprocessor(const std::string& input) + : input_(input), has_import_(false) { +} + +bool Preprocessor::Process() { + if (HasImport() == false) + return true; + + size_t pos = input_.find_last_of("/\\"); + std::string folder = input_.substr(0, pos); + std::string file = input_.substr(pos + 1); + + has_import_ = true; + + std::string tmp_file = folder + "/.tidl_tmp_" + file; + std::ifstream src; + src.open(input_); + + std::ofstream dst; + dst.open(tmp_file); + + node_tree_ = std::make_shared(file, nullptr, file, 1); + node_list_.emplace_back(file); + + bool ret = GenTidl(&src, &dst, folder, file, node_tree_); + + src.close(); + dst.close(); + + input_ = tmp_file; + + return ret; +} + +bool Preprocessor::ExistNode(const std::string& file) { + for (auto node_name : node_list_) { + if (node_name == file) + return true; + } + return false; +} + +bool Preprocessor::GenTidl(std::ifstream *src, std::ofstream *dst, + const std::string& src_dir, const std::string& src_file, + std::shared_ptr node) { + int line_num = 0; + std::string line; + while (std::getline(*src, line)) { + line_num++; + std::string import_file = GetTidlFile(line); + + if (import_file.empty()) { + line += "\n"; + dst->write(line.c_str(), line.size()); + line_info_.emplace_back(line_num, node->parent_ == nullptr ? + std::make_shared(src_file, nullptr, src_file, line_num) : + node); + + } else if (!ExistNode(import_file)) { + std::ifstream import_src(src_dir + "/" + import_file); + if (!import_src.is_open()) { + std::cerr << "Unable to open " << import_file << std::endl; + return false; + } + + auto n = std::make_shared( + src_file, node, import_file, line_num); + node_list_.emplace_back(import_file); + if (!GenTidl(&import_src, dst, src_dir, import_file, n)) { + import_src.close(); + return false; + } + import_src.close(); + } + } + return true; +} + +std::string Preprocessor::GetTidlFile(std::string line) { + std::string keyword("import"); + std::string extension(".tidl>"); + + line.erase(std::remove_if(line.begin(), + line.end(), [](unsigned char x){ return std::isspace(x); }), line.end()); + + size_t pos = line.find("//"); + if (pos != std::string::npos) + line = line.substr(0, pos); + + pos = line.find(keyword); + if (pos != 0) + return {}; + + line = line.substr(keyword.length()); + + + pos = line.find(extension); + if (pos != line.length() - extension.length()) + return {}; + + pos = line.find('<'); + if (pos != 0) + return {}; + + return line.substr(1, line.length() - 2); +} + +bool Preprocessor::HasImport() { + std::ifstream stream(input_); + if (!stream.is_open()) + return false; + + std::string line; + while (std::getline(stream, line)) { + if (!GetTidlFile(line).empty()) { + stream.close(); + return true; + } + } + + stream.close(); + return false; +} + +Preprocessor::~Preprocessor() { + if (has_import_) + unlink(input_.c_str()); +} + +void Preprocessor::PrintError(std::shared_ptr node) { + if (node->parent_ != nullptr) { + PrintError(node->parent_); + std::cerr << "In file included from " << node->source_name_ << ":" << + std::to_string(node->import_line_) << std::endl; + } +} + +void Preprocessor::ReportError(const std::string& err, unsigned line) { + if (has_import_ == false) { + std::cerr << input_ << ":" << line << ": \t" << err << std::endl; + return; + } + + if (line <= 0 || line - 1 > line_info_.size()) { + std::cerr << input_ << ":" << line << ": " << err << std::endl; + return; + } + + auto info = line_info_[line - 1]; + auto node = info.second; + + if (node->parent_) { + std::cerr << std::endl; + PrintError(node); + } + + std::cerr << std::endl; + std::cerr << node->import_name_ << ":" << info.first << ": \t" << err << + std::endl << std::endl; +} + +std::string Preprocessor::GetInputPath() { + return input_; +} + +Preprocessor::NodeInfo::NodeInfo(std::string source_name, + std::shared_ptr parent, std::string import_name, + int import_line) : + source_name_(std::move(source_name)), parent_(parent), + import_name_(std::move(import_name)), import_line_(import_line) { +} +} // namespace tidl diff --git a/idlc/ast/preprocessor.h b/idlc/ast/preprocessor.h new file mode 100644 index 00000000..e4510fa3 --- /dev/null +++ b/idlc/ast/preprocessor.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef IDLC_PREPORCESSOR_H_ +#define IDLC_PREPORCESSOR_H_ + +#include +#include +#include + +namespace tidl { + +class Preprocessor { + private: + class NodeInfo { + public: + NodeInfo(std::string source_name, std::shared_ptr parent, + std::string import_name, int import_line); + std::string source_name_; + std::shared_ptr parent_; + std::string import_name_; + int import_line_; + }; + + public: + Preprocessor(const std::string& input); + ~Preprocessor(); + bool Process(); + std::string GetInputPath(); + void ReportError(const std::string& err, unsigned line); + void PrintError(std::shared_ptr node); + + private: + bool HasImport(); + bool GenTidl(std::ifstream *src, std::ofstream *dst, + const std::string& src_dir, const std::string& src_file, + std::shared_ptr node); + std::string GetTidlFile(std::string line); + bool ExistNode(const std::string& file); + + std::string input_; + bool has_import_ ; + std::string tmp_path_ ; + std::shared_ptr node_tree_; + std::string tmp_line_num_; + std::vector>> line_info_; + std::vector node_list_; +}; + +} // namespace tidl + +#endif // IDLC_PREPORCESSOR_H_ diff --git a/idlc/ast/tidlc.ll b/idlc/ast/tidlc.ll index 81ecc123..866ec32a 100644 --- a/idlc/ast/tidlc.ll +++ b/idlc/ast/tidlc.ll @@ -31,15 +31,15 @@ std::string values; %} -"/*" { comments += yytext; BEGIN(COMMENT); } -"*/"+\/ { comments += yytext; yylloc->step(); BEGIN(INITIAL); } -"*/" { comments += yytext; comments += "\n"; BEGIN(INITIAL); } -"*/"\n+ { comments += yytext; yylloc->step(); BEGIN(INITIAL); } -\n+ { comments += yytext; yylloc->lines(yyleng); } -([^*]\n)+|. { comments += yytext; yylloc->step(); } +("/*".*"*/")+\n { comments += yytext; yylloc->lines(1); yylloc->step(); BEGIN(INITIAL); } +"/*" { comments += yytext; yylloc->step(); BEGIN(COMMENT); } +"*/" { comments += yytext; yylloc->lines(1); yylloc->step(); comments += "\n"; BEGIN(INITIAL); } +"*/"\n { comments += yytext; yylloc->lines(1); yylloc->step(); BEGIN(INITIAL); } +\n { comments += yytext; yylloc->lines(1); } +[^\n] { comments += yytext;} <> { return 0; } -"//".*\n { comments += yytext; yylloc->step(); } +"//".*\n { comments += yytext; yylloc->lines(1); yylloc->step(); } "\"" { BEGIN(VALUE); } "\"" { diff --git a/tests/build_tests/CMakeLists.txt b/tests/build_tests/CMakeLists.txt index e60f5511..672daf84 100644 --- a/tests/build_tests/CMakeLists.txt +++ b/tests/build_tests/CMakeLists.txt @@ -105,6 +105,8 @@ SET(TIDL_GEN_SRCS DataPort_v2StubC.c Foo_v2ProxyC.c Foo_v2StubC.c + Import_v2ProxyC.c + Import_v2StubC.c ) ADD_CUSTOM_COMMAND(OUTPUT ${TIDL_GEN_SRCS} PRE_BUILD diff --git a/tests/build_tests/prebuild.sh b/tests/build_tests/prebuild.sh index 38ab9511..7a80e19d 100755 --- a/tests/build_tests/prebuild.sh +++ b/tests/build_tests/prebuild.sh @@ -16,6 +16,7 @@ FILES_V2[1]="Buffer_v2" FILES_V2[2]="Ex_v2" FILES_V2[3]="DataPort_v2" FILES_V2[4]="Foo_v2" +FILES_V2[5]="Import_v2" FILES_CION[0]="Message" FILES_CION[1]="Buffer" diff --git a/tests/build_tests/tidl/Import_v2.tidl b/tests/build_tests/tidl/Import_v2.tidl new file mode 100755 index 00000000..74e2521f --- /dev/null +++ b/tests/build_tests/tidl/Import_v2.tidl @@ -0,0 +1,13 @@ +protocol 2 + +import + +interface Message { + void NotifyCB(string sender, string msg) delegate; + + int Register(string name, NotifyCB cb); + void Unregister() async; + int Send(string msg); + [privilege = "http://tizen.org/privilege/alarm.set"] + int SendEnvelope(string name, map envelope_map); +} diff --git a/tests/build_tests/tidl/Struct_v2.tidl b/tests/build_tests/tidl/Struct_v2.tidl new file mode 100755 index 00000000..3aacc54e --- /dev/null +++ b/tests/build_tests/tidl/Struct_v2.tidl @@ -0,0 +1,9 @@ +protocol 2 + +struct Envelope { + map string_map; + set double_set; + list string_list; + array bundle_array; +} + diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 753e98c2..6c5e2a6e 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -26,6 +26,7 @@ SET(TIDLC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../idlc/ast/parser.cc ${CMAKE_CURRENT_SOURCE_DIR}/../../idlc/ast/attribute.cc ${CMAKE_CURRENT_SOURCE_DIR}/../../idlc/ast/enum.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../idlc/ast/preprocessor.cc ) ADD_DEFINITIONS("-DFULLVER=\"${FULLVER}\"")