Implement C Stub Generator (Interface part) 82/170782/13
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 22 Feb 2018 05:39:10 +0000 (14:39 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 23 Feb 2018 06:35:20 +0000 (15:35 +0900)
Change-Id: I1af21520740434ce28ae68d8827aa68066e23480
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
idlc/c_gen/c_body_gen_base.cc
idlc/c_gen/c_body_gen_base.h
idlc/c_gen/c_gen_base.cc
idlc/c_gen/c_gen_base.h
idlc/c_gen/c_stub_body_gen.cc
idlc/c_gen/c_stub_body_gen.h
idlc/c_gen/c_stub_header_gen.cc
idlc/c_gen/c_stub_header_gen.h

index 7fb91d3..b674ea6 100644 (file)
@@ -25,14 +25,22 @@ CBodyGeneratorBase::CBodyGeneratorBase(std::shared_ptr<Document> doc)
 
 void CBodyGeneratorBase::GenStructures(std::ofstream& stream) {
   for (auto& i : GetDocument().GetBlocks()) {
-    if (i->GetType() != Block::TYPE_STRUCTURE)
-      continue;
-
-    const Structure &st = static_cast<const Structure&>(*i);
-    GenStructure(stream, st);
-    for (auto& j : st.GetElements().GetElms()) {
-      auto& t = j->GetType();
-      AddStructureFromType(t);
+    if (i->GetType() == Block::TYPE_STRUCTURE) {
+      const Structure &st = static_cast<const Structure&>(*i);
+      GenStructure(stream, st);
+      for (auto& j : st.GetElements().GetElms()) {
+       auto& t = j->GetType();
+       AddStructureFromType(t);
+      }
+    } else {
+      const Interface &inf = static_cast<const Interface&>(*i);
+      for (auto& d : inf.GetDeclarations().GetDecls()) {
+        for (auto& p : d->GetParameters().GetParams()) {
+          if (TypeIsDelegator(inf, p->GetParameterType().GetBaseType()))
+            continue;
+          AddStructureFromType(p->GetParameterType().GetBaseType());
+        }
+      }
     }
   }
 
@@ -481,7 +489,8 @@ void CBodyGeneratorBase::GenStructureCloner(std::ofstream& stream,
       );
 }
 
-std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type) {
+std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type,
+                                                    bool meta_type) {
   if (type.IsUserDefinedType())
     return "";
   if (type.ToString() == "char")
@@ -495,8 +504,11 @@ std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type) {
   if (type.ToString() == "long long")
     return "int64";
   if (type.ToString() == "list" ||
-      type.ToString() == "array")
+      type.ToString() == "array") {
+    if (meta_type)
+      return "";
     return "array_count";
+  }
 
   return type.ToString();
 }
