Support 'import' keyword 24/289224/5
authorjusung <jusung07.son@samsung.com>
Fri, 3 Mar 2023 02:17:07 +0000 (11:17 +0900)
committerjusung <jusung07.son@samsung.com>
Tue, 14 Mar 2023 06:25:06 +0000 (15:25 +0900)
Change-Id: I7f382e90717c6de66937675d680504d3ecc9620a
Signed-off-by: jusung <jusung07.son@samsung.com>
idlc/ast/parser.cc
idlc/ast/parser.h
idlc/ast/preprocessor.cc [new file with mode: 0644]
idlc/ast/preprocessor.h [new file with mode: 0644]
idlc/ast/tidlc.ll
tests/build_tests/CMakeLists.txt
tests/build_tests/prebuild.sh
tests/build_tests/tidl/Import_v2.tidl [new file with mode: 0755]
tests/build_tests/tidl/Struct_v2.tidl [new file with mode: 0755]
tests/unit_tests/CMakeLists.txt

index 5f2991c63504bec87060b8d4e2613ede456b70bb..a074863e67541938541102eef98981af4db71fe4 100644 (file)
@@ -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<char>(inFile)),
       std::istreambuf_iterator<char>());
-  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;
 }
 
index eba8211f03c65b59f265ae59a6529d5dcdf50c23..20fb6a114d3355f1843423e968425a40c5d71107 100644 (file)
@@ -22,6 +22,7 @@
 #include <list>
 
 #include "idlc/ast/document.h"
+#include "idlc/ast/preprocessor.h"
 
 namespace tidl {
 
@@ -47,13 +48,13 @@ class Parser {
  private:
   void* scanner_;
   std::shared_ptr<Document> doc_;
-  std::string path_;
   bool error_;
   bool beta_enable_;
   bool cion_enable_;
   bool mqtt_enable_;
   bool group_enable_;
   int ver_;
+  std::unique_ptr<Preprocessor> pr_;
 };
 
 }  // namespace tidl
diff --git a/idlc/ast/preprocessor.cc b/idlc/ast/preprocessor.cc
new file mode 100644 (file)
index 0000000..44dba0b
--- /dev/null
@@ -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 <dirent.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cstring>
+#include <cctype>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <utility>
+
+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<NodeInfo>(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<NodeInfo> 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<NodeInfo>(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<NodeInfo>(
+          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<NodeInfo> 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<NodeInfo> 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 (file)
index 0000000..e4510fa
--- /dev/null
@@ -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 <memory>
+#include <string>
+#include <vector>
+
+namespace tidl {
+
+class Preprocessor {
+ private:
+  class NodeInfo {
+   public:
+     NodeInfo(std::string source_name, std::shared_ptr<NodeInfo> parent,
+         std::string import_name, int import_line);
+     std::string source_name_;
+     std::shared_ptr<NodeInfo> 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<NodeInfo> 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<NodeInfo> 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<NodeInfo> node_tree_;
+  std::string tmp_line_num_;
+  std::vector<std::pair<int, std::shared_ptr<NodeInfo>>> line_info_;
+  std::vector<std::string> node_list_;
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_PREPORCESSOR_H_
index 81ecc123bc57f1b3f48a56b6ad448d0bafc5899a..866ec32abc8471a4f65df20b1c8651fb2039f6ff 100644 (file)
   std::string values;
 %}
 
-"/*"                    { comments += yytext; BEGIN(COMMENT); }
-<COMMENT>"*/"+\/        { comments += yytext; yylloc->step(); BEGIN(INITIAL); }
-<COMMENT>"*/"           { comments += yytext; comments += "\n"; BEGIN(INITIAL); }
-<COMMENT>"*/"\n+        { comments += yytext; yylloc->step(); BEGIN(INITIAL); }
-<COMMENT>\n+            { comments += yytext; yylloc->lines(yyleng); }
-<COMMENT>([^*]\n)+|.    { comments += yytext; yylloc->step(); }
+("/*".*"*/")+\n         { comments += yytext; yylloc->lines(1); yylloc->step(); BEGIN(INITIAL); }
+"/*"                    { comments += yytext;  yylloc->step(); BEGIN(COMMENT); }
+<COMMENT>"*/"           { comments += yytext; yylloc->lines(1); yylloc->step(); comments += "\n"; BEGIN(INITIAL); }
+<COMMENT>"*/"\n         { comments += yytext; yylloc->lines(1); yylloc->step(); BEGIN(INITIAL); }
+<COMMENT>\n             { comments += yytext; yylloc->lines(1); }
+<COMMENT>[^\n]          { comments += yytext;}
 <COMMENT><<EOF>>        { return 0; }
 
-"//".*\n                { comments += yytext; yylloc->step(); }
+"//".*\n                { comments += yytext; yylloc->lines(1); yylloc->step(); }
 
 "\""                    { BEGIN(VALUE); }
 <VALUE>"\""             {
index e60f55118a5c1284eadc467b1782f01416aaf1e2..672daf841c9aef594428eb2e2fefffa7e22b1ff3 100644 (file)
@@ -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
index 38ab951178b365f0e841f4b2a7968429bde76cf6..7a80e19d5f318636e5ac24229f594473af1ae978 100755 (executable)
@@ -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 (executable)
index 0000000..74e2521
--- /dev/null
@@ -0,0 +1,13 @@
+protocol 2
+
+import <Struct_v2.tidl>
+
+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<string, Envelope> envelope_map);
+}
diff --git a/tests/build_tests/tidl/Struct_v2.tidl b/tests/build_tests/tidl/Struct_v2.tidl
new file mode 100755 (executable)
index 0000000..3aacc54
--- /dev/null
@@ -0,0 +1,9 @@
+protocol 2
+
+struct Envelope {
+  map<string, int> string_map;
+  set<double> double_set;
+  list<string> string_list;
+  array<bundle> bundle_array;
+}
+
index 753e98c25ea260a8906d64334dbcee1b8f72766c..6c5e2a6e8fbb84ffca68f8c56c40845a527ded04 100644 (file)
@@ -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}\"")