--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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_