@@ -516,9 +528,9 @@ std::string CBodyGeneratorBase::GetStringFromElementType(const BaseType& type) {
 }
 
 std::string CBodyGeneratorBase::GetParcelWriteFunctionString(
-    const BaseType& type) {
+    const BaseType& type, bool meta_type) {
   std::string str = "rpc_port_parcel_write";
-  std::string parcel_type = GetParcelTypeString(type);
+  std::string parcel_type = GetParcelTypeString(type, meta_type);
   if (parcel_type != "")
     str += "_" + parcel_type;
 
@@ -570,7 +582,7 @@ std::string CBodyGeneratorBase::GetParcelWriteString(const std::string& id,
         [&]()->std::string {
           return GenTemplateString(parcel,
               [&]()->std::string {
-                return GetParcelWriteFunctionString(type);
+                return GetParcelWriteFunctionString(*type.GetMetaType(), true);
               },
               [&]()->std::string {
                 if (type.GetMetaType()->IsUserDefinedType() ||
@@ -592,9 +604,9 @@ std::string CBodyGeneratorBase::GetParcelWriteString(const std::string& id,
 }
 
 std::string CBodyGeneratorBase::GetParcelReadFunctionString(
-    const BaseType& type) {
+    const BaseType& type, bool meta_type) {
   std::string str = "rpc_port_parcel_read";
-  std::string parcel_type = GetParcelTypeString(type);
+  std::string parcel_type = GetParcelTypeString(type, meta_type);
   if (parcel_type != "")
     str += "_" + parcel_type;
 
@@ -604,7 +616,7 @@ std::string CBodyGeneratorBase::GetParcelReadFunctionString(
 std::string CBodyGeneratorBase::GetParcelReadString(const std::string& id,
                                                     const BaseType& type) {
   std::string str;
-  const char parcel[] = "$$(parcel, $$)\n";
+  const char parcel[] = "$$(parcel, $$);\n";
   const char if_statement_with_braces[] =
       "if ($$) {\n" \
       "    $$" \
@@ -670,7 +682,7 @@ std::string CBodyGeneratorBase::GetParcelReadString(const std::string& id,
             s += NLine(1);
             s += GenTemplateString(parcel,
                 [&]()->std::string {
-                  return GetParcelReadFunctionString(*type.GetMetaType());
+                  return GetParcelReadFunctionString(*type.GetMetaType(), true);
                 },
                 [&]()->std::string {
                   return "&value->parcelable, value";
@@ -770,7 +782,7 @@ std::string CBodyGeneratorBase::GetFinalizeString(const std::string& id,
                 return "value";
               },
               [&]()->std::string {
-                return GetDestructorString(*type.GetMetaType(), "value");
+                return GetDestructorString(*type.GetMetaType(), "value", true);
               }
               );
         },
@@ -1089,7 +1101,8 @@ std::string CBodyGeneratorBase::GetClonerString(const std::string& id,
 }
 
 std::string CBodyGeneratorBase::GetDestructorString(const BaseType& type,
-                                                    const std::string& value) {
+                                                    const std::string& value,
+                                                    bool container_value) {
   std::string str;
 
   if (type.IsUserDefinedType() ||
@@ -1099,7 +1112,7 @@ std::string CBodyGeneratorBase::GetDestructorString(const BaseType& type,
         "(" + value + ");" + NLine(1);
   } else if (type.ToString() == "bundle") {
     str += "bundle_free(" + value + ");" + NLine(1);
-  } else {
+  } else if (type.ToString() == "string" || container_value) {
     str += "free(" + value + ");" + NLine(1);
   }
 
@@ -1169,4 +1182,97 @@ void CBodyGeneratorBase::GenLogTag(std::ofstream& stream,
       );
 }
 
+void CBodyGeneratorBase::GenInterfaceEnumerations(std::ofstream& stream,
+                                                  const Interface& inf) {
+  GenInterfaceMethodEnumeration(stream, inf);
+  GenInterfaceDelegateEnumeration(stream, inf);
+}
+
+void CBodyGeneratorBase::GenInterfaceDelegateEnumeration(
+    std::ofstream& stream, const Interface& inf) {
+  const char enum_format[] = "$$_DELEGATE_$$ = $$,\n";
+  const char format[] =
+      "enum $$_delegate_e {\n" \
+      "$$" \
+      "};\n";
+  int count = 1;
+
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(format,
+        [&]()->std::string {
+          return inf.GetID();
+        },
+        [&]()->std::string {
+          std::string str;
+          for (auto& i : inf.GetDeclarations().GetDecls()) {
+            if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+              continue;
+
+            str += GenTemplateString(enum_format,
+                [&]()->std::string {
+                  return inf.GetID();
+                },
+                [&]()->std::string {
+                  return i->GetID();
+                },
+                [&]()->std::string {
+                  return std::to_string(count++);
+                }
+                );
+          }
+          return str;
+        }
+        )
+      );
+}
+
+void CBodyGeneratorBase::GenInterfaceMethodEnumeration(
+    std::ofstream& stream, const Interface& inf) {
+  const char enum_format[] = "$$_METHOD_$$,\n";
+  const char block[] =
+    "enum $$_method_e {\n" \
+    "    $$_METHOD_Result,\n" \
+    "    $$_METHOD_Callback,\n"
+    "$$" \
+    "};\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(block,
+        [&]()->std::string {
+          return inf.GetID();
+        },
+        [&]()->std::string {
+          return inf.GetID();
+        },
+        [&]()->std::string {
+          return inf.GetID();
+        },
+        [&]()->std::string {
+          std::string str;
+          for (auto& i : inf.GetDeclarations().GetDecls()) {
+            if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+              continue;
+            str += GenTemplateString(enum_format,
+                [&]()->std::string {
+                  return inf.GetID();
+                },
+                [&]()->std::string {
+                  return i->GetID();
+                }
+                );
+          }
+          return str;
+        }
+        )
+      );
+}
+
+void CBodyGeneratorBase::GenTypedefStubMethod(std::ofstream& stream) {
+  const char format[] =
+      "typedef int (*stub_method)(rpc_port_h, rpc_port_parcel_h, void* data);\n";
+
+  stream << NLine(1);
+  stream << std::string(format);
+}
+
 }  // namespace tidl
index 0786be2..5628279 100644 (file)
@@ -33,6 +33,23 @@ class CBodyGeneratorBase : public CGeneratorBase {
   void GenStructures(std::ofstream& stream);
   void GenIncludeHeader(std::ofstream& stream);
   void GenLogTag(std::ofstream& stream, const std::string& log_tag);
+  void GenTypedefStubMethod(std::ofstream& stream);
+  void GenInterfaceEnumerations(std::ofstream& stream, const Interface& inf);
+  std::string GetParcelWriteFunctionString(const BaseType& type,
+                                           bool meta_type = false);
+  std::string GetParcelReadFunctionString(const BaseType& type,
+                                          bool meta_type = false);
+  std::string GetDestructorString(const BaseType& type,
+                                  const std::string& value,
+                                  bool container_value = false);
+  std::string GetConstructorString(const BaseType& type,
+                                   const std::string& value);
+
+ private:
+  void GenInterfaceMethodEnumeration(std::ofstream& stream,
+                                     const Interface& inf);
+  void GenInterfaceDelegateEnumeration(std::ofstream& stream,
+                                       const Interface& inf);
 
  private:
   void GenStructure(std::ofstream& stream, const Structure& st);
@@ -48,10 +65,8 @@ class CBodyGeneratorBase : public CGeneratorBase {
 
  private:
   std::string GetStringFromElementType(const BaseType& type);
-  std::string GetParcelTypeString(const BaseType& type);
-  std::string GetParcelWriteFunctionString(const BaseType& type);
+  std::string GetParcelTypeString(const BaseType& type, bool meta_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);
@@ -60,9 +75,8 @@ class CBodyGeneratorBase : public CGeneratorBase {
   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);
+  std::string GetSetterString(const std::string& lvalue,
+                              const std::string& rvalue);
 };
 
 }  // namespace tidl
index 6fc62d3..ce0bce9 100644 (file)
@@ -52,9 +52,9 @@ std::string CGeneratorBase::ConvertTypeToString(
     ParameterType::Direction direction, const BaseType& type) {
   if (type.IsUserDefinedType()) {
     if (direction == ParameterType::Direction::IN)
-      return type.ToString();
+      return "rpc_port_" + type.ToString() + "_h";
     else
-      return type.ToString() + "*";
+      return "rpc_port_" + type.ToString() + "_h" + "*";
   }
 
   if (type.ToString() == "list" ||
@@ -110,6 +110,20 @@ std::string CGeneratorBase::GetParcelParamTypeString(const BaseType& type) {
   return type.ToString() + "*";
 }
 
+std::string CGeneratorBase::GetReturnTypeString(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;
@@ -128,7 +142,11 @@ void CGeneratorBase::AddStructureFromType(const BaseType& type) {
   Structure* st = new Structure(type_name, elms, "", __LINE__);
   assert(st != nullptr);
 
-  structures_[type_name] = std::unique_ptr<Structure>(st);
+  if (StructureExist(*st)) {
+    delete st;
+  } else {
+    structures_[type_name] = std::unique_ptr<Structure>(st);
+  }
 
   AddStructureFromType(*type.GetMetaType());
 }
@@ -244,4 +262,69 @@ void CGeneratorBase::GenGNUSourceDefinition(std::ofstream& stream) {
   stream << std::string(format);
 }
 
+std::string CGeneratorBase::ReplaceAll(std::string str,
+                                       const std::string& from,
+                                       const std::string& to) {
+  std::size_t pos = 0;
+  while ((pos = str.find(from, pos)) != std::string::npos) {
+    str.replace(pos, from.length(), to);
+    pos += to.length();
+  }
+  return str;
+}
+
+bool CGeneratorBase::TypeIsDelegator(const Interface& inf,
+                                     const BaseType& type) {
+  for (auto& i : inf.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
+    if (i->GetID() == type.GetFullName())
+      return true;
+  }
+  return false;
+}
+
+bool CGeneratorBase::StructureExist(const Structure& st) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_STRUCTURE)
+      continue;
+
+    const Structure &s = static_cast<const Structure&>(*i);
+    if (s.GetID() == st.GetID())
+      return true;
+  }
+  return false;
+}
+
+std::string CGeneratorBase::GetParamTypeString(
+    ParameterType::Direction direction, const BaseType& type) {
+  if (type.IsUserDefinedType() ||
+      type.ToString() == "list" ||
+      type.ToString() == "array") {
+    if (direction == ParameterType::Direction::IN)
+      return "rpc_port_" + type.ToString() + "_h";
+    else
+      return "rpc_port_" + type.ToString() + "_h" + "*";
+  }
+
+  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() + "*";
+}
+
 }  // namespace tidl
index 220bdc1..07873c2 100644 (file)
@@ -46,6 +46,8 @@ class CGeneratorBase : public Generator {
     return templ;
   }
 
+  std::string ReplaceAll(std::string str,
+                         const std::string& from, const std::string& to);
   std::string Trim(const std::string& str);
   std::string SmartIndent(std::string lines);
   std::string Tab(int cnt);
@@ -54,6 +56,10 @@ class CGeneratorBase : public Generator {
                                   const BaseType& type);
   std::string GetFullNameFromType(const BaseType& type);
   std::string GetParcelParamTypeString(const BaseType& type);
+  std::string GetReturnTypeString(const BaseType& type);
+  std::string GetParamTypeString(ParameterType::Direction direction,
+                                 const BaseType& type);
+  bool TypeIsDelegator(const Interface& inf, const BaseType& type);
   void AddStructureFromType(const BaseType& type);
   const std::map<std::string, std::unique_ptr<Structure>>& GetStructures(void) {
     return structures_;
@@ -64,6 +70,9 @@ class CGeneratorBase : public Generator {
   void GenGNUSourceDefinition(std::ofstream& stream);
 
  private:
+  bool StructureExist(const Structure& st);
+
+ private:
   std::map<std::string, std::unique_ptr<Structure>> structures_;
 };
 
index aacbb21..ddfdb06 100644 (file)
@@ -27,9 +27,886 @@ void CStubBodyGen::OnInitGen(std::ofstream& stream) {
   GenIncludeDefaultHeaders(stream);
   GenIncludeHeader(stream);
   GenLogTag(stream, std::string("RPC_PORT_STUB"));
+  GenTypedefStubMethod(stream);
   GenStructures(stream);
+  GenInterfaces(stream);
 }
 
 void CStubBodyGen::OnFiniGen(std::ofstream& stream) {}
 
+void CStubBodyGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    const Interface &inf = static_cast<const Interface&>(*i);
+    GenInterface(stream, inf);
+  }
+}
+
+void CStubBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) {
+  GenInterfaceEnumerations(stream, inf);
+  GenInterfaceGlobalVariables(stream, inf);
+  GenInterfaceContext(stream, inf);
+  GenInterfaceDelegators(stream, inf);
+  GenInterfaceMethods(stream, inf);
+  GenInterfaceMethodTable(stream, inf);
+  GenInterfaceOnConnectedEventCB(stream, inf);
+  GenInterfaceOnDisconnectedEventCB(stream, inf);
+  GenInterfaceOnReceivedEventCB(stream, inf);
+  GenInterfaceRegister(stream, inf);
+  GenInterfaceUnregister(stream, inf);
+}
+
+void CStubBodyGen::GenInterfaceMethods(std::ofstream& stream,
+                                       const Interface& inf) {
+  const char block[] =
+      "static int __$$_method_$$(rpc_port_h port, rpc_port_parcel_h parcel, void* data)\n" \
+      "{\n" \
+      "    rpc_port_stub_$$_context_h context = data;\n" \
+      "$$" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+
+  for (auto& i : inf.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    stream << NLine(1);
+    stream << SmartIndent(GenTemplateString(block,
+          [&]()->std::string {
+            return inf.GetID();
+          },
+          [&]()->std::string {
+            return i->GetID();
+          },
+          [&]()->std::string {
+            return inf.GetID();
+          },
+          [&]()->std::string {
+            return GetMethodString(inf, *i);
+          }
+          )
+        );
+  }
+}
+
+void CStubBodyGen::GenInterfaceMethodTable(std::ofstream& stream,
+                                           const Interface& inf) {
+  const char block[] =
+      "static stub_method __$$_method_table[] = {\n" \
+      "$$" \
+      "};\n";
+  const char method_format[] = "[$$] = $$,\n";
+  std::string str;
+  int cnt = 0;
+
+  for (auto& i : inf.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+    str += GenTemplateString(method_format,
+        [&]()->std::string {
+          return inf.GetID() + "_METHOD_" + i->GetID();
+        },
+        [&]()->std::string {
+          return "__" + inf.GetID() + "_method_" + i->GetID();
+        }
+        );
+    cnt++;
+  }
+
+  if (cnt == 0)
+    return;
+
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(block,
+        [&]()->std::string {
+          return inf.GetID();
+        },
+        [&]()->std::string {
+          return str;
+        }
+        )
+      );
+}
+
+void CStubBodyGen::GenInterfaceOnConnectedEventCB(std::ofstream& stream,
+                                                  const Interface& inf) {
+  const char block[] =
+      "static void __##_on_connected(const char* sender, const char* instance, void* data)\n" \
+      "{\n" \
+      "    rpc_port_stub_##_context_h context;\n" \
+      "\n" \
+      "    LOGI(\"[__RPC_PORT__] sender(%s), instance(%s)\", sender, instance);\n" \
+      "    context = __create_##_context(sender, instance);\n" \
+      "    if (!context)\n" \
+      "        return;\n" \
+      "\n" \
+      "    if (context->callback.create)\n" \
+      "        context->callback.create(context, context->user_data);\n" \
+      "    __##_contexts = g_list_append(__##_contexts, context);\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceOnDisconnectedEventCB(std::ofstream& stream,
+                                                     const Interface& inf) {
+  const char block[] =
+      "static void __##_on_disconnected(const char* sender, const char* instance, void* data)\n" \
+      "{\n" \
+      "    rpc_port_stub_##_context_h context;\n" \
+      "\n" \
+           "    LOGI(\"[__RPC_PORT__] sender(%s), instance(%s)\", sender, instance);\n" \
+           "    context = __find_##_context(instance);\n" \
+           "    if (!context)\n" \
+                 "        return;\n" \
+      "\n" \
+           "    if (context->callback.terminate)\n" \
+                 "        context->callback.terminate(context, context->user_data);\n" \
+           "    __##_contexts = g_list_remove(__##_contexts, context);\n" \
+           "    __destroy_##_context(context);\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceOnReceivedEventCB(std::ofstream& stream,
+                                                 const Interface& inf) {
+  const char block[] =
+      "static int __##_on_received(const char* sender, const char* instance, rpc_port_h port, void* data)\n" \
+      "{\n" \
+      "    rpc_port_stub_##_context_h context;\n" \
+      "    rpc_port_parcel_h parcel;\n" \
+      "    int cmd = -1;\n" \
+      "    int r;\n" \
+      "\n" \
+      "    LOGI(\"[__RPC_PORT__] sender(%s), instance(%s)\", sender, instance);\n" \
+      "    context = __find_##_context(instance);\n" \
+      "    if (!context) {\n" \
+      "        LOGE(\"Failed to find ## context(%s)\", instance);\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "    context->port = port;\n" \
+      "\n" \
+      "    r = rpc_port_parcel_create_from_port(&parcel, port);\n" \
+      "    if (r != 0) {\n" \
+      "        LOGE(\"Failed to create parcel from port\");\n" \
+      "        return r;\n" \
+      "    }\n" \
+      "\n" \
+      "    rpc_port_parcel_read_int32(parcel, &cmd);\n" \
+      "    if (cmd > 1 && cmd < (sizeof(__##_method_table) / sizeof(__##_method_table[0]))) {\n" \
+      "         if (__##_method_table[cmd])\n"
+      "             r = __##_method_table[cmd](port, parcel, context);\n" \
+      "    } else {\n" \
+      "         LOGE(\"Unknown Command(%d)\", cmd);\n" \
+      "         r = -1;\n" \
+      "    }\n"
+      "\n" \
+      "    rpc_port_parcel_destroy(parcel);\n" \
+      "\n" \
+      "    return r;\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceRegister(std::ofstream& stream,
+                                        const Interface& inf) {
+  const char block[] =
+      "int rpc_port_stub_##_register(rpc_port_stub_##_callback_s* callback, void* user_data)\n" \
+      "{\n" \
+      "    int r;\n" \
+      "\n" \
+      "    if (__##_stub) {\n" \
+      "        LOGW(\"Already exists\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    if (!callback) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    __##_callback = *callback;\n" \
+      "    __##_user_data = user_data;\n" \
+      "    r = rpc_port_stub_create(&__##_stub, \"##\");\n" \
+      "    if (r != 0) {\n" \
+      "        LOGE(\"Failed to create stub handle\");\n" \
+      "        return r;\n" \
+      "    }\n" \
+      "\n" \
+      "    r = rpc_port_stub_add_received_event_cb(__##_stub, __##_on_received, NULL);\n" \
+      "    if (r != 0) {\n" \
+      "        LOGE(\"Failed to add received event callback\");\n" \
+      "        rpc_port_stub_destroy(__##_stub);\n" \
+      "         __##_stub = NULL;\n" \
+      "        return r;\n" \
+      "    }\n" \
+      "\n" \
+      "    r = rpc_port_stub_add_connected_event_cb(__##_stub, __##_on_connected, NULL);\n" \
+      "    if (r != 0) {\n" \
+      "        LOGE(\"Failed to add connected event callback\");\n" \
+      "        rpc_port_stub_destroy(__##_stub);\n" \
+      "        __##_stub = NULL;\n" \
+      "        return r;\n" \
+      "    }\n" \
+      "\n" \
+      "    r = rpc_port_stub_add_disconnected_event_cb(__##_stub, __##_on_disconnected, NULL);\n" \
+      "    if (r != 0) {\n" \
+      "        LOGE(\"Failed to add disconnected event callback\");\n" \
+      "        rpc_port_stub_destroy(__##_stub);\n" \
+      "        __##_stub = NULL;\n" \
+      "        return r;\n" \
+      "    }\n" \
+      "\n" \
+      "$$" \
+      "\n" \
+      "    r = rpc_port_stub_listen(__##_stub);\n" \
+      "    if (r != 0) {\n" \
+      "        LOGE(\"Failed to listen stub\");\n" \
+      "        rpc_port_stub_destroy(__##_stub);\n" \
+      "        __##_stub = NULL;\n" \
+      "        return r;\n" \
+      "    }\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(
+        ReplaceAll(block, "##", inf.GetID()),
+        [&]()->std::string {
+          std::string str;
+          for (auto& a : inf.GetAttributes().GetAttrs()) {
+            if (a->GetKey() != "privilege")
+              continue;
+            str += NLine(1);
+            str += GetAddPrivilegeString(inf.GetID(), *a);
+          }
+          return str;
+        }
+        )
+      );
+}
+
+void CStubBodyGen::GenInterfaceUnregister(std::ofstream& stream,
+                                          const Interface& inf) {
+  const char block[] =
+      "int rpc_port_stub_##_unregister(void)\n" \
+      "{\n" \
+      "    int r;\n" \
+      "\n" \
+      "    if (!__##_stub)\n" \
+      "        return -1;\n" \
+      "\n" \
+      "    if (__##_contexts) {\n" \
+      "        g_list_free_full(__##_contexts, __destroy_##_context);\n" \
+      "        __##_contexts = NULL;\n" \
+      "    }\n" \
+      "\n" \
+      "    r = rpc_port_stub_destroy(__##_stub);\n" \
+      "    __##_stub = NULL;\n" \
+      "    return r;\n"
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceGlobalVariables(std::ofstream& stream,
+                                               const Interface& inf) {
+  const char format[] =
+      "static rpc_port_stub_h __##_stub;\n" \
+      "static rpc_port_stub_##_callback_s __##_callback;\n" \
+      "static void* __##_user_data;\n" \
+      "static GList* __##_contexts;\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(format, "##", inf.GetID()));
+}
+
+std::string CStubBodyGen::GetMethodString(const Interface& inf,
+                                          const Declaration& decl) {
+  std::string str;
+  const char port_setter[] = "rpc_port_set_$$_port($$, port);\n";
+  const char parcel[] = "$$(parcel, $$);\n";
+  const char do_while_block[] =
+      "do {\n" \
+      "    rpc_port_parcel_h result;\n" \
+      "    rpc_port_parcel_create(&result);\n" \
+      "    rpc_port_parcel_write_int32(result, $$_METHOD_Result);\n" \
+      "    $$(result, result_value);\n" \
+      "    rpc_port_parcel_send(result, port);\n" \
+      "    rpc_port_parcel_destroy(result);\n" \
+      "} while (0);\n";
+  int cnt = 0;
+  for (auto& i : decl.GetParameters().GetParams()) {
+    str += GetParcelParamTypeString(i->GetParameterType().GetBaseType()) +
+        " " + i->GetID() + ";" + NLine(1);
+    cnt++;
+  }
+  str += NLine(1);
+
+  for (auto& i: decl.GetParameters().GetParams()) {
+    if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
+        i->GetParameterType().GetBaseType().ToString() == "list" ||
+        i->GetParameterType().GetBaseType().ToString() == "array") {
+      str += GetConstructorString(i->GetParameterType().GetBaseType(),
+          i->GetID());
+      if (TypeIsDelegator(inf, i->GetParameterType().GetBaseType())) {
+        str += GenTemplateString(port_setter,
+            [&]()->std::string {
+              return i->GetParameterType().GetBaseType().ToString();
+            },
+            [&]()->std::string {
+              return i->GetID();
+            }
+            );
+      }
+    }
+
+    str += GenTemplateString(parcel,
+          [&]()->std::string {
+            return GetParcelReadFunctionString(
+                i->GetParameterType().GetBaseType(), true);
+          },
+          [&]()->std::string {
+            if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
+                i->GetParameterType().GetBaseType().ToString() == "list" ||
+                i->GetParameterType().GetBaseType().ToString() == "array")
+              return "&" + i->GetID() + "->parcelable, " + i->GetID();
+            return "&" + i->GetID();
+          }
+        );
+  }
+
+  if (cnt > 0)
+    str += NLine(1);
+
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC &&
+      decl.GetType().ToString() != "void") {
+    str += GetReturnTypeString(decl.GetType()) + " result_value = ";
+  }
+
+  str += "context->callback." + decl.GetID() + "(context";
+  for (auto& i: decl.GetParameters().GetParams()) {
+    str += ", " + i->GetID();
+  }
+  str += ", context->user_data);" + NLine(1);
+  if (decl.GetMethodType() == Declaration::MethodType::SYNC &&
+      decl.GetType().ToString() != "void") {
+    str += GenTemplateString(do_while_block,
+        [&]()->std::string {
+          return inf.GetID();
+        },
+        [&]()->std::string {
+          return GetParcelWriteFunctionString(decl.GetType(), true);
+        }
+        );
+    }
+
+  for (auto& i: decl.GetParameters().GetParams()) {
+    str += GetDestructorString(i->GetParameterType().GetBaseType(),
+        i->GetID());
+  }
+
+  return str;
+}
+
+std::string CStubBodyGen::GetAddPrivilegeString(const std::string& id,
+                                                const Attribute& attr) {
+  const char format[] =
+      "r = $$;\n" \
+       "if (r != 0) {\n" \
+      "    LOGE(\"$$\");\n" \
+      "    rpc_port_stub_destroy(__$$_stub);\n" \
+      "    __$$_stub = NULL;\n" \
+      "    return r;\n" \
+      "}\n";
+  std::string str;
+
+  str += GenTemplateString(format,
+      [&]()->std::string {
+        return "rpc_port_stub_add_privilege(__" + id +
+            "_stub, \"" + attr.GetValue() + "\")";
+      },
+      [&]()->std::string {
+        return "Failed to add privilege";
+      },
+      [&]()->std::string {
+        return id;
+      },
+      [&]()->std::string {
+        return id;
+      }
+      );
+  return str;
+}
+
+void CStubBodyGen::GenInterfaceDelegators(std::ofstream& stream,
+                                          const Interface& inf) {
+  for (auto& i : inf.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
+    GenInterfaceDelegator(stream, inf.GetID(), *i);
+  }
+}
+
+void CStubBodyGen::GenInterfaceDelegator(std::ofstream& stream,
+                                         const std::string& id,
+                                         const Declaration& decl) {
+  GenInterfaceDelegatorDeclaration(stream, id, decl);
+  GenInterfaceDelegatorSerializer(stream, id, decl);
+  GenInterfaceDelegatorDeserializer(stream, id, decl);
+  GenInterfaceDelegatorConstructor(stream, id, decl);
+  GenInterfaceDelegatorDestructor(stream, id, decl);
+  GenInterfaceDelegatorCloner(stream, id, decl);
+  GenInterfaceDelegatorInvoker(stream, id, decl);
+  GenInterfaceDelegatorPortSetter(stream, id, decl);
+}
+
+void CStubBodyGen::GenInterfaceDelegatorDeclaration(std::ofstream& stream,
+                                                    const std::string& id,
+                                                    const Declaration& decl) {
+  const char block[] =
+      "struct $$_s {\n" \
+      "    rpc_port_parcelable_t parcelable;\n" \
+      "    rpc_port_h port;\n" \
+      "    int id;\n" \
+      "    int seq_id;\n" \
+      "};\n";
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(block,
+        [&]()->std::string {
+          return decl.GetID();
+        }
+        )
+      );
+}
+
+void CStubBodyGen::GenInterfaceDelegatorConstructor(std::ofstream& stream,
+                                                    const std::string& id,
+                                                    const Declaration& decl) {
+  const char block[] =
+      "int rpc_port_create_##(rpc_port_##_h* h)\n" \
+      "{\n" \
+      "    struct ##_s* handle;\n" \
+      "    static int seq_num;\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" \
+      "    handle->id = $$_DELEGATE_##;\n" \
+      "    handle->seq_id = seq_num++;\n" \
+      "\n" \
+      "    *h = handle;\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(
+        ReplaceAll(block, "##", decl.GetID()),
+        [&]()->std::string {
+          return id;
+        }
+        )
+      );
+}
+
+void CStubBodyGen::GenInterfaceDelegatorDestructor(std::ofstream& stream,
+                                                   const std::string& id,
+                                                   const Declaration& decl) {
+  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(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorSerializer(std::ofstream& stream,
+                                                   const std::string& id,
+                                                   const Declaration& decl) {
+  const char block[] =
+      "static void __##_to(rpc_port_parcel_h parcel, void* data)\n" \
+      "{\n" \
+      "    rpc_port_##_h handle = data;\n" \
+      "\n" \
+      "    if (!handle) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return;\n" \
+      "    }\n" \
+      "\n" \
+      "    rpc_port_parcel_write_int32(parcel, handle->id);\n" \
+      "    rpc_port_parcel_write_int32(parcel, handle->seq_id);\n" \
+      "}\n";
+
+    stream << NLine(1);
+    stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorDeserializer(std::ofstream& stream,
+                                                     const std::string& id,
+                                                     const Declaration& decl) {
+  const char block[] =
+      "static void __##_from(rpc_port_parcel_h parcel, void* data)\n" \
+      "{\n" \
+      "    rpc_port_##_h handle = data;\n" \
+      "\n" \
+      "    if (!handle) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return;\n" \
+      "    }\n" \
+      "\n" \
+      "    rpc_port_parcel_read_int32(parcel, &handle->id);\n" \
+      "    rpc_port_parcel_read_int32(parcel, &handle->seq_id);\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorCloner(std::ofstream& stream,
+                                               const std::string& id,
+                                               const Declaration& decl) {
+  const char block[] =
+      "int rpc_port_clone_##(rpc_port_##_h h, rpc_port_##_h* clone)\n" \
+      "{\n" \
+      "    rpc_port_##_h handle;\n" \
+      "\n" \
+      "    if (!h || !clone) {\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 = h->parcelable;\n" \
+      "    handle->port = h->port;\n" \
+      "    handle->id = h->id;\n" \
+      "    handle->seq_id = h->seq_id;\n" \
+      "\n" \
+      "    *clone = handle;\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorInvoker(std::ofstream& stream,
+                                                const std::string& id,
+                                                const Declaration& decl) {
+  const char parcel[] = "$$(parcel, $$);\n";
+  const char block[] =
+      "int rpc_port_invoke_$$($$)\n" \
+      "{\n" \
+      "    rpc_port_parcel_h parcel = NULL;\n" \
+      "\n" \
+      "    if (!h || !h->port) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    if (!__$$_context_port_exist(h->port)) {\n" \
+      "        LOGE(\"Port doesn't exist\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    rpc_port_parcel_create(&parcel);\n" \
+      "    if (!parcel) {\n" \
+      "        LOGE(\"Failed to create parcel\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    rpc_port_parcel_write_int32(parcel, $$_METHOD_Callback);\n" \
+      "    rpc_port_parcel_write(parcel, &h->parcelable, h);\n" \
+      "$$" \
+      "    rpc_port_parcel_send(parcel, h->port);\n" \
+      "    rpc_port_parcel_destroy(parcel);\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(block,
+        [&]()->std::string {
+          return decl.GetID();
+        },
+        [&]()->std::string {
+          std::string str;
+          str += "rpc_port_" + decl.GetID() + "_h h";
+          for (auto& i : decl.GetParameters().GetParams()) {
+            str += ", ";
+            str += ConvertTypeToString(i->GetParameterType().GetDirection(),
+                i->GetParameterType().GetBaseType()) + " " + i->GetID();
+          }
+          return str;
+        },
+        [&]()->std::string {
+          return id;
+        },
+        [&]()->std::string {
+          return id;
+        },
+        [&]()->std::string {
+          std::string str;
+          for (auto& i : decl.GetParameters().GetParams()) {
+            str += GenTemplateString(parcel,
+                [&]()->std::string {
+                  return GetParcelWriteFunctionString(
+                      i->GetParameterType().GetBaseType());
+                },
+                [&]()->std::string {
+                  if (i->GetParameterType().GetBaseType().IsUserDefinedType() ||
+                      i->GetParameterType().GetBaseType().ToString() == "list" ||
+                      i->GetParameterType().GetBaseType().ToString() == "array")
+                    return "&" + i->GetID() + "->parcelable, " + i->GetID();
+                  return i->GetID();
+                }
+                );
+          }
+          return str;
+        }
+        )
+      );
+}
+
+void CStubBodyGen::GenInterfaceDelegatorPortSetter(std::ofstream& stream,
+                                                   const std::string& id,
+                                                   const Declaration& decl) {
+  const char block[] =
+      "int rpc_port_set_##_port(rpc_port_##_h h, rpc_port_h port)\n" \
+      "{\n" \
+      "    if (!h || !port) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    h->port = port;\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContext(std::ofstream& stream,
+                                       const Interface& inf) {
+  GenInterfaceContextDeclaration(stream, inf);
+  GenInterfaceContextConstructor(stream, inf);
+  GenInterfaceContextDestructor(stream, inf);
+  GenInterfaceContextFinder(stream, inf);
+  GenInterfaceContextTagSetter(stream, inf);
+  GenInterfaceContextTagGetter(stream, inf);
+  GenInterfaceContextSenderGetter(stream, inf);
+  GenInterfaceContextPortExist(stream, inf);
+}
+
+void CStubBodyGen::GenInterfaceContextDeclaration(std::ofstream& stream,
+                                                  const Interface& inf) {
+  const char block[] =
+      "struct ##_context_s {\n" \
+      "    char* sender;\n" \
+      "    char* instance;\n" \
+      "    rpc_port_h port;\n" \
+      "    void* tag;\n" \
+      "    rpc_port_stub_##_callback_s callback;\n" \
+      "    void* user_data;\n" \
+      "};\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextConstructor(std::ofstream& stream,
+                                                  const Interface& inf) {
+  const char block[] =
+      "static struct ##_context_s* __create_##_context(const char* sender, const char* instance)\n" \
+      "{\n" \
+      "    struct ##_context_s* handle;\n" \
+      "\n"
+      "    handle = calloc(1, sizeof(struct ##_context_s));\n" \
+      "    if (!handle) {\n" \
+      "        LOGE(\"Out of memory\");\n" \
+      "        return NULL;\n" \
+      "    }\n" \
+      "\n" \
+      "    handle->sender = strdup(sender);\n" \
+      "    if (!handle->sender) {\n" \
+      "        LOGE(\"Out of memory\");\n" \
+      "        free(handle);\n" \
+      "        return NULL;\n" \
+      "    }\n" \
+      "\n" \
+      "    handle->instance = strdup(instance);\n" \
+      "    if (!handle->instance) {\n" \
+      "        LOGE(\"Out of memory\");\n" \
+      "        free(handle->sender);\n" \
+      "        free(handle);\n" \
+      "        return NULL;\n" \
+      "    }\n" \
+      "\n" \
+      "    handle->callback = __##_callback;\n"\
+      "    handle->user_data = __##_user_data;\n" \
+      "\n" \
+      "    return handle;\n" \
+      "}\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextDestructor(std::ofstream& stream,
+                                                 const Interface& inf) {
+  const char block[] =
+      "static void __destroy_##_context(gpointer data)\n" \
+      "{\n" \
+      "    struct ##_context_s* handle = data;\n" \
+      "\n" \
+      "    if (!handle) {\n" \
+      "        LOGE(\"Critical error!\");\n" \
+      "        return;\n" \
+      "    }\n" \
+      "\n" \
+      "    free(handle->instance);\n" \
+      "    free(handle->sender);\n" \
+      "    free(handle);\n" \
+      "}\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextFinder(std::ofstream& stream,
+                                             const Interface& inf) {
+  const char block[] =
+      "static struct ##_context_s* __find_##_context(const char* instance)\n" \
+      "{\n" \
+      "    struct ##_context_s* handle;\n" \
+      "    GList* iter;\n" \
+      "\n" \
+      "    iter = __##_contexts;\n" \
+      "    while (iter) {\n" \
+      "        handle = (struct ##_context_s*)iter->data;\n" \
+      "        if (!strcmp(handle->instance, instance))\n" \
+      "            return handle;\n" \
+      "        iter = g_list_next(iter);\n" \
+      "    }\n" \
+      "\n" \
+      "    return NULL;\n" \
+      "}\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextTagSetter(std::ofstream& stream,
+                                                const Interface& inf) {
+  const char block[] =
+      "int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void* tag)\n" \
+      "{\n" \
+      "    if (!ctx) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    ctx->tag = tag;\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextTagGetter(std::ofstream& stream,
+                                                const Interface& inf) {
+  const char block[] =
+      "int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void** tag)\n" \
+      "{\n" \
+      "    if (!ctx || !tag) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    *tag = ctx->tag;\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextSenderGetter(std::ofstream& stream,
+                                                   const Interface& inf) {
+  const char block[] =
+      "int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char** sender)\n" \
+      "{\n" \
+      "    if (!ctx || !sender) {\n" \
+      "        LOGE(\"Invalid parameter\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    *sender = strdup(ctx->sender);\n" \
+      "    if (*sender == NULL) {\n" \
+      "        LOGE(\"Out of memory\");\n" \
+      "        return -1;\n" \
+      "    }\n" \
+      "\n" \
+      "    return 0;\n" \
+      "}\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextPortExist(std::ofstream& stream,
+                                                const Interface& inf) {
+  const char block[] =
+      "static bool __##_context_port_exist(rpc_port_h port)\n" \
+      "{\n" \
+      "    struct ##_context_s* handle;\n" \
+      "    GList* iter;\n" \
+      "\n" \
+      "    iter = __##_contexts;\n" \
+      "    while (iter) {\n" \
+      "        handle = (struct ##_context_s*)iter->data;\n" \
+      "        if (handle->port == port)\n" \
+      "            return true;\n" \
+      "        iter = g_list_next(iter);\n" \
+      "    }\n" \
+      "\n" \
+      "    return false;\n" \
+      "}\n";
+  stream << NLine(1);
+  stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
 }  // namespace tidl
index ab92c56..11a7b60 100644 (file)
@@ -31,6 +31,75 @@ class CStubBodyGen : public CBodyGeneratorBase {
 
   void OnInitGen(std::ofstream& stream) override;
   void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceMethods(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceMethodTable(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceOnConnectedEventCB(std::ofstream& stream,
+                                      const Interface& inf);
+  void GenInterfaceOnDisconnectedEventCB(std::ofstream& stream,
+                                         const Interface& inf);
+  void GenInterfaceOnReceivedEventCB(std::ofstream& stream,
+                                     const Interface& inf);
+  void GenInterfaceRegister(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceUnregister(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceGlobalVariables(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceContext(std::ofstream& stream, const Interface& inf);
+
+ private:
+  void GenInterfaceContextDeclaration(std::ofstream& stream,
+                                      const Interface& inf);
+  void GenInterfaceContextConstructor(std::ofstream& stream,
+                                      const Interface& inf);
+  void GenInterfaceContextDestructor(std::ofstream& stream,
+                                     const Interface& inf);
+  void GenInterfaceContextFinder(std::ofstream& stream,
+                                 const Interface& inf);
+  void GenInterfaceContextTagSetter(std::ofstream& stream,
+                                    const Interface& inf);
+  void GenInterfaceContextTagGetter(std::ofstream& stream,
+                                    const Interface& inf);
+  void GenInterfaceContextSenderGetter(std::ofstream& stream,
+                                       const Interface& inf);
+  void GenInterfaceContextPortExist(std::ofstream& stream,
+                                    const Interface& inf);
+
+ private:
+  void GenInterfaceDelegator(std::ofstream& stream, const std::string& id,
+                             const Declaration& decl);
+  void GenInterfaceDelegatorDeclaration(std::ofstream& stream,
+                                        const std::string& id,
+                                       const Declaration& decl);
+  void GenInterfaceDelegatorConstructor(std::ofstream& stream,
+                                      const std::string& id,
+                                       const Declaration& decl);
+  void GenInterfaceDelegatorDestructor(std::ofstream& stream,
+                                      const std::string& id,
+                                      const Declaration& decl);
+  void GenInterfaceDelegatorSerializer(std::ofstream& stream,
+                                      const std::string& id,
+                                      const Declaration& decl);
+  void GenInterfaceDelegatorDeserializer(std::ofstream& stream,
+                                        const std::string& id,
+                                        const Declaration& decl);
+  void GenInterfaceDelegatorCloner(std::ofstream& stream,
+                                  const std::string& id,
+                                  const Declaration& decl);
+  void GenInterfaceDelegatorInvoker(std::ofstream& stream,
+                                   const std::string& id,
+                                   const Declaration& decl);
+  void GenInterfaceDelegatorPortSetter(std::ofstream& stream,
+                                       const std::string& id,
+                                       const Declaration& decl);
+
+ private:
+  std::string GetMethodString(const Interface& id, const Declaration& decl);
+  std::string GetAddEventCBString(const std::string& id);
+  std::string GetAddPrivilegeString(const std::string& id,
+                                    const Attribute& attr);
 };
 
 }  // namespace tidl
index 5d54ef8..cfcf6ab 100644 (file)
@@ -27,10 +27,188 @@ void CStubHeaderGen::OnInitGen(std::ofstream& stream) {
   GenIncludeDefaultHeaders(stream, false);
   GenExplicitLinkageOpen(stream);
   GenStructures(stream);
+  GenInterfaces(stream);
 }
 
 void CStubHeaderGen::OnFiniGen(std::ofstream& stream) {
   GenExplicitLinkageClose(stream);
 }
 
+void CStubHeaderGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+
+    const Interface &inf = static_cast<const Interface&>(*i);
+    GenInterface(stream, inf);
+  }
+}
+
+void CStubHeaderGen::GenInterface(std::ofstream& stream,
+                                  const Interface& inf) {
+  GenInterfaceContext(stream, inf);
+  GenInterfaceDelegators(stream, inf);
+  GenInterfaceDeclaration(stream, inf);
+  GenInterfaceRegister(stream, inf);
+  GenInterfaceUnregister(stream, inf);
+}
+
+void CStubHeaderGen::GenInterfaceDeclaration(std::ofstream& stream,
+                                             const Interface& inf) {
+  const char callback[] = "$$ (*$$)(rpc_port_stub_Message_context_h context, $$void *user_data);\n";
+  const char block[] =
+      "typedef struct {\n" \
+      "    void (*create)(rpc_port_stub_##_context_h context, void* user_data);\n" \
+      "    void (*terminate)(rpc_port_stub_##_context_h context, void* user_data);\n" \
+      "    $$" \
+      "} rpc_port_stub_##_callback_s;\n";
+  stream << NLine(1);
+  stream << SmartIndent(GenTemplateString(ReplaceAll(block, "##", inf.GetID()),
+        [&]()->std::string {
+          std::string str;
+          for (auto& i: inf.GetDeclarations().GetDecls()) {
+            if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+              continue;
+            str += GenTemplateString(callback,
+                [&]()->std::string {
+                  return GetReturnTypeString(i->GetType());
+                },
+                [&]()->std::string {
+                  return i->GetID();
+                },
+                [&]()->std::string {
+                  std::string s;
+                  for (auto& p : i->GetParameters().GetParams()) {
+                    if (TypeIsDelegator(inf, p->GetParameterType().GetBaseType())) {
+                      s += GetParcelParamTypeString(p->GetParameterType().GetBaseType()) +
+                          " " + p->GetID();
+                    } else {
+                      s += GetParamTypeString(p->GetParameterType().GetDirection(),
+                          p->GetParameterType().GetBaseType()) + " " + p->GetID();
+                    }
+                    s += ", ";
+                  }
+                  return s;
+                }
+                );
+          }
+          return str;
+        }
+        )
+      );
+}
+
+void CStubHeaderGen::GenInterfaceContext(std::ofstream& stream,
+                                         const Interface& inf) {
+  GenInterfaceContextDeclaration(stream, inf);
+  GenInterfaceContextTagSetter(stream, inf);
+  GenInterfaceContextTagGetter(stream, inf);
+  GenInterfaceContextSenderGetter(stream, inf);
+}
+
+void CStubHeaderGen::GenInterfaceContextDeclaration(
+    std::ofstream& stream, const Interface& inf) {
+  const char format[] = "typedef struct ##_context_s* rpc_port_stub_##_context_h;\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceContextTagSetter(
+    std::ofstream& stream, const Interface& inf) {
+  const char format[] =
+      "int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void* tag);\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceContextTagGetter(
+    std::ofstream& stream, const Interface& inf) {
+  const char format[] =
+      "int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void** tag);\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceContextSenderGetter(
+    std::ofstream& stream, const Interface& inf) {
+  const char format[] =
+      "int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char** sender);\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegators(std::ofstream& stream,
+                                            const Interface& inf) {
+  for (auto& i : inf.GetDeclarations().GetDecls()) {
+    if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+      continue;
+    GenInterfaceDelegator(stream, inf.GetID(), *i);
+  }
+}
+
+void CStubHeaderGen::GenInterfaceDelegator(std::ofstream& stream,
+                                           const std::string& id,
+                                           const Declaration& decl) {
+  GenInterfaceDelegatorDeclaration(stream, id, decl);
+  GenInterfaceDelegatorDestructor(stream, id, decl);
+  GenInterfaceDelegatorCloner(stream, id, decl);
+  GenInterfaceDelegatorInvoker(stream, id, decl);
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorDeclaration(
+    std::ofstream& stream, const std::string& id, const Declaration& decl) {
+  const char format[] = "typedef struct ##_s* rpc_port_##_h;\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", decl.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorDestructor(
+    std::ofstream& stream, const std::string& id, const Declaration& decl) {
+  const char format[] =
+      "int rpc_port_destroy_##(rpc_port_##_h h);\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", decl.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorCloner(
+    std::ofstream& stream, const std::string& id, const Declaration& decl) {
+  const char format[] =
+      "int rpc_port_clone_##(rpc_port_##_h h, rpc_port_##_h* clone);\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", decl.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorInvoker(
+    std::ofstream& stream, const std::string& id, const Declaration& decl) {
+  const char format[] =
+      "int rpc_port_invoke_##(rpc_port_##_h h$$);\n";
+  stream << NLine(1);
+  stream << GenTemplateString(ReplaceAll(format, "##", decl.GetID()),
+      [&]()->std::string {
+        std::string str;
+        for (auto& i : decl.GetParameters().GetParams()) {
+          str += ", ";
+          str += GetParamTypeString(i->GetParameterType().GetDirection(),
+              i->GetParameterType().GetBaseType()) + " " + i->GetID();
+        }
+        return str;
+      }
+      );
+}
+
+void CStubHeaderGen::GenInterfaceRegister(std::ofstream& stream,
+                                          const Interface& inf) {
+  const char format[] =
+      "int rpc_port_stub_##_register(rpc_port_stub_##_callback_s* callback, void* user_data);\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceUnregister(std::ofstream& stream,
+                                            const Interface& inf) {
+  const char format[] = "int rpc_port_stub_##_unregister(void);\n";
+  stream << NLine(1);
+  stream << ReplaceAll(format, "##", inf.GetID());
+}
+
 }  // namespace tidl
index b4cc89b..2359cef 100644 (file)
@@ -31,6 +31,42 @@ class CStubHeaderGen : public CHeaderGeneratorBase {
 
   void OnInitGen(std::ofstream& stream) override;
   void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceContext(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceDelegators(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceRegister(std::ofstream& stream, const Interface& inf);
+  void GenInterfaceUnregister(std::ofstream& stream, const Interface& inf);
+
+ private:
+  void GenInterfaceContextDeclaration(std::ofstream& stream,
+                                      const Interface& inf);
+  void GenInterfaceContextTagSetter(std::ofstream& stream,
+                                    const Interface& inf);
+  void GenInterfaceContextTagGetter(std::ofstream& stream,
+                                    const Interface& inf);
+  void GenInterfaceContextSenderGetter(std::ofstream& stream,
+                                       const Interface& inf);
+
+ private:
+  void GenInterfaceDelegator(std::ofstream& stream,
+                             const std::string& id,
+                             const Declaration& decl);
+  void GenInterfaceDelegatorDeclaration(std::ofstream& stream,
+                                        const std::string& id,
+                                        const Declaration& decl);
+  void GenInterfaceDelegatorDestructor(std::ofstream& stream,
+                                      const std::string& id,
+                                      const Declaration& decl);
+  void GenInterfaceDelegatorCloner(std::ofstream& stream,
+                                  const std::string& id,
+                                  const Declaration& decl);
+  void GenInterfaceDelegatorInvoker(std::ofstream& stream,
+                                   const std::string& id,
+                                   const Declaration& decl);
 };
 
 }  // namespace tidl