From 47c7372dad6371f4263c09f6ad7e499a7533007d Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 1 Feb 2018 16:26:35 +0900 Subject: [PATCH] Implement C Generator (Structure Part) Change-Id: I594485400ecee5791eba13c14a0fba2526b81abe Signed-off-by: Hwankyu Jhun --- idlc/c_gen/c_body_gen_base.cc | 1172 ++++++++++++++++++++++++++++++++++++++ idlc/c_gen/c_body_gen_base.h | 70 +++ idlc/c_gen/c_gen_base.cc | 223 +++++++- idlc/c_gen/c_gen_base.h | 34 ++ idlc/c_gen/c_header_gen_base.cc | 267 +++++++++ idlc/c_gen/c_header_gen_base.h | 53 ++ idlc/c_gen/c_proxy_body_gen.cc | 8 +- idlc/c_gen/c_proxy_body_gen.h | 5 +- idlc/c_gen/c_proxy_header_gen.cc | 8 +- idlc/c_gen/c_proxy_header_gen.h | 4 +- idlc/c_gen/c_stub_body_gen.cc | 8 +- idlc/c_gen/c_stub_body_gen.h | 4 +- idlc/c_gen/c_stub_header_gen.cc | 11 +- idlc/c_gen/c_stub_header_gen.h | 4 +- idlc/type.cc | 8 + idlc/type.h | 2 + 16 files changed, 1866 insertions(+), 15 deletions(-) create mode 100644 idlc/c_gen/c_body_gen_base.cc create mode 100644 idlc/c_gen/c_body_gen_base.h create mode 100644 idlc/c_gen/c_header_gen_base.cc create mode 100644 idlc/c_gen/c_header_gen_base.h diff --git a/idlc/c_gen/c_body_gen_base.cc b/idlc/c_gen/c_body_gen_base.cc new file mode 100644 index 0000000..7fb91d3 --- /dev/null +++ b/idlc/c_gen/c_body_gen_base.cc @@ -0,0 +1,1172 @@ +/* + * Copyright (c) 2018 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 + +#include "idlc/c_gen/c_body_gen_base.h" + +namespace tidl { + +CBodyGeneratorBase::CBodyGeneratorBase(std::shared_ptr doc) + : CGeneratorBase(doc) {} + +void CBodyGeneratorBase::GenStructures(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_STRUCTURE) + continue; + + const Structure &st = static_cast(*i); + GenStructure(stream, st); + for (auto& j : st.GetElements().GetElms()) { + auto& t = j->GetType(); + AddStructureFromType(t); + } + } + + for (auto& p : GetStructures()) { + const Structure& st = *p.second; + GenStructure(stream, st); + } +} + +void CBodyGeneratorBase::GenStructure(std::ofstream& stream, + const Structure& st) { + GenStructureDeclaration(stream, st); + GenStructureParcelTo(stream, st); + GenStructureParcelFrom(stream, st); + GenStructureConstructor(stream, st); + GenStructureDestructor(stream, st); + GenStructureCloner(stream, st); + GenStructureSetter(stream, st); + GenStructureGetter(stream, st); + GenStructureIterator(stream, st); +} + +void CBodyGeneratorBase::GenStructureDeclaration(std::ofstream& stream, + const Structure& st) { + const char block[] = + "struct $$_s {\n" \ + " rpc_port_parcelable_t parcelable;\n" \ + " $$" \ + "};\n"; + + stream << NLine(1); + stream << st.GetComments(); + + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + std::string str; + for (auto& i : st.GetElements().GetElms()) { + str += GetStringFromElementType(i->GetType()) + + " " + i->GetID() + ";"; + str += NLine(1); + } + return str; + } + ) + ); +} + +void CBodyGeneratorBase::GenStructureParcelTo(std::ofstream& stream, + const Structure& st) { + const char block[] = + "static void __$$_to(rpc_port_parcel_h parcel, void* data)\n" \ + "{\n" \ + " rpc_port_$$_h h = data;\n" \ + "\n" \ + " if (!parcel || !h) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return;\n" \ + " }\n" \ + "$$" \ + "}\n"; + + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + std::string str; + for (auto& i : st.GetElements().GetElms()) { + str += NLine(1); + str += GetParcelWriteString(i->GetID(), i->GetType()); + } + return str; + } + ) + ); +} + +void CBodyGeneratorBase::GenStructureParcelFrom(std::ofstream& stream, + const Structure& st) { + const char block[] = + "static void __$$_from(rpc_port_parcel_h parcel, void* data)\n" \ + "{\n" \ + " rpc_port_$$_h h = data;\n" \ + "\n" + " if (!parcel || !h) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return;\n" \ + " }\n" \ + "$$" \ + "}\n"; + + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + std::string str; + for (auto& i : st.GetElements().GetElms()) { + str += NLine(1); + str += GetParcelReadString(i->GetID(), i->GetType()); + } + return str; + } + ) + ); +} + +void CBodyGeneratorBase::GenStructureConstructor(std::ofstream& stream, + const Structure& st) { + const char block[] = + "int rpc_port_create_$$(rpc_port_$$_h* h)\n" \ + "{\n" \ + " struct $$_s* handle;\n" \ + "\n" \ + " if (!h) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return -1;\n" \ + " }\n" \ + "\n" \ + " handle = calloc(1, sizeof(struct $$_s));\n" \ + " if (!handle) {\n" \ + " LOGE(\"Out of memory\");\n" \ + " return -1;\n" \ + " }\n" \ + "\n" + " handle->parcelable.to = __$$_to;\n" \ + " handle->parcelable.from = __$$_from;\n" \ + "\n" + " *h = handle;\n" + "\n" + " return 0;\n" \ + "}\n"; + + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + } + ) + ); +} + +void CBodyGeneratorBase::GenStructureDestructor(std::ofstream& stream, + const Structure& st) { + const char block[] = + "int rpc_port_destroy_$$(rpc_port_$$_h h)\n" \ + "{\n" \ + " if (!h) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return -1;\n" \ + " }\n" \ + "$$" \ + "\n" \ + " free(h);\n" \ + "\n" \ + " return 0;\n" \ + "}\n"; + + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + std::string str; + for (auto& i : st.GetElements().GetElms()) { + str += NLine(1); + str += GetFinalizeString(i->GetID(), i->GetType()); + } + return str; + } + ) + ); +} + +void CBodyGeneratorBase::GenStructureSetter(std::ofstream& stream, + const Structure& st) { + const char block[] = + "int rpc_port_$$_$$_$$(rpc_port_$$_h h, $$ $$)\n" \ + "{\n" \ + " if ($$) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return -1;\n" \ + " }\n" \ + "$$" \ + "\n" \ + " return 0;\n" \ + "}\n"; + + for (auto& i : st.GetElements().GetElms()) { + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + if (i->GetType().ToString() == "list" || + i->GetType().ToString() == "array") + return "add"; + return "set"; + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + if (i->GetType().IsUserDefinedType()) + return GetParcelParamTypeString(i->GetType()); + + if (i->GetType().ToString() == "list" || + i->GetType().ToString() == "array") { + if (i->GetType().GetMetaType()->IsUserDefinedType() || + i->GetType().GetMetaType()->ToString() == "list" || + i->GetType().GetMetaType()->ToString() == "array") { + return GetParcelParamTypeString(*i->GetType().GetMetaType()); + } else { + return ConvertTypeToString(ParameterType::Direction::IN, + *i->GetType().GetMetaType()); + } + } + + return ConvertTypeToString(ParameterType::Direction::IN, + i->GetType()); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + if ((i->GetType().IsUserDefinedType() || + i->GetType().ToString() == "string" || + i->GetType().ToString() == "bundle") || + ((i->GetType().ToString() == "list" || + i->GetType().ToString() == "array") && + (i->GetType().GetMetaType()->IsUserDefinedType() || + i->GetType().GetMetaType()->ToString() == "list" || + i->GetType().GetMetaType()->ToString() == "array" || + i->GetType().GetMetaType()->ToString() == "string" || + i->GetType().GetMetaType()->ToString() == "bundle"))) + return "!h || !" + i->GetID(); + + return "!h"; + }, + [&]()->std::string { + std::string str; + str += NLine(1); + str += GetSetterString(i->GetID(), i->GetType()); + return str; + } + ) + ); + } +} + +void CBodyGeneratorBase::GenStructureGetter(std::ofstream& stream, + const Structure& st) { + const char block[] = + "int rpc_port_get_$$_$$(rpc_port_$$_h h, $$ $$)\n" \ + "{\n" \ + " if (!h || $$) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return -1;\n" \ + " }\n" \ + "$$" \ + "\n" \ + " return 0;\n" \ + "}\n"; + + for (auto& i : st.GetElements().GetElms()) { + if (i->GetType().ToString() == "list" || + i->GetType().ToString() == "array") + continue; + + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + if (i->GetType().IsUserDefinedType()) + return GetParcelParamTypeString(i->GetType()); + + return ConvertTypeToString(ParameterType::Direction::OUT, + i->GetType()); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + return "!" + i->GetID(); + }, + [&]()->std::string { + std::string str; + str += NLine(1); + str += GetGetterString(i->GetID(), i->GetType()); + return str; + } + ) + ); + } +} + +void CBodyGeneratorBase::GenStructureIterator(std::ofstream& stream, + const Structure& st) { + const char block[] = + "int rpc_port_foreach_$$_$$(rpc_port_$$_h h, " \ + "void (*callback)($$ $$, void* user_data), void* user_data)\n" \ + "{\n" \ + " if (!h || !callback) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return -1;\n" \ + " }\n" \ + "$$" \ + "\n" \ + " return 0;\n" \ + "}\n"; + + for (auto& i : st.GetElements().GetElms()) { + if (i->GetType().ToString() != "list" && + i->GetType().ToString() != "array") + continue; + + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + if (i->GetType().GetMetaType()->IsUserDefinedType() || + i->GetType().GetMetaType()->ToString() == "list" || + i->GetType().GetMetaType()->ToString() == "array") + return GetParcelParamTypeString(*i->GetType().GetMetaType()); + + return ConvertTypeToString(ParameterType::Direction::IN, + *i->GetType().GetMetaType()); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + std::string str; + str += NLine(1); + str += GetIteratorString(i->GetID(), i->GetType()); + return str; + } + ) + ); + } +} + +void CBodyGeneratorBase::GenStructureCloner(std::ofstream& stream, + const Structure& st) { + const char block[] = + "int rpc_port_clone_$$(rpc_port_$$_h h, rpc_port_$$_h* clone)\n" \ + "{\n" \ + " rpc_port_$$_h handle = NULL;\n" \ + "\n" \ + " if (!h || !clone) {\n" \ + " LOGE(\"Invalid parameter\");\n" \ + " return -1;\n" \ + " }\n" \ + "\n" \ + " rpc_port_create_$$(&handle);\n" \ + " if (!handle) {\n" \ + " LOGE(\"Failed to create $$ handle\");\n" \ + " return -1;\n" \ + " }\n" \ + "$$" \ + "\n" \ + " *clone = handle;\n" \ + "\n" \ + " return 0;\n" \ + "}\n"; + + stream << NLine(1); + stream << SmartIndent(GenTemplateString(block, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + std::string str; + for (auto& i : st.GetElements().GetElms()) { + str += NLine(1); + str += GetClonerString(i->GetID(), i->GetType()); + } + return str; + } + ) + ); +} + +std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type) { + if (type.IsUserDefinedType()) + return ""; + if (type.ToString() == "char") + return "byte"; + if (type.ToString() == "short") + return "int16"; + if (type.ToString() == "int") + return "int32"; + if (type.ToString() == "long") + return "int32"; + if (type.ToString() == "long long") + return "int64"; + if (type.ToString() == "list" || + type.ToString() == "array") + return "array_count"; + + return type.ToString(); +} + +std::string CBodyGeneratorBase::GetStringFromElementType(const BaseType& type) { + if (type.IsUserDefinedType()) + return "rpc_port_" + type.ToString() + "_h"; + if (type.ToString() == "list" || + type.ToString() == "array") + return "GList*"; + if (type.ToString() == "string") + return "char*"; + if (type.ToString() == "bundle") + return "bundle*"; + + return type.ToString(); +} + +std::string CBodyGeneratorBase::GetParcelWriteFunctionString( + const BaseType& type) { + std::string str = "rpc_port_parcel_write"; + std::string parcel_type = GetParcelTypeString(type); + if (parcel_type != "") + str += "_" + parcel_type; + + return str; +} + +std::string CBodyGeneratorBase::GetParcelWriteString(const std::string& id, + const BaseType& type) { + std::string str; + const char parcel[] = "$$(parcel, $$);\n"; + const char do_while[] = + "do {\n" \ + " GList* iter = $$;\n" + " while (iter) {\n" \ + " $$ value = iter->data;\n" \ + "\n" \ + " iter = g_list_next(iter);\n" \ + " if (!value) {\n" \ + " LOGW(\"Warning: value is NULL\");\n" \ + " continue;\n" \ + " }\n" \ + "\n" \ + " $$" \ + " }\n" \ + "} while (0);\n"; + + str += GenTemplateString(parcel, + [&]()->std::string { + return GetParcelWriteFunctionString(type); + }, + [&]()->std::string { + if (type.IsUserDefinedType()) + return "&h->" + id + ", h->" + id; + if (type.ToString() == "list") + return "g_list_length(h->" + id + ")"; + return "h->" + id; + } + ); + + if (type.ToString() == "list" || + type.ToString() == "array") { + str += GenTemplateString(do_while, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return GetParcelParamTypeString(*type.GetMetaType()); + }, + [&]()->std::string { + return GenTemplateString(parcel, + [&]()->std::string { + return GetParcelWriteFunctionString(type); + }, + [&]()->std::string { + if (type.GetMetaType()->IsUserDefinedType() || + type.GetMetaType()->ToString() == "list" || + type.GetMetaType()->ToString() == "array") + return "&value->parcelable, value"; + if (type.GetMetaType()->ToString() == "string" || + type.GetMetaType()->ToString() == "bundle") + return "value"; + + return "*value"; + } + ); + } + ); + } + + return str; +} + +std::string CBodyGeneratorBase::GetParcelReadFunctionString( + const BaseType& type) { + std::string str = "rpc_port_parcel_read"; + std::string parcel_type = GetParcelTypeString(type); + if (parcel_type != "") + str += "_" + parcel_type; + + return str; +} + +std::string CBodyGeneratorBase::GetParcelReadString(const std::string& id, + const BaseType& type) { + std::string str; + const char parcel[] = "$$(parcel, $$)\n"; + const char if_statement_with_braces[] = + "if ($$) {\n" \ + " $$" \ + "}\n"; + const char do_while[] = + "do {\n" \ + " int len = 0;\n" \ + "\n" \ + " $$" \ + " for (int i = 0; i < len; i++) {\n" \ + " $$ value = NULL;\n" \ + "\n" \ + " $$" \ + " $$ = g_list_append($$, value);\n" \ + " }\n" \ + "} while (0);\n"; + + if (type.ToString() != "list" && + type.ToString() != "array") { + str += GenTemplateString(parcel, + [&]()->std::string { + return GetParcelReadFunctionString(type); + }, + [&]()->std::string { + if (type.IsUserDefinedType()) + return "&h->" + id + "h->" + id; + return "&h->" + id; + } + ); + } else { + str += GenTemplateString(do_while, + [&]()->std::string { + return GenTemplateString(parcel, + [&]()->std::string { + return GetParcelReadFunctionString(type); + }, + [&]()->std::string { + return "&len"; + } + ); + }, + [&]()->std::string { + return GetParcelParamTypeString(*type.GetMetaType()); + }, + [&]()->std::string { + std::string s; + + if (type.GetMetaType()->IsUserDefinedType() || + type.GetMetaType()->ToString() == "list" || + type.GetMetaType()->ToString() == "array") { + s += GetConstructorString(*type.GetMetaType(), "value"); + s += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!value"; + }, + [&]()->std::string { + std::string ss; + ss += "LOGE(\"Failed to create handle\");" + NLine(1); + ss += "return;" + NLine(1); + return ss; + } + ); + s += NLine(1); + s += GenTemplateString(parcel, + [&]()->std::string { + return GetParcelReadFunctionString(*type.GetMetaType()); + }, + [&]()->std::string { + return "&value->parcelable, value"; + } + ); + } else if (type.GetMetaType()->ToString() == "string" || + type.GetMetaType()->ToString() == "bundle") { + s += GenTemplateString(parcel, + [&]()->std::string { + return GetParcelReadFunctionString(*type.GetMetaType()); + }, + [&]()->std::string { + return "&value"; + } + ); + } else { + s += "value = calloc(1, sizeof(*value));" + NLine(1); + s += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!value"; + }, + [&]()->std::string { + std::string ss; + ss += "LOGE(\"Out of memory\");" + NLine(1); + ss += "return;" + NLine(1); + return ss; + } + ); + s += NLine(1); + s += GenTemplateString(parcel, + [&]()->std::string { + return GetParcelReadFunctionString(*type.GetMetaType()); + }, + [&]()->std::string { + return "value"; + } + ); + } + + return s; + }, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return "h->" + id; + } + ); + } + + return str; +} + +std::string CBodyGeneratorBase::GetFinalizeString(const std::string& id, + const BaseType& type) { + std::string str; + const char if_statement[] = + "if ($$)\n" \ + " $$"; + const char do_while[] = + "do {\n" \ + " GList* iter = $$;\n" \ + " while (iter) {\n" \ + " $$ value = iter->data;\n" \ + " $$" \ + " iter = g_list_next(iter);\n" \ + " }\n" \ + " g_list_free($$);\n" \ + "} while (0);\n"; + + if (!type.IsUserDefinedType() && + type.ToString() != "list" && + type.ToString() != "string" && + type.ToString() != "bundle") + return str; + + if (type.ToString() != "list") { + str += GenTemplateString(if_statement, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return GetDestructorString(type, "h->" + id); + } + ); + } else { + str += GenTemplateString(do_while, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return GetParcelParamTypeString(*type.GetMetaType()); + }, + [&]()->std::string { + return GenTemplateString(if_statement, + [&]()->std::string { + return "value"; + }, + [&]()->std::string { + return GetDestructorString(*type.GetMetaType(), "value"); + } + ); + }, + [&]()->std::string { + return "h->" + id; + } + ); + } + + return str; +} + +std::string CBodyGeneratorBase::GetSetterString(const std::string& id, + const BaseType& type) { + std::string str; + const char setter[] = "$$ = $$;\n"; + const char if_statement_with_braces[] = + "if ($$) {\n" \ + " $$" \ + "}\n"; + const char do_while[] = + "do {\n" \ + " $$ value;\n" \ + "\n" \ + " value = calloc(1, sizeof(*value));\n" \ + " $$" \ + " $$ = g_list_append($$, value);\n" \ + "} while (0);\n"; + + if (type.IsUserDefinedType() || + type.ToString() == "string" || + type.ToString() == "bundle") { + str += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + std::string s; + s += GetDestructorString(type, "h->" + id); + s += GetSetterString("h->" + id, "NULL"); + return s; + } + ); + str += NLine(1); + str += GetSetterString(type, "h->" + id, id); + str += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!h->" + id; + }, + [&]()->std::string { + std::string s; + s += "LOGE(\"Failed to duplicate data\");" + NLine(1); + s += "return -1;" + NLine(1); + return s; + } + ); + } else if (type.ToString() == "list" || + type.ToString() == "array") { + if (type.GetMetaType()->IsUserDefinedType() || + type.GetMetaType()->ToString() == "string" || + type.GetMetaType()->ToString() == "bundle" || + type.GetMetaType()->ToString() == "list" || + type.GetMetaType()->ToString() == "array") { + str += GenTemplateString(setter, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return "g_list_append(h->" + id + ", " + id + ")"; + } + ); + } else { + str += GenTemplateString(do_while, + [&]()->std::string { + return GetParcelParamTypeString(*type.GetMetaType()); + }, + [&]()->std::string { + std::string s; + s += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!value"; + }, + [&]()->std::string { + std::string s; + s += "LOGE(\"Out of memory\");" + NLine(1); + s += "return -1;" + NLine(1); + return s; + } + ); + s += NLine(1); + s += GetSetterString("*value", id); + return s; + }, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return "h->" + id; + } + ); + } + } else { + str += GetSetterString(type, "h->" + id, id); + } + + return str; +} + +std::string CBodyGeneratorBase::GetGetterString(const std::string& id, + const BaseType& type) { + std::string str; + const char if_statement_with_braces[] = + "if ($$) {\n" \ + " $$" \ + "}\n"; + + if (type.IsUserDefinedType() || + type.ToString() == "string" || + type.ToString() == "bundle") { + str += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!h->" + id; + }, + [&]()->std::string { + std::string s; + s += "LOGE(\"Invalid parameter: h->" + id + + " is NULL\");" + NLine(1); + s += "return -1;" + NLine(1); + return s; + } + ); + str += NLine(1); + } + + if (type.IsUserDefinedType()) { + str += GetSetterString(type, id, "h->" + id); + } else { + str += GetSetterString(type, "*" + id, "h->" + id); + } + + if (type.IsUserDefinedType() || + type.ToString() == "string" || + type.ToString() == "bundle") { + str += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!" + id; + }, + [&]()->std::string { + std::string s; + s += "LOGE(\"Failed to duplicate " + id + "\");" + NLine(1); + s += "return -1;" + NLine(1); + return s; + } + ); + } + + return str; +} + +std::string CBodyGeneratorBase::GetIteratorString(const std::string& id, + const BaseType& type) { + std::string str; + const char iterator[] = + "do {\n" \ + " GList* iter = $$;\n" \ + " while (iter) {\n" \ + " $$ value = iter->data;\n" \ + "\n" \ + " iter = g_list_next(iter);\n" \ + " if (!value) {\n" \ + " LOGW(\"Warning: value is NULL\");\n" \ + " continue;\n" \ + " }\n" \ + "\n" \ + " callback($$, user_data);\n" \ + " }\n" \ + "} while (0);\n"; + + str += GenTemplateString(iterator, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return GetParcelParamTypeString(*type.GetMetaType()); + }, + [&]()->std::string { + if (type.GetMetaType()->IsUserDefinedType() || + type.GetMetaType()->ToString() == "list" || + type.GetMetaType()->ToString() == "array" || + type.GetMetaType()->ToString() == "string" || + type.GetMetaType()->ToString() == "bundle") + return "value"; + + return "*value"; + } + ); + + return str; +} + +std::string CBodyGeneratorBase::GetClonerString(const std::string& id, + const BaseType& type) { + std::string str; + const char if_statement_with_braces[] = + "if ($$) {\n" \ + " $$" \ + "}\n"; + const char do_while[] = + "do {\n" \ + " GList* iter = $$;\n" \ + " while (iter) {\n" \ + " $$ new_value;\n" \ + " $$ value = iter->data;\n" \ + "\n" \ + " if (!value) {\n" \ + " LOGE(\"Error: value is NULL\");\n" \ + " break;\n" \ + " }\n" \ + "\n" \ + " $$" \ + " $$ = g_list_append($$, new_value);\n" \ + " iter = g_list_next(iter);\n" \ + " }\n" \ + "} while (0);\n"; + + if (type.IsUserDefinedType() || + type.ToString() == "string" || + type.ToString() == "bundle") { + str += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + std::string s; + s += GetSetterString(type, "handle->" + id, "h->" + id); + s += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!handle->" + id; + }, + [&]()->std::string { + std::string ss; + ss += "LOGE(\"Failed to duplicate h->" + id + "\");" + + NLine(1); + ss += "return -1;" + NLine(1); + return ss; + } + ); + return s; + } + ); + } else if (type.ToString() == "list" || + type.ToString() == "array") { + str += GenTemplateString(do_while, + [&]()->std::string { + return "h->" + id; + }, + [&]()->std::string { + return GetParcelParamTypeString(*type.GetMetaType()); + }, + [&]()->std::string { + return GetParcelParamTypeString(*type.GetMetaType()); + }, + [&]()->std::string { + std::string s; + if (type.GetMetaType()->IsUserDefinedType() || + type.GetMetaType()->ToString() == "list" || + type.GetMetaType()->ToString() == "array" || + type.GetMetaType()->ToString() == "string" || + type.GetMetaType()->ToString() == "bundle") { + s += GetSetterString(*type.GetMetaType(), + "new_value", "value"); + s += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!new_value"; + }, + [&]()->std::string { + std::string ss; + ss += "LOGE(\"Failed to duplicate value\");" + + NLine(1); + ss += "return -1;" + NLine(1); + return ss; + } + ); + } else { + s += "new_value = calloc(1, sizeof(*new_value));" + NLine(1); + s += GenTemplateString(if_statement_with_braces, + [&]()->std::string { + return "!new_value"; + }, + [&]()->std::string { + std::string tmp; + tmp += "LOGE(\"Out of memory\");" + NLine(1); + tmp += "return -1;" + NLine(1); + return tmp; + } + ); + s += NLine(1); + s += GetSetterString(*type.GetMetaType(), + "*new_value", "value"); + } + s += NLine(1); + return s; + }, + [&]()->std::string { + return "handle->" + id; + }, + [&]()->std::string { + return "handle->" + id; + } + ); + } else { + str += GetSetterString(type, "handle->" + id, "h->" + id); + } + + return str; +} + +std::string CBodyGeneratorBase::GetDestructorString(const BaseType& type, + const std::string& value) { + std::string str; + + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + str += "rpc_port_destroy_" + GetFullNameFromType(type) + + "(" + value + ");" + NLine(1); + } else if (type.ToString() == "bundle") { + str += "bundle_free(" + value + ");" + NLine(1); + } else { + str += "free(" + value + ");" + NLine(1); + } + + return str; +} + +std::string CBodyGeneratorBase::GetConstructorString(const BaseType& type, + const std::string& value) { + std::string str; + str += "rpc_port_create_" + GetFullNameFromType(type) + + "(&" + value + ");" + NLine(1); + return str; +} + +std::string CBodyGeneratorBase::GetSetterString(const BaseType& type, + const std::string& lvalue, + const std::string& rvalue) { + std::string str; + + if (type.IsUserDefinedType() || + type.ToString() == "list" || + type.ToString() == "array") { + str += "rpc_port_clone_" + GetFullNameFromType(type) + + "(" + rvalue + ", &" + lvalue +");" + NLine(1); + } else if (type.ToString() == "string") { + str += lvalue + " = strdup(" + rvalue + ");" + NLine(1); + } else if (type.ToString() == "bundle") { + str += lvalue + " = bundle_dup(" + rvalue + ");" + NLine(1); + } else { + str += GetSetterString(lvalue, rvalue); + } + + return str; +} + +std::string CBodyGeneratorBase::GetSetterString(const std::string& lvalue, + const std::string& rvalue) { + std::string str; + str += lvalue + " = " + rvalue + ";" + NLine(1); + return str; +} + +void CBodyGeneratorBase::GenIncludeHeader(std::ofstream& stream) { + std::string str; + str += "#include \""; + str += FileName.substr(0, FileName.length() - 2); + str += ".h\""; + stream << NLine(1); + stream << str; + stream << NLine(1); +} + +void CBodyGeneratorBase::GenLogTag(std::ofstream& stream, + const std::string& log_tag) { + const char format[] = + "#ifdef LOG_TAG\n" \ + "#undef LOG_TAG\n" \ + "#endif\n" \ + "\n" \ + "#define LOG_TAG \"$$\"\n"; + + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + return log_tag; + } + ); +} + +} // namespace tidl diff --git a/idlc/c_gen/c_body_gen_base.h b/idlc/c_gen/c_body_gen_base.h new file mode 100644 index 0000000..0786be2 --- /dev/null +++ b/idlc/c_gen/c_body_gen_base.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 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_C_GEN_C_BODY_GEN_BASE_H_ +#define IDLC_C_GEN_C_BODY_GEN_BASE_H_ + +#include +#include +#include + +#include "idlc/c_gen/c_gen_base.h" + +namespace tidl { + +class CBodyGeneratorBase : public CGeneratorBase { + public: + explicit CBodyGeneratorBase(std::shared_ptr doc); + virtual ~CBodyGeneratorBase() = default; + + void GenStructures(std::ofstream& stream); + void GenIncludeHeader(std::ofstream& stream); + void GenLogTag(std::ofstream& stream, const std::string& log_tag); + + private: + void GenStructure(std::ofstream& stream, const Structure& st); + void GenStructureDeclaration(std::ofstream& stream, const Structure& st); + void GenStructureParcelTo(std::ofstream& stream, const Structure& st); + void GenStructureParcelFrom(std::ofstream& stream, const Structure& st); + void GenStructureConstructor(std::ofstream& stream, const Structure& st); + void GenStructureDestructor(std::ofstream& stream, const Structure& st); + void GenStructureSetter(std::ofstream& stream, const Structure& st); + void GenStructureGetter(std::ofstream& stream, const Structure& st); + void GenStructureIterator(std::ofstream& stream, const Structure& st); + void GenStructureCloner(std::ofstream& stream, const Structure& st); + + private: + std::string GetStringFromElementType(const BaseType& type); + std::string GetParcelTypeString(const BaseType& type); + std::string GetParcelWriteFunctionString(const BaseType& type); + std::string GetParcelWriteString(const std::string& id, const BaseType& type); + std::string GetParcelReadFunctionString(const BaseType& type); + std::string GetParcelReadString(const std::string& id, const BaseType& type); + std::string GetFinalizeString(const std::string& id, const BaseType& type); + std::string GetSetterString(const std::string& id, const BaseType& type); + std::string GetGetterString(const std::string& id, const BaseType& type); + std::string GetIteratorString(const std::string& id, const BaseType& type); + std::string GetClonerString(const std::string& id, const BaseType& type); + std::string GetSetterString(const BaseType& type, const std::string& lvalue, + const std::string& rvalue); + std::string GetSetterString(const std::string& lvalue, const std::string& rvalue); + std::string GetDestructorString(const BaseType& type, const std::string& value); + std::string GetConstructorString(const BaseType& type, const std::string& value); +}; + +} // namespace tidl + +#endif // IDLC_C_GEN_C_BODY_GEN_BASE_H_ diff --git a/idlc/c_gen/c_gen_base.cc b/idlc/c_gen/c_gen_base.cc index 5d2780e..6fc62d3 100644 --- a/idlc/c_gen/c_gen_base.cc +++ b/idlc/c_gen/c_gen_base.cc @@ -14,13 +14,234 @@ * limitations under the License. */ +#include +#include #include +#include #include "idlc/c_gen/c_gen_base.h" namespace tidl { CGeneratorBase::CGeneratorBase(std::shared_ptr doc) - : Generator(doc) {} + : Generator(doc) { + structures_.clear(); +} + +std::string CGeneratorBase::Tab(int cnt) { + std::string str; + + for (int i = 0; i < cnt; ++i) { + str += "\t"; + } + + return str; +} + +std::string CGeneratorBase::NLine(int cnt) { + std::string str; + + for (int i = 0; i < cnt; ++i) { + str += "\n"; + } + + return str; +} + +std::string CGeneratorBase::ConvertTypeToString( + ParameterType::Direction direction, const BaseType& type) { + if (type.IsUserDefinedType()) { + if (direction == ParameterType::Direction::IN) + return type.ToString(); + else + return type.ToString() + "*"; + } + + if (type.ToString() == "list" || + type.ToString() == "array") { + if (direction == ParameterType::Direction::IN) + return "GList*"; + else + return "GList**"; + } + + if (type.ToString() == "string") { + if (direction == ParameterType::Direction::IN) + return "const char*"; + else + return "char**"; + } + + if (type.ToString() == "bundle") { + if (direction == ParameterType::Direction::IN) + return "bundle*"; + else + return "bundle**"; + } + + if (direction == ParameterType::Direction::IN) + return type.ToString(); + + return type.ToString() + "*"; +} + +std::string CGeneratorBase::GetFullNameFromType(const BaseType& type) { + std::string str = type.ToString(); + + if (type.GetMetaType() != nullptr) { + str += "_"; + str += GetFullNameFromType(*type.GetMetaType()); + } + + return str; +} + +std::string CGeneratorBase::GetParcelParamTypeString(const BaseType& type) { + if (type.IsUserDefinedType()) + return "rpc_port_" + type.ToString() + "_h"; + + if (type.ToString() == "list" || + type.ToString() == "array") + return "rpc_port_" + GetFullNameFromType(type) + "_h"; + + if (type.ToString() == "string") + return "char*"; + + return type.ToString() + "*"; +} + +void CGeneratorBase::AddStructureFromType(const BaseType& type) { + if (type.GetMetaType() == nullptr) + return; + + BaseType* t = new BaseType(type); + assert(t != nullptr); + + std::string type_name = GetFullNameFromType(type); + Element* elm = new Element(type_name + "s", t, "", __LINE__); + assert(elm != nullptr); + + Elements* elms = new Elements(); + assert(elms != nullptr); + elms->Add(elm); + + Structure* st = new Structure(type_name, elms, "", __LINE__); + assert(st != nullptr); + + structures_[type_name] = std::unique_ptr(st); + + AddStructureFromType(*type.GetMetaType()); +} + +std::string CGeneratorBase::SmartIndent(std::string lines) { + std::stringstream ss(lines); + std::string result; + std::string to; + std::size_t found; + bool if_statement = false; + int indent = 0; + + while (std::getline(ss, to, '\n')) { + to = Trim(to); + found = to.find('}'); + if (found != std::string::npos) { + indent--; + } + + if (to.length() > 0) { + for (int i = 0; i < indent; i++) { + result += "\t"; + } + } + + if (found == std::string::npos && if_statement) { + indent--; + if_statement = false; + } + + result += to; + result += "\n"; + + found = to.find('{'); + if (found != std::string::npos) { + indent++; + } else { + found = to.find("if ("); + if (found != std::string::npos) { + indent++; + if_statement = true; + } + } + } + + return result; +} + +std::string CGeneratorBase::Trim(const std::string& str) +{ + std::size_t first = str.find_first_not_of(" \t\r\n"); + if (first == std::string::npos) + return str; + + std::size_t last = str.find_last_not_of(" \t\r\n"); + return str.substr(first, (last - first + 1)); +} + +void CGeneratorBase::GenLicenseDescription(std::ofstream& stream) { + const char license[] = + "/*\n" \ + " * Copyright (c) $$ Samsung Electronics Co., Ltd.\n" \ + " *\n" \ + " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" \ + " * you may not use this file except in compliance with the License.\n" \ + " * You may obtain a copy of the License at\n" \ + " *\n" \ + " * http://www.apache.org/licenses/LICENSE-2.0\n" \ + " *\n" \ + " * Unless required by applicable law or agreed to in writing, software\n" \ + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" \ + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" \ + " * See the License for the specific language governing permissions and\n" \ + " * limitations under the License.\n" \ + " */\n"; + + GenTemplate(license, stream, + [&]()->std::string { + std::time_t t = std::time(NULL); + std::tm* local_time = std::localtime(&t); + return std::to_string(local_time->tm_year + 1900); + } + ); +} + +void CGeneratorBase::GenIncludeDefaultHeaders(std::ofstream& stream, + bool body) { + const char header[] = + "#include \n" \ + "#include \n"; + + const char body_header[] = + "#include \n" \ + "#include \n" \ + "#include \n" \ + "#include \n" \ + "#include \n" \ + "#include \n" \ + "#include \n"; + + stream << NLine(1); + if (body) { + stream << std::string(body_header); + } else { + stream << std::string(header); + } +} + +void CGeneratorBase::GenGNUSourceDefinition(std::ofstream& stream) { + const char format[] = "#define _GNU_SOURCE\n"; + + stream << NLine(1); + stream << std::string(format); +} } // namespace tidl diff --git a/idlc/c_gen/c_gen_base.h b/idlc/c_gen/c_gen_base.h index f894138..220bdc1 100644 --- a/idlc/c_gen/c_gen_base.h +++ b/idlc/c_gen/c_gen_base.h @@ -31,6 +31,40 @@ class CGeneratorBase : public Generator { public: explicit CGeneratorBase(std::shared_ptr doc); virtual ~CGeneratorBase() = default; + + template + std::string GenTemplateString(std::string templ, T cb, ARGS... args) { + size_t f = templ.find("$$"); + templ.replace(f, std::string("$$").length(), cb()); + return GenTemplateString(std::move(templ), args...); + } + + template + std::string GenTemplateString(std::string templ, T cb) { + size_t f = templ.find("$$"); + templ.replace(f, std::string("$$").length(), cb()); + return templ; + } + + std::string Trim(const std::string& str); + std::string SmartIndent(std::string lines); + std::string Tab(int cnt); + std::string NLine(int cnt); + std::string ConvertTypeToString(ParameterType::Direction direction, + const BaseType& type); + std::string GetFullNameFromType(const BaseType& type); + std::string GetParcelParamTypeString(const BaseType& type); + void AddStructureFromType(const BaseType& type); + const std::map>& GetStructures(void) { + return structures_; + } + + void GenLicenseDescription(std::ofstream& stream); + void GenIncludeDefaultHeaders(std::ofstream& stream, bool body = true); + void GenGNUSourceDefinition(std::ofstream& stream); + + private: + std::map> structures_; }; } // namespace tidl diff --git a/idlc/c_gen/c_header_gen_base.cc b/idlc/c_gen/c_header_gen_base.cc new file mode 100644 index 0000000..2b356d2 --- /dev/null +++ b/idlc/c_gen/c_header_gen_base.cc @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2018 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 + +#include "idlc/c_gen/c_header_gen_base.h" + +namespace tidl { + +CHeaderGeneratorBase::CHeaderGeneratorBase(std::shared_ptr doc) + : CGeneratorBase(doc) {} + +void CHeaderGeneratorBase::GenPragmaOnce(std::ofstream& stream) { + const char format[] = "#pragma once\n"; + + stream << NLine(1); + stream << std::string(format); +} + +void CHeaderGeneratorBase::GenExplicitLinkageOpen(std::ofstream& stream) { + const char format[] = + "#ifdef __cplusplus\n" \ + "extern \"C\" {\n" \ + "#endif\n"; + + stream << NLine(1); + stream << std::string(format); +} + +void CHeaderGeneratorBase::GenExplicitLinkageClose(std::ofstream& stream) { + const char format[] = + "#ifdef __cplusplus\n" \ + "}\n" \ + "#endif\n"; + + stream << NLine(1); + stream << std::string(format); +} + +void CHeaderGeneratorBase::GenStructures(std::ofstream& stream) { + for (auto& i : GetDocument().GetBlocks()) { + if (i->GetType() != Block::TYPE_STRUCTURE) + continue; + + const Structure &st = static_cast(*i); + GenStructure(stream, st); + for (auto& j : st.GetElements().GetElms()) { + auto& t = j->GetType(); + AddStructureFromType(t); + } + } + + for (auto& p : GetStructures()) { + const Structure& st = *p.second; + GenStructure(stream, st); + } +} + +void CHeaderGeneratorBase::GenStructure(std::ofstream& stream, + const Structure& st) { + GenStructureDeclaration(stream, st); + GenStructureConstructor(stream, st); + GenStructureDestructor(stream, st); + GenStructureCloner(stream, st); + GenStructureSetter(stream, st); + GenStructureGetter(stream, st); + GenStructureIterator(stream, st); +} + +void CHeaderGeneratorBase::GenStructureDeclaration(std::ofstream& stream, + const Structure& st) { + const char format[] = "typedef struct $$_s *rpc_port_$$_h;\n"; + + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + } + ); +} + +void CHeaderGeneratorBase::GenStructureConstructor(std::ofstream& stream, + const Structure& st) { + const char format[] = "int rpc_port_create_$$(rpc_port_$$_h* h);\n"; + + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + } + ); +} + +void CHeaderGeneratorBase::GenStructureDestructor(std::ofstream& stream, + const Structure& st) { + const char format[] = "int rpc_port_destroy_$$(rpc_port_$$_h h);\n"; + + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + } + ); +} + +void CHeaderGeneratorBase::GenStructureSetter(std::ofstream& stream, + const Structure& st) { + const char format[] = "int rpc_port_$$_$$_$$(rpc_port_$$_h h, $$ $$);\n"; + + for (auto& i : st.GetElements().GetElms()) { + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + if (i->GetType().ToString() == "list" || + i->GetType().ToString() == "array") + return "add"; + return "set"; + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + if (i->GetType().IsUserDefinedType()) + return GetParcelParamTypeString(i->GetType()); + + if (i->GetType().ToString() == "list" || + i->GetType().ToString() == "array") { + if (i->GetType().GetMetaType()->IsUserDefinedType() || + i->GetType().GetMetaType()->ToString() == "list" || + i->GetType().GetMetaType()->ToString() == "array") { + return GetParcelParamTypeString(*i->GetType().GetMetaType()); + } else { + return ConvertTypeToString(ParameterType::Direction::IN, + *i->GetType().GetMetaType()); + } + } + + return ConvertTypeToString(ParameterType::Direction::IN, + i->GetType()); + }, + [&]()->std::string { + return i->GetID(); + } + ); + } +} + +void CHeaderGeneratorBase::GenStructureGetter(std::ofstream& stream, + const Structure& st) { + const char format[] = "int rpc_port_get_$$_$$(rpc_port_$$_h h, $$ $$);\n"; + + for (auto& i : st.GetElements().GetElms()) { + if (i->GetType().ToString() == "list" || + i->GetType().ToString() == "array") + continue; + + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + if (i->GetType().IsUserDefinedType()) + return GetParcelParamTypeString(i->GetType()); + + return ConvertTypeToString(ParameterType::Direction::OUT, + i->GetType()); + }, + [&]()->std::string { + return i->GetID(); + } + ); + } +} + +void CHeaderGeneratorBase::GenStructureIterator(std::ofstream& stream, + const Structure& st) { + const char format[] = + "int rpc_port_foreach_$$_$$(rpc_port_$$_h h, " \ + "void (*callback)($$ $$, void* user_data), void* user_data);\n"; + + for (auto& i : st.GetElements().GetElms()) { + if (i->GetType().ToString() != "list" && + i->GetType().ToString() != "array") + continue; + + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return i->GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + if (i->GetType().GetMetaType()->IsUserDefinedType() || + i->GetType().GetMetaType()->ToString() == "list" || + i->GetType().GetMetaType()->ToString() == "array") + return GetParcelParamTypeString(*i->GetType().GetMetaType()); + + return ConvertTypeToString(ParameterType::Direction::IN, + *i->GetType().GetMetaType()); + }, + [&]()->std::string { + return i->GetID(); + } + ); + } +} + +void CHeaderGeneratorBase::GenStructureCloner(std::ofstream& stream, + const Structure& st) { + const char format[] = + "int rpc_port_clone_$$(rpc_port_$$_h h, rpc_port_$$_h* clone);\n"; + + stream << NLine(1); + GenTemplate(format, stream, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + }, + [&]()->std::string { + return st.GetID(); + } + ); +} + +} // namespace tidl diff --git a/idlc/c_gen/c_header_gen_base.h b/idlc/c_gen/c_header_gen_base.h new file mode 100644 index 0000000..f9d0505 --- /dev/null +++ b/idlc/c_gen/c_header_gen_base.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 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_C_GEN_C_HEADER_GEN_BASE_H_ +#define IDLC_C_GEN_C_HEADER_GEN_BASE_H_ + +#include +#include +#include + +#include "idlc/c_gen/c_gen_base.h" + +namespace tidl { + +class CHeaderGeneratorBase : public CGeneratorBase { + public: + explicit CHeaderGeneratorBase(std::shared_ptr doc); + virtual ~CHeaderGeneratorBase() = default; + + void GenPragmaOnce(std::ofstream& stream); + void GenExplicitLinkageOpen(std::ofstream& stream); + void GenExplicitLinkageClose(std::ofstream& stream); + void GenStructures(std::ofstream& stream); + + private: + void GenStructure(std::ofstream& stream, const Structure& st); + void GenStructureDeclaration(std::ofstream& stream, const Structure& st); + void GenStructureParcelTo(std::ofstream& stream, const Structure& st); + void GenStructureParcelFrom(std::ofstream& stream, const Structure& st); + void GenStructureConstructor(std::ofstream& stream, const Structure& st); + void GenStructureDestructor(std::ofstream& stream, const Structure& st); + void GenStructureSetter(std::ofstream& stream, const Structure& st); + void GenStructureGetter(std::ofstream& stream, const Structure& st); + void GenStructureIterator(std::ofstream& stream, const Structure& st); + void GenStructureCloner(std::ofstream& stream, const Structure& st); +}; + +} // namespace tidl + +#endif // IDLC_C_GEN_C_HEADER_GEN_BASE_H_ diff --git a/idlc/c_gen/c_proxy_body_gen.cc b/idlc/c_gen/c_proxy_body_gen.cc index 0aa1715..3cd5cfb 100644 --- a/idlc/c_gen/c_proxy_body_gen.cc +++ b/idlc/c_gen/c_proxy_body_gen.cc @@ -19,9 +19,15 @@ namespace tidl { CProxyBodyGen::CProxyBodyGen(std::shared_ptr doc) - : CGeneratorBase(doc) {} + : CBodyGeneratorBase(doc) {} void CProxyBodyGen::OnInitGen(std::ofstream& stream) { + GenLicenseDescription(stream); + GenGNUSourceDefinition(stream); + GenIncludeDefaultHeaders(stream); + GenIncludeHeader(stream); + GenLogTag(stream, std::string("RPC_PORT_PROXY")); + GenStructures(stream); } void CProxyBodyGen::OnFiniGen(std::ofstream& stream) { diff --git a/idlc/c_gen/c_proxy_body_gen.h b/idlc/c_gen/c_proxy_body_gen.h index 07937eb..ecf4166 100644 --- a/idlc/c_gen/c_proxy_body_gen.h +++ b/idlc/c_gen/c_proxy_body_gen.h @@ -20,18 +20,17 @@ #include #include -#include "idlc/c_gen/c_gen_base.h" +#include "idlc/c_gen/c_body_gen_base.h" namespace tidl { -class CProxyBodyGen : public CGeneratorBase { +class CProxyBodyGen : public CBodyGeneratorBase { public: explicit CProxyBodyGen(std::shared_ptr doc); virtual ~CProxyBodyGen() = default; void OnInitGen(std::ofstream& stream) override; void OnFiniGen(std::ofstream& stream) override; - }; } // namespace tidl diff --git a/idlc/c_gen/c_proxy_header_gen.cc b/idlc/c_gen/c_proxy_header_gen.cc index b4c5be2..6e9652b 100644 --- a/idlc/c_gen/c_proxy_header_gen.cc +++ b/idlc/c_gen/c_proxy_header_gen.cc @@ -19,12 +19,18 @@ namespace tidl { CProxyHeaderGen::CProxyHeaderGen(std::shared_ptr doc) - : CGeneratorBase(doc) {} + : CHeaderGeneratorBase(doc) {} void CProxyHeaderGen::OnInitGen(std::ofstream& stream) { + GenLicenseDescription(stream); + GenPragmaOnce(stream); + GenIncludeDefaultHeaders(stream, false); + GenExplicitLinkageOpen(stream); + GenStructures(stream); } void CProxyHeaderGen::OnFiniGen(std::ofstream& stream) { + GenExplicitLinkageClose(stream); } } // namespace tidl diff --git a/idlc/c_gen/c_proxy_header_gen.h b/idlc/c_gen/c_proxy_header_gen.h index 9be5d6e..07dc168 100644 --- a/idlc/c_gen/c_proxy_header_gen.h +++ b/idlc/c_gen/c_proxy_header_gen.h @@ -20,11 +20,11 @@ #include #include -#include "idlc/c_gen/c_gen_base.h" +#include "idlc/c_gen/c_header_gen_base.h" namespace tidl { -class CProxyHeaderGen : public CGeneratorBase { +class CProxyHeaderGen : public CHeaderGeneratorBase { public: explicit CProxyHeaderGen(std::shared_ptr doc); virtual ~CProxyHeaderGen() = default; diff --git a/idlc/c_gen/c_stub_body_gen.cc b/idlc/c_gen/c_stub_body_gen.cc index de9578b..aacbb21 100644 --- a/idlc/c_gen/c_stub_body_gen.cc +++ b/idlc/c_gen/c_stub_body_gen.cc @@ -19,9 +19,15 @@ namespace tidl { CStubBodyGen::CStubBodyGen(std::shared_ptr doc) - : CGeneratorBase(doc) {} + : CBodyGeneratorBase(doc) {} void CStubBodyGen::OnInitGen(std::ofstream& stream) { + GenLicenseDescription(stream); + GenGNUSourceDefinition(stream); + GenIncludeDefaultHeaders(stream); + GenIncludeHeader(stream); + GenLogTag(stream, std::string("RPC_PORT_STUB")); + GenStructures(stream); } void CStubBodyGen::OnFiniGen(std::ofstream& stream) {} diff --git a/idlc/c_gen/c_stub_body_gen.h b/idlc/c_gen/c_stub_body_gen.h index 695f5d2..ab92c56 100644 --- a/idlc/c_gen/c_stub_body_gen.h +++ b/idlc/c_gen/c_stub_body_gen.h @@ -20,11 +20,11 @@ #include #include -#include "idlc/c_gen/c_gen_base.h" +#include "idlc/c_gen/c_body_gen_base.h" namespace tidl { -class CStubBodyGen : public CGeneratorBase { +class CStubBodyGen : public CBodyGeneratorBase { public: explicit CStubBodyGen(std::shared_ptr doc); virtual ~CStubBodyGen() = default; diff --git a/idlc/c_gen/c_stub_header_gen.cc b/idlc/c_gen/c_stub_header_gen.cc index 49db44e..5d54ef8 100644 --- a/idlc/c_gen/c_stub_header_gen.cc +++ b/idlc/c_gen/c_stub_header_gen.cc @@ -19,11 +19,18 @@ namespace tidl { CStubHeaderGen::CStubHeaderGen(std::shared_ptr doc) - : CGeneratorBase(doc) {} + : CHeaderGeneratorBase(doc) {} void CStubHeaderGen::OnInitGen(std::ofstream& stream) { + GenLicenseDescription(stream); + GenPragmaOnce(stream); + GenIncludeDefaultHeaders(stream, false); + GenExplicitLinkageOpen(stream); + GenStructures(stream); } -void CStubHeaderGen::OnFiniGen(std::ofstream& stream) {} +void CStubHeaderGen::OnFiniGen(std::ofstream& stream) { + GenExplicitLinkageClose(stream); +} } // namespace tidl diff --git a/idlc/c_gen/c_stub_header_gen.h b/idlc/c_gen/c_stub_header_gen.h index 361d568..b4cc89b 100644 --- a/idlc/c_gen/c_stub_header_gen.h +++ b/idlc/c_gen/c_stub_header_gen.h @@ -20,11 +20,11 @@ #include #include -#include "idlc/c_gen/c_gen_base.h" +#include "idlc/c_gen/c_header_gen_base.h" namespace tidl { -class CStubHeaderGen : public CGeneratorBase { +class CStubHeaderGen : public CHeaderGeneratorBase { public: explicit CStubHeaderGen(std::shared_ptr doc); virtual ~CStubHeaderGen() = default; diff --git a/idlc/type.cc b/idlc/type.cc index fec745b..e070533 100644 --- a/idlc/type.cc +++ b/idlc/type.cc @@ -30,6 +30,14 @@ BaseType::BaseType(std::string name, std::string comments, : Token(std::move(name), std::move(comments)), user_defined_(user_defined) { } +BaseType::BaseType(const BaseType& type) + : Token(type.ToString(), type.GetComments()), + user_defined_(type.IsUserDefinedType()) { + if (type.GetMetaType() != nullptr) { + SetMetaType(new BaseType(*type.GetMetaType())); + } +} + void BaseType::SetMetaType(BaseType* type) { meta_type_.reset(type); } diff --git a/idlc/type.h b/idlc/type.h index 433be2e..e3cf288 100644 --- a/idlc/type.h +++ b/idlc/type.h @@ -39,6 +39,8 @@ class BaseType : public Token { public: explicit BaseType(std::string name, std::string comments, bool user_defined = false); + BaseType(const BaseType& type); + void SetMetaType(BaseType* type); const BaseType* GetMetaType() const { return meta_type_.get(); -- 2.7.4