Implement cpp group generator 83/277483/11
authorjh9216.park <jh9216.park@samsung.com>
Thu, 7 Jul 2022 10:25:54 +0000 (06:25 -0400)
committerjh9216.park <jh9216.park@samsung.com>
Tue, 12 Jul 2022 06:51:49 +0000 (02:51 -0400)
Change-Id: I4348aa75ed30d666bf1ae794ad6690a13fe8bb17
Signed-off-by: jh9216.park <jh9216.park@samsung.com>
16 files changed:
Makefile.dibs
idlc/ast/tidlc_y.cpp
idlc/gen/cpp_gen_base.cc
idlc/gen/cpp_gen_base.h
idlc/gen/cpp_group_body_gen.cc [new file with mode: 0644]
idlc/gen/cpp_group_body_gen.h [new file with mode: 0644]
idlc/gen/cpp_group_body_gen_cb.h [new file with mode: 0644]
idlc/gen/cpp_group_header_gen.cc [new file with mode: 0644]
idlc/gen/cpp_group_header_gen.h [new file with mode: 0644]
idlc/gen/cpp_group_header_gen_cb.h [new file with mode: 0644]
idlc/main.cc
idlc/options.cc
packaging/tidl.spec
tests/build_tests/CMakeLists.txt
tests/build_tests/prebuild.sh
tests/build_tests/tidl/FooPubsub.tidl [new file with mode: 0755]

index dc53155..d62cd68 100644 (file)
@@ -23,6 +23,8 @@ SRC_FILES := \
        idlc/gen/cpp_proxy_header_gen.cc \
        idlc/gen/cpp_stub_body_gen.cc \
        idlc/gen/cpp_stub_header_gen.cc \
+       idlc/gen/cpp_group_body_gen.cc \
+       idlc/gen/cpp_group_header_gen.cc \
        idlc/gen/cs_gen_base.cc \
        idlc/gen/cs_lib_gen.cc \
        idlc/gen/cs_proxy_gen.cc \
index 4df31eb..87d502d 100644 (file)
@@ -385,13 +385,13 @@ static const yytype_int8 yytranslate[] =
 static const yytype_int16 yyrline[] =
 {
        0,    96,    96,   101,   106,   120,   123,   128,   134,   139,
-     145,   152,   158,   169,   175,   180,   184,   188,   194,   200,
-     211,   217,   222,   228,   235,   241,   249,   254,   259,   266,
-     272,   283,   289,   302,   310,   325,   330,   335,   340,   344,
-     348,   352,   356,   362,   368,   379,   385,   388,   391,   396,
-     399,   403,   409,   412,   418,   421,   438,   441,   445,   449,
-     453,   457,   461,   465,   469,   479,   483,   487,   493,   500,
-     504
+     145,   152,   160,   171,   177,   182,   186,   190,   196,   204,
+     215,   221,   226,   232,   239,   245,   253,   258,   263,   270,
+     278,   289,   295,   308,   316,   331,   336,   341,   346,   350,
+     354,   358,   362,   368,   376,   387,   393,   396,   399,   404,
+     407,   411,   417,   420,   426,   429,   446,   449,   453,   457,
+     461,   465,   469,   473,   477,   487,   491,   495,   501,   508,
+     512
 };
 #endif
 
@@ -1336,14 +1336,16 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
                   {
     ((*yyvalp).elms) = new (std::nothrow) tidl::Elements();
     if (((*yyvalp).elms) != nullptr) {
-      ((*yyvalp).elms)->Add(std::unique_ptr<tidl::Element>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.elm)));
+      if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.elm) != nullptr) {
+        ((*yyvalp).elms)->Add(std::unique_ptr<tidl::Element>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.elm)));
+      }
     }
   }
-#line 1343 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1345 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 12:
-#line 158 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 160 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                      {
     ((*yyvalp).elms) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.elms);
     if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.elm) != nullptr) {
@@ -1355,68 +1357,70 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
       }
     }
   }
-#line 1359 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1361 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 13:
-#line 169 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 171 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                {
     ps->ReportError("syntax error in elements declarations.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yyloc).begin.line);
     ((*yyvalp).elms) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.elms);
   }
-#line 1368 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1370 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 14:
-#line 175 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 177 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                    {
     ((*yyvalp).elm) = new tidl::Element((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.b_type), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.b_type)->GetComments(),
         (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yyloc).begin.line);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.token);
   }
-#line 1378 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1380 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 15:
-#line 180 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 182 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                          {
     ps->ReportError("syntax error. \"No identifier\".", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
     ((*yyvalp).elm) = NULL;
   }
-#line 1387 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1389 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 16:
-#line 184 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 186 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                {
     ps->ReportError("syntax error in element declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yyloc).begin.line);
     ((*yyvalp).elm) = NULL;
   }
-#line 1396 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1398 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 17:
-#line 188 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 190 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
           {
     ps->ReportError("syntax error in element declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
     ((*yyvalp).elm) = NULL;
   }
-#line 1405 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1407 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 18:
-#line 194 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 196 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                       {
     ((*yyvalp).attrs) = new (std::nothrow) tidl::Attributes();
     if (((*yyvalp).attrs) != nullptr) {
-      ((*yyvalp).attrs)->Add(std::unique_ptr<tidl::Attribute>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.attr)));
+      if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.attr) != nullptr) {
+        ((*yyvalp).attrs)->Add(std::unique_ptr<tidl::Attribute>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.attr)));
+      }
     }
   }
-#line 1416 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1420 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 19:
-#line 200 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 204 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                  {
     ((*yyvalp).attrs) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.attrs);
     if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.attr) != nullptr) {
@@ -1428,62 +1432,62 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
       }
     }
   }
-#line 1432 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1436 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 20:
-#line 211 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 215 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
           {
     ps->ReportError("syntax error in attributes", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
     ((*yyvalp).attrs) = new tidl::Attributes();
   }
-#line 1441 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1445 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 21:
-#line 217 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 221 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                 {
     ((*yyvalp).attr) = new tidl::Attribute((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yyloc).begin.line);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.token);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
   }
-#line 1451 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1455 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 22:
-#line 222 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 226 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                         {
     ps->ReportError("syntax error in attribute declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yyloc).begin.line);
     ((*yyvalp).attr) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.token);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
   }
-#line 1462 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1466 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 23:
-#line 228 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 232 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                        {
     ps->ReportError("syntax error in attribute declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
     ((*yyvalp).attr) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.token);
   }
-#line 1472 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1476 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 24:
-#line 235 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 239 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                           {
     ((*yyvalp).interf) = new tidl::Interface((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.decls), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yysemantics.yysval.token)->GetComments(),
         new tidl::Attributes(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yyloc).begin.line);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yysemantics.yysval.token);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token);
   }
-#line 1483 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1487 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 25:
-#line 241 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 245 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                                              {
     ((*yyvalp).interf) = new tidl::Interface((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.decls), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-7)].yystate.yysemantics.yysval.token)->GetComments(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-6)].yystate.yysemantics.yysval.attrs),
         (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-7)].yystate.yyloc).begin.line);
@@ -1492,52 +1496,54 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yysemantics.yysval.token);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token);
   }
-#line 1496 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1500 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 26:
-#line 249 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 253 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                         {
     ps->ReportError("syntax error. \"No identifier\".", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yyloc).begin.line);
     ((*yyvalp).interf) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token);
   }
-#line 1506 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1510 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 27:
-#line 254 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 258 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                               {
     ps->ReportError("syntax error in interface declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yyloc).begin.line);
     ((*yyvalp).interf) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yysemantics.yysval.token);
   }
-#line 1516 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1520 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 28:
-#line 259 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 263 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                     {
     ps->ReportError("syntax error in interface declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yyloc).begin.line);
     ((*yyvalp).interf) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.token);
   }
-#line 1526 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1530 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 29:
-#line 266 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 270 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                           {
     ((*yyvalp).decls) = new (std::nothrow) tidl::Declarations();
     if (((*yyvalp).decls) != nullptr) {
-      ((*yyvalp).decls)->Add(std::unique_ptr<tidl::Declaration>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.decl)));
+      if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.decl) != nullptr) {
+        ((*yyvalp).decls)->Add(std::unique_ptr<tidl::Declaration>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.decl)));
+      }
     }
   }
-#line 1537 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1543 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 30:
-#line 272 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 278 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                              {
     ((*yyvalp).decls) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.decls);
     if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.decl) != nullptr) {
@@ -1549,20 +1555,20 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
       }
     }
   }
-#line 1553 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1559 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 31:
-#line 283 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 289 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                    {
     ps->ReportError("syntax error in methods declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yyloc).begin.line);
     ((*yyvalp).decls) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.decls);
   }
-#line 1562 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1568 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 32:
-#line 289 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 295 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                       {
     if (ps->IsGroupEnabled()) {
       ps->ReportError("Group does not support 'sync' method type", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yyloc).begin.line);
@@ -1576,11 +1582,11 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yysemantics.yysval.token);
     }
   }
-#line 1580 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1586 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 33:
-#line 302 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 308 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                   {
     ((*yyvalp).decl) = new tidl::Declaration((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yysemantics.yysval.token)->ToString(),
         std::unique_ptr<tidl::BaseType>(new tidl::BaseType("void", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-6)].yystate.yysemantics.yysval.token)->GetComments())),
@@ -1589,11 +1595,11 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-6)].yystate.yysemantics.yysval.token);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yysemantics.yysval.token);
   }
-#line 1593 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1599 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 34:
-#line 310 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 316 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                      {
     if (ps->IsGroupEnabled()) {
       ps->ReportError("Group does not support 'delegate' method type", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-6)].yystate.yyloc).begin.line);
@@ -1609,97 +1615,99 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yysemantics.yysval.token);
     }
   }
-#line 1613 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1619 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 35:
-#line 325 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 331 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                      {
     ps->ReportError("syntax error in method declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yysemantics.yysval.token);
   }
-#line 1623 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1629 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 36:
-#line 330 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 336 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                         {
     ps->ReportError("syntax error in method declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-5)].yystate.yysemantics.yysval.token);
   }
-#line 1633 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1639 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 37:
-#line 335 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 341 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                           {
     ps->ReportError("syntax error. \"No async\".", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yysemantics.yysval.token);
   }
-#line 1643 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1649 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 38:
-#line 340 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 346 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                         {
     ps->ReportError("syntax error. \"No identifier\".", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
   }
-#line 1652 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1658 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 39:
-#line 344 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 350 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                              {
     ps->ReportError("syntax error. \"No identifier\".", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
   }
-#line 1661 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1667 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 40:
-#line 348 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 354 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                 {
     ps->ReportError("syntax error. \"No identifier\".", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-4)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
   }
-#line 1670 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1676 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 41:
-#line 352 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 358 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                 {
     ps->ReportError("syntax error in method declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
   }
-#line 1679 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1685 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 42:
-#line 356 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 362 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                              {
     ps->ReportError("syntax error in method declaration.", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yyloc).begin.line);
     ((*yyvalp).decl) = NULL;
   }
-#line 1688 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1694 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 43:
-#line 362 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 368 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                           {
     ((*yyvalp).params) = new tidl::Parameters();
-    if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.param) != nullptr) {
-      ((*yyvalp).params)->Add(std::unique_ptr<tidl::Parameter>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.param)));
+    if (((*yyvalp).params) != nullptr) {
+      if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.param) != nullptr) {
+        ((*yyvalp).params)->Add(std::unique_ptr<tidl::Parameter>((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.param)));
+      }
     }
   }
-#line 1699 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1707 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 44:
-#line 368 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 376 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                      {
     ((*yyvalp).params) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-2)].yystate.yysemantics.yysval.params);
     if ((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.param) != nullptr) {
@@ -1711,95 +1719,95 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
       }
     }
   }
-#line 1715 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1723 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 45:
-#line 379 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 387 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
           {
     ps->ReportError("syntax error in parameter list", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
     ((*yyvalp).params) = new tidl::Parameters();
   }
-#line 1724 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1732 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 46:
-#line 385 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 393 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                           {
     ((*yyvalp).direction) = new tidl::Token("in", "");
   }
-#line 1732 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1740 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 47:
-#line 388 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 396 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
           {
     ((*yyvalp).direction) = new tidl::Token("out", "");
   }
-#line 1740 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1748 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 48:
-#line 391 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 399 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
           {
     ((*yyvalp).direction) = new tidl::Token("ref", "");
   }
-#line 1748 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1756 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 49:
-#line 396 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 404 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
            {
     ((*yyvalp).param) = nullptr;
   }
-#line 1756 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1764 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 50:
-#line 399 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 407 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
            {
     ((*yyvalp).param) = nullptr;
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
   }
-#line 1765 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1773 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 51:
-#line 403 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 411 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                         {
     ((*yyvalp).param) = new tidl::Parameter((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.p_type), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yyloc).begin.line);
     delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
   }
-#line 1774 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1782 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 52:
-#line 409 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 417 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                           {
       ((*yyvalp).p_type) = new tidl::ParameterType((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.b_type));
     }
-#line 1782 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1790 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 53:
-#line 412 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 420 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                     {
       ((*yyvalp).p_type) = new tidl::ParameterType((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.b_type), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.direction)->ToString());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.direction);
     }
-#line 1791 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1799 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 54:
-#line 418 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 426 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                     {
       ((*yyvalp).b_type) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.b_type);
     }
-#line 1799 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1807 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 55:
-#line 421 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 429 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
              {
       if (ps->IsGroupEnabled()) {
         ps->ReportError("Group does not support 'file' type", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
@@ -1815,82 +1823,82 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
         delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
       }
     }
-#line 1819 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1827 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 56:
-#line 438 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 446 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                          {
       ((*yyvalp).b_type) = (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.b_type);
     }
-#line 1827 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1835 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 57:
-#line 441 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 449 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
              {
       ((*yyvalp).b_type) = new tidl::BaseType("void", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1836 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1844 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 58:
-#line 445 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 453 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
              {
       ((*yyvalp).b_type) = new tidl::BaseType("char", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1845 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1853 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 59:
-#line 449 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 457 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
               {
       ((*yyvalp).b_type) = new tidl::BaseType("short", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1854 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1862 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 60:
-#line 453 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 461 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
             {
       ((*yyvalp).b_type) = new tidl::BaseType("int", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1863 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1871 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 61:
-#line 457 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 465 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
              {
       ((*yyvalp).b_type) = new tidl::BaseType("long", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1872 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1880 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 62:
-#line 461 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 469 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
               {
       ((*yyvalp).b_type) = new tidl::BaseType("float", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1881 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1889 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 63:
-#line 465 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 473 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                {
       ((*yyvalp).b_type) = new tidl::BaseType("double", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1890 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1898 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 64:
-#line 469 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 477 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                {
       if (ps->IsCionEnabled()) {
         ps->ReportError("Cion does not support 'bundle' type", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yyloc).begin.line);
@@ -1901,66 +1909,66 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
         delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
       }
     }
-#line 1905 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1913 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 65:
-#line 479 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 487 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                {
       ((*yyvalp).b_type) = new tidl::BaseType("string", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1914 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1922 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 66:
-#line 483 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 491 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
              {
       ((*yyvalp).b_type) = new tidl::BaseType("bool", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1923 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1931 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 67:
-#line 487 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 495 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
            {
       ((*yyvalp).b_type) = new tidl::BaseType((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments(), true);
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1932 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1940 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 68:
-#line 493 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 501 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                                                                        {
       ((*yyvalp).b_type) = new tidl::BaseType((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token)->ToString(), (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token)->GetComments());
       ((*yyvalp).b_type)->SetMetaType((YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-1)].yystate.yysemantics.yysval.b_type));
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (-3)].yystate.yysemantics.yysval.token);
     }
-#line 1942 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1950 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 69:
-#line 500 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 508 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
                             {
       ((*yyvalp).token) = new tidl::Token("list", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1951 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1959 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
   case 70:
-#line 504 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 512 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
               {
       ((*yyvalp).token) = new tidl::Token("array", (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token)->GetComments());
       delete (YY_CAST (yyGLRStackItem const *, yyvsp)[YYFILL (0)].yystate.yysemantics.yysval.token);
     }
-#line 1960 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1968 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
     break;
 
 
-#line 1964 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 1972 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
 
       default: break;
     }
@@ -3422,7 +3430,7 @@ yyparse (yy::parser& yyparser, tidl::Parser* ps)
 
   // User initialization code.
 yylloc.initialize ();
-#line 3426 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 3434 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
 
 
   if (! yyinitGLRStack (yystackp, YYINITDEPTH))
@@ -3710,7 +3718,7 @@ yypdumpstack (yyGLRStack* yystackp)
 
 
 
-#line 510 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
+#line 518 "/home/gogo/work/tidl/idlc/ast/tidlc.yy"
 
 
 #include <ctype.h>
@@ -3722,7 +3730,7 @@ void yy::parser::error(const yy::parser::location_type& l,
 }
 
 
-#line 3726 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 3734 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
 
 /*------------------.
 | Report an error.  |
@@ -3738,7 +3746,7 @@ yyerror (const yy::parser::location_type *yylocationp, yy::parser& yyparser, tid
 
 
 namespace yy {
-#line 3742 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 3750 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
 
   /// Build a parser object.
   parser::parser (tidl::Parser* ps_yyarg)
@@ -3826,4 +3834,4 @@ namespace yy {
 
 #endif
 } // yy
-#line 3830 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
+#line 3838 "/home/gogo/work/tidl/idlc/ast/tidlc_y.cpp"
index 5b606bd..9aafedd 100644 (file)
@@ -61,19 +61,26 @@ CppGeneratorBase::CppGeneratorBase(std::shared_ptr<Document> doc)
 }
 
 void CppGeneratorBase::GenStructuresForHeader(std::ofstream& stream) {
-  stream << CB_BUNDLE;
-  stream << CB_FILE;
+  stream << GetStructuresForHeader();
+}
+
+std::string CppGeneratorBase::GetStructuresForHeader() {
+  std::string str;
+
+  str += CB_BUNDLE;
+  str += CB_FILE;
   for (auto& i : GetDocument().GetBlocks()) {
     if (i->GetType() != Block::TYPE_STRUCTURE)
       continue;
     Structure& st = static_cast<Structure&>(*i);
-    GenStructureForHeader(stream, st);
+    str += GetStructureForHeader(st);
   }
+
+  return str;
 }
 
-void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream,
-                                             const Structure& st) {
-  ReplaceAll(CB_STRUCTURE_FOR_HEADER)
+std::string CppGeneratorBase::GetStructureForHeader(const Structure& st) {
+  return std::string(ReplaceAll(CB_STRUCTURE_FOR_HEADER)
       .Change("<CLS_NAME>", st.GetID())
       .Change("<PARAMS>", [&]() {
         std::string str;
@@ -111,8 +118,7 @@ void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream,
         }
         str += NLine(1);
         return str;
-      })
-      .Out(stream);
+      }));
 }
 
 std::string CppGeneratorBase::GetSetter(const Element& ele) {
@@ -389,7 +395,11 @@ void CppGeneratorBase::GenListSerializer(std::ofstream& stream, bool proto) {
 
 void CppGeneratorBase::GenMethodId(std::ofstream& stream,
                                    const Interface& iface) {
-  ReplaceAll(CB_METHOD_IDS)
+  stream << GetMethodId(iface);
+}
+
+std::string CppGeneratorBase::GetMethodId(const Interface& iface) {
+  return std::string(ReplaceAll(CB_METHOD_IDS)
       .Change("<IDS>", [&]() {
         std::string str;
         int cnt = 2;
@@ -402,8 +412,7 @@ void CppGeneratorBase::GenMethodId(std::ofstream& stream,
 
         return str;
       })
-      .AddIndent(TAB_SIZE)
-      .Out(stream);
+      .AddIndent(TAB_SIZE));
 }
 
 void CppGeneratorBase::GenDelegateId(std::ofstream& stream,
index de96d9f..0d32993 100644 (file)
@@ -34,12 +34,14 @@ class CppGeneratorBase : public Generator {
 
   void GenVersion(std::ofstream& stream);
   void GenStructuresForHeader(std::ofstream& stream);
+  std::string GetStructuresForHeader();
   void GenStructuresForBody(std::ofstream& stream);
   void GenSerializer(std::ofstream& stream);
   void GenDeSerializer(std::ofstream& stream);
   void GenListSerializer(std::ofstream& stream, bool proto = false);
   void GenPrototype(std::ofstream& stream);
   void GenMethodId(std::ofstream& stream, const Interface& iface);
+  std::string GetMethodId(const Interface& iface);
   void GenDelegateId(std::ofstream& stream, const Interface& iface);
   void GenParameters(std::ofstream& stream, const Parameters& ps);
   void GenBodyCallbacks(std::ofstream& stream, const Interface& iface,
@@ -70,7 +72,7 @@ class CppGeneratorBase : public Generator {
                        bool proto = false);
   void GenSerializer(std::ofstream& stream, const Structure& st,
                      bool proto = false);
-  void GenStructureForHeader(std::ofstream& stream, const Structure& st);
+  std::string GetStructureForHeader(const Structure& st);
   void GenStructureForBody(std::ofstream& stream, const Structure& st);
   void GenBodyCallback(std::ofstream& stream, const Interface& iface,
                        const Declaration& decl, bool is_proxy);
diff --git a/idlc/gen/cpp_group_body_gen.cc b/idlc/gen/cpp_group_body_gen.cc
new file mode 100644 (file)
index 0000000..4b1ce7a
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "idlc/gen/cpp_group_body_gen.h"
+
+namespace {
+#include "idlc/gen/cpp_group_body_gen_cb.h"
+}
+
+namespace tidl {
+
+CppGroupBodyGen::CppGroupBodyGen(std::shared_ptr<Document> doc)
+    : CppGeneratorBase(doc) {}
+
+void CppGroupBodyGen::OnInitGen(std::ofstream& stream) {
+  std::string key(".cc");
+  std::string header_file = FileName;
+  std::size_t found = header_file.rfind(key);
+  if (found != std::string::npos)
+    header_file.replace(found, key.length(), ".h");
+
+  GenVersion(stream);
+
+  ReplaceAll(CB_HEADER)
+      .Change("<HEADER_FILE>", header_file)
+      .Out(stream);
+
+  GenLogTag(stream, "RPC_PORT_GROUP");
+  GenLogDefinition(stream);
+  GenVersionDefinition(stream);
+  stream << NLine(1);
+  GenNamespace(stream);
+}
+
+void CppGroupBodyGen::OnFiniGen(std::ofstream& stream) {
+}
+
+void CppGroupBodyGen::GenNamespace(std::ofstream& stream) {
+  stream << "namespace rpc_port ";
+  GenBrace(stream, 0, [&]() {
+    stream << "namespace " << GetFileNamespace() << " ";
+    GenBrace(stream, 0, [&]() {
+      stream <<  NLine(1);
+      GenStructuresForBody(stream);
+      stream << "namespace group ";
+      GenBrace(stream, 0, [&]() {
+        GenPrototype(stream);
+        GenSerializer(stream);
+        GenDeSerializer(stream);
+        GenListSerializer(stream);
+        GenInterfaces(stream);
+      }, false, false);
+      stream << "  // namespace group" + NLine(1);
+    }, false, false);
+    stream << "  // namespace " + GetFileNamespace() + NLine(1);
+  }, false, false);
+  stream << "  // namespace rpc_port" + NLine(1);
+}
+
+void CppGroupBodyGen::GenInterfaces(std::ofstream& stream) {
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+    Interface& iface = static_cast<Interface&>(*i);
+    GenInterface(stream, iface);
+  }
+}
+
+void CppGroupBodyGen::GenInterface(std::ofstream& stream,
+                                   const Interface& iface) {
+  GenConstructor(stream, iface);
+  GenDestructor(stream, iface);
+  GenHelperMethods(stream, iface);
+  GenMethods(stream, iface);
+}
+
+void CppGroupBodyGen::GenConstructor(std::ofstream& stream,
+                                     const Interface& iface) {
+  ReplaceAll(CB_INTERFACE_CTOR)
+      .Change("<CLS_NAME>", iface.GetID())
+      .Out(stream);
+}
+
+void CppGroupBodyGen::GenDestructor(std::ofstream& stream,
+                                    const Interface& iface) {
+  ReplaceAll(CB_INTERFACE_DTOR)
+      .Change("<CLS_NAME>", iface.GetID())
+      .Out(stream);
+}
+
+std::string CppGroupBodyGen::GetDeserializer(const Interface& iface) {
+  std::string str;
+
+  for (const auto& i : iface.GetDeclarations()) {
+    str += ReplaceAll(CB_METHOD_DISPATCHER)
+        .Change("<METHOD_ID>", i->GetID())
+        .Change("<DISPATCH>", GetDispatcher(*i));
+  }
+
+  return str;
+}
+
+std::string CppGroupBodyGen::GetDispatcher(const Declaration& decl) {
+  std::string str;
+  int cnt = 1;
+
+  // Deserialize
+  for (const auto& i : decl.GetParameters()) {
+    if (i->GetParameterType().GetDirection() == ParameterType::Direction::OUT) {
+      cnt++;
+      continue;
+    }
+
+    std::string v = "param" + std::to_string(cnt);
+    std::string c = ConvertTypeToDeserializer(
+        i->GetParameterType().GetBaseType(), v, "p");
+    str += AddIndent(TAB_SIZE * 3, c);
+    cnt++;
+  }
+
+  // Invoke
+  cnt = 1;
+  std::string m;
+
+  m += "ptr->On" + decl.GetID() + "(";
+  for (const auto& i : decl.GetParameters()) {
+    (void)i;
+    if (cnt != 1) {
+      m += ", ";
+    }
+
+    m += "param" + std::to_string(cnt);
+    cnt++;
+  }
+
+  m += ");\n";
+  str += AddIndent(TAB_SIZE * 3, m);
+
+  return str;
+}
+
+void CppGroupBodyGen::GenHelperMethods(std::ofstream& stream,
+                                       const Interface& iface) {
+  ReplaceAll(CB_GROUP_HELPER_METHODS)
+      .Change("<CLS_NAME>", iface.GetID())
+      .Change("<DESERIALIZE>", GetDeserializer(iface))
+      .Out(stream);
+}
+
+void CppGroupBodyGen::GenMethods(std::ofstream& stream,
+                                 const Interface& iface) {
+  auto& decls = iface.GetDeclarations();
+
+  for (const auto& i : decls) {
+    GenInvocation(stream, iface, *i);
+  }
+}
+
+void CppGroupBodyGen::GenInvocation(std::ofstream& stream,
+    const Interface& iface, const Declaration& decl) {
+  ReplaceAll(CB_INVOCATION)
+      .Change("<RET_TYPE>", ConvertTypeToString(decl.GetType()))
+      .Change("<IFACE>", iface.GetID())
+      .Change("<METHOD>", decl.GetID())
+      .Change("<PARAMS>", GetParameters(decl.GetParameters()))
+      .Change("<SERIALIZE>", [&]() {
+        std::string m;
+        std::string ret;
+        for (const auto& i : decl.GetParameters()) {
+          auto& pt = i->GetParameterType();
+          if (pt.GetDirection() == ParameterType::Direction::OUT)
+            continue;
+          m += GenPrivateSharingRequest(pt.GetBaseType(), i->GetID());
+          m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p");
+        }
+
+        ret = AddIndent(TAB_SIZE, m) + NLine(1);
+        return ret;
+      })
+      .Out(stream);
+}
+
+}  // namespace tidl
diff --git a/idlc/gen/cpp_group_body_gen.h b/idlc/gen/cpp_group_body_gen.h
new file mode 100644 (file)
index 0000000..0174683
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022 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_CPP_GEN_CPP_GROUP_BODY_GEN_H_
+#define IDLC_CPP_GEN_CPP_GROUP_BODY_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen/cpp_gen_base.h"
+
+namespace tidl {
+
+class CppGroupBodyGen : public CppGeneratorBase {
+ public:
+  explicit CppGroupBodyGen(std::shared_ptr<Document> doc);
+  virtual ~CppGroupBodyGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenNamespace(std::ofstream& stream);
+  void GenInterfaces(std::ofstream& stream);
+  void GenInterface(std::ofstream& stream, const Interface& iface);
+  void GenConstructor(std::ofstream& stream, const Interface& iface);
+  void GenDestructor(std::ofstream& stream, const Interface& iface);
+  void GenHelperMethods(std::ofstream& stream, const Interface& iface);
+  void GenMethods(std::ofstream& stream, const Interface& iface);
+  void GenInvocation(std::ofstream& stream, const Interface& iface,
+      const Declaration& decl);
+  std::string GetDeserializer(const Interface& iface);
+  std::string GetDispatcher(const Declaration& decl);
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_CPP_GEN_CPP_GROUP_BODY_GEN_H_
diff --git a/idlc/gen/cpp_group_body_gen_cb.h b/idlc/gen/cpp_group_body_gen_cb.h
new file mode 100644 (file)
index 0000000..4ae3efe
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2022 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_CPP_GEN_CPP_GROUP_BODY_GEN_CB_H_
+#define IDLC_CPP_GEN_CPP_GROUP_BODY_GEN_CB_H_
+
+const char CB_HEADER[] =
+R"__cpp_cb(
+#include <stdlib.h>
+#include <assert.h>
+#include <dlog.h>
+
+#include "<HEADER_FILE>"
+)__cpp_cb";
+
+const char CB_INTERFACE_CTOR[] =
+R"__cpp_cb(
+<CLS_NAME>::<CLS_NAME>() {
+}
+
+<CLS_NAME>::<CLS_NAME>(const std::string& sender_appid) {
+  Subscribe(sender_appid);
+}
+
+)__cpp_cb";
+
+const char CB_INTERFACE_DTOR[] =
+R"__cpp_cb(
+<CLS_NAME>::~<CLS_NAME>() {
+  Unsubscribe();
+}
+)__cpp_cb";
+
+const char CB_INVOCATION[] =
+R"__cpp_cb(
+<RET_TYPE> <IFACE>::<METHOD>(<PARAMS>) {
+  rpc_port_parcel_h p;
+  rpc_port_parcel_create(&p);
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+  rpc_port_parcel_header_h header_;
+  rpc_port_parcel_get_header(p, &header_);
+  rpc_port_parcel_header_set_tag(header_, TIDL_VERSION);
+  int seq_num_ = -1;
+  rpc_port_parcel_header_get_seq_num(header_, &seq_num_);
+  _W("[Version] \"%s\", [Sequence] %d", TIDL_VERSION, seq_num_);
+  rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::<METHOD>));
+<SERIALIZE>
+  // Send
+  bundle* b = bundle_create();
+  std::unique_ptr<bundle, decltype(bundle_free)*> b_auto(b, bundle_free);
+  if (GetBundleFromParcel(p, b) == nullptr) {
+    _E("Failed to make bundle from parcel");
+    throw InvalidIOException();
+  }
+
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_publish_app_event(GetEventName().c_str(), b);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to publish event. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+)__cpp_cb";
+
+const char CB_GROUP_HELPER_METHODS[] =
+R"__cpp_cb(
+void <CLS_NAME>::Subscribe(const std::string& sender_appid) {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  int ret = event_add_event_handler(GetEventName(sender_appid).c_str(), EventCb, this, &event_handler_);
+  if (ret != EVENT_ERROR_NONE) {
+    _E("Failed to register events. result(%d)", ret);
+    throw InvalidIOException();
+  }
+}
+
+void <CLS_NAME>::Unsubscribe() {
+  std::lock_guard<std::recursive_mutex> lock(mutex_);
+  if (event_handler_) {
+    event_remove_event_handler(event_handler_);
+    event_handler_ = nullptr;
+  }
+}
+
+bundle* <CLS_NAME>::GetBundleFromParcel(rpc_port_parcel_h p, bundle* b) {
+  void* raw = nullptr;
+  unsigned int size = 0;
+
+  int ret = rpc_port_parcel_get_raw(p, &raw, &size);
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  ret = bundle_add_byte(b, "TIDL_RAW", raw, size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  return b;
+}
+
+rpc_port_parcel_h <CLS_NAME>::GetParcelFromBundle(bundle* b) {
+  void* raw = nullptr;
+  unsigned int size = 0;
+  rpc_port_parcel_h p;
+
+  int ret = bundle_get_byte(b, "TIDL_RAW", &raw, &size);
+  if (ret != BUNDLE_ERROR_NONE)
+    return nullptr;
+
+  ret = rpc_port_parcel_create_from_raw(&p, raw, size);
+  if (ret != RPC_PORT_ERROR_NONE)
+    return nullptr;
+
+  return p;
+}
+
+std::string <CLS_NAME>::GetAppId() {
+  static std::string str;
+
+  if (!str.empty())
+    return str;
+
+  char* id;
+  int ret = app_get_id(&id);
+  if (ret != APP_ERROR_NONE)
+    return "system";
+
+  str = id;
+  free(id);
+  return str;
+}
+
+std::string <CLS_NAME>::GetEventName() {
+  return "event." + GetAppId() + ".tidl_iface_<CLS_NAME>";
+}
+
+std::string <CLS_NAME>::GetEventName(const std::string& sender_appid) {
+  return "event." + sender_appid + ".tidl_iface_<CLS_NAME>";
+}
+
+void <CLS_NAME>::EventCb(const char* event_name, bundle* event_data, void* user_data) {
+  auto* ptr = static_cast<<CLS_NAME>*>(user_data);
+  rpc_port_parcel_h p = ptr->GetParcelFromBundle(event_data);
+  if (p == nullptr) {
+    _E("Invalid bundle");
+    return;
+  }
+
+  std::unique_ptr<std::remove_pointer<rpc_port_parcel_h>::type,
+      decltype(rpc_port_parcel_destroy)*> p_auto(p, rpc_port_parcel_destroy);
+
+  rpc_port_parcel_h header;
+  int seq_num = -1;
+  int cmd;
+  rpc_port_parcel_get_header(p, &header);
+  rpc_port_parcel_header_get_seq_num(header, &seq_num);
+
+  _W("[Sequence] %d", seq_num);
+  rpc_port_parcel_read_int32(p, &cmd);
+  switch (cmd) {
+<DESERIALIZE>
+
+    default:
+      _E("Unknown command(%d)", cmd);
+  }
+}
+
+)__cpp_cb";
+
+
+const char CB_METHOD_DISPATCHER[] =
+R"__cpp_cb(
+    case static_cast<int>(MethodId::<METHOD_ID>):
+    {
+<DISPATCH>
+    }
+    break;
+
+)__cpp_cb";
+
+#endif  // IDLC_CPP_GEN_CPP_GROUP_BODY_GEN_CB_H_
diff --git a/idlc/gen/cpp_group_header_gen.cc b/idlc/gen/cpp_group_header_gen.cc
new file mode 100644 (file)
index 0000000..aaa996f
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "idlc/gen/cpp_group_header_gen.h"
+
+namespace {
+#include "idlc/gen/cpp_group_header_gen_cb.h"
+}
+
+namespace tidl {
+
+CppGroupHeaderGen::CppGroupHeaderGen(std::shared_ptr<Document> doc)
+    : CppGeneratorBase(doc) {}
+
+void CppGroupHeaderGen::OnInitGen(std::ofstream& stream) {
+  GenVersion(stream);
+  stream << CB_HEADER;
+  GenNamespace(stream);
+}
+
+void CppGroupHeaderGen::OnFiniGen(std::ofstream& stream) {
+}
+
+void CppGroupHeaderGen::GenNamespace(std::ofstream& stream) {
+  ReplaceAll(CB_NAMESPACE_FULL)
+      .Change("<FILE_NAMESPACE>", GetFileNamespace())
+      .Change("<STRUCTS>", GetStructuresForHeader())
+      .Change("<EXCEPTIONS>", std::string(CB_EXCEPTIONS))
+      .Change("<INTERFACES>", GetInterfaces())
+      .Out(stream);
+}
+
+std::string CppGroupHeaderGen::GetInterfaces() {
+  std::string str;
+  for (auto& i : GetDocument().GetBlocks()) {
+    if (i->GetType() != Block::TYPE_INTERFACE)
+      continue;
+    Interface& iface = static_cast<Interface&>(*i);
+    str += GetInterface(iface);
+  }
+
+  return str;
+}
+
+std::string CppGroupHeaderGen::GetInterface(const Interface& iface) {
+  return std::string(ReplaceAll(CB_CLASS_FULL)
+      .Change("<CLS_NAME>", iface.GetID())
+      .Change("<PUBLIC_MEMBERS>", GetMethods(iface))
+      .Change("<PRIVATE_MEMBERS>",GetMethodId(iface)));
+}
+
+std::string CppGroupHeaderGen::GetMethods(const Interface& iface) {
+  auto& decls = iface.GetDeclarations();
+  std::string str;
+  for (const auto& i : decls) {
+    if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+      continue;
+
+    str += GetDeclaration(*i);
+  }
+  return str;
+}
+
+std::string CppGroupHeaderGen::GetDeclaration(const Declaration& decl) {
+  return std::string(ReplaceAll(CB_METHOD_DECL)
+      .Change("<COMMENTS>", decl.GetComments().empty() ? "" : decl.GetComments())
+      .Change("<RET_TYPE>", ConvertTypeToString(decl.GetType()))
+      .Change("<METHOD_NAME>", decl.GetID())
+      .Change("<PARAMS>", GetParameters(decl.GetParameters())));
+}
+}  // namespace tidl
diff --git a/idlc/gen/cpp_group_header_gen.h b/idlc/gen/cpp_group_header_gen.h
new file mode 100644 (file)
index 0000000..2921840
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2022 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_CPP_GEN_CPP_GROUP_HEADER_GEN_H_
+#define IDLC_CPP_GEN_CPP_GROUP_HEADER_GEN_H_
+
+#include <memory>
+#include <string>
+
+#include "idlc/gen/cpp_gen_base.h"
+
+namespace tidl {
+
+class CppGroupHeaderGen : public CppGeneratorBase {
+ public:
+  explicit CppGroupHeaderGen(std::shared_ptr<Document> doc);
+  virtual ~CppGroupHeaderGen() = default;
+
+  void OnInitGen(std::ofstream& stream) override;
+  void OnFiniGen(std::ofstream& stream) override;
+
+ private:
+  void GenNamespace(std::ofstream& stream);
+  std::string GetInterfaces();
+  std::string GetInterface(const Interface& iface);
+  std::string GetMethods(const Interface& iface);
+  std::string GetDeclaration(const Declaration& decl);
+};
+
+}  // namespace tidl
+
+#endif  // IDLC_CPP_GEN_CPP_GROUP_HEADER_GEN_H_
diff --git a/idlc/gen/cpp_group_header_gen_cb.h b/idlc/gen/cpp_group_header_gen_cb.h
new file mode 100644 (file)
index 0000000..d1f3045
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2022 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_CPP_GEN_CPP_GROUP_HEADER_GEN_CB_H_
+#define IDLC_CPP_GEN_CPP_GROUP_HEADER_GEN_CB_H_
+
+const char CB_EXCEPTIONS[] =
+R"__cpp_cb(
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+class InvalidIOException : public Exception {};
+class PermissionDeniedException : public Exception {};
+class InvalidIDException : public Exception {};
+)__cpp_cb";
+
+const char CB_NAMESPACE_FULL[] =
+R"__cpp_cb(
+namespace rpc_port {
+namespace <FILE_NAMESPACE> {
+
+<STRUCTS>
+namespace group {
+
+<EXCEPTIONS>
+<INTERFACES>
+}  // namespace group
+}  // namespace <FILE_NAMESPACE>
+}  // namespace rpc_port
+)__cpp_cb";
+
+const char CB_CLASS_FULL[] =
+R"__cpp_cb(
+class <CLS_NAME> {
+ public:
+  <CLS_NAME>();
+  <CLS_NAME>(const std::string& sender_appid);
+  virtual ~<CLS_NAME>();
+
+  <PUBLIC_MEMBERS>
+
+ private:
+<PRIVATE_MEMBERS>
+
+  bundle* GetBundleFromParcel(rpc_port_parcel_h p, bundle* b);
+  rpc_port_parcel_h GetParcelFromBundle(bundle* b);
+  std::string GetAppId();
+  std::string GetEventName();
+  std::string GetEventName(const std::string& sender_appid);
+  void Subscribe(const std::string& sender_appid);
+  void Unsubscribe();
+  static void EventCb(const char* event_name, bundle* event_data, void* user_data);
+
+ private:
+  event_handler_h event_handler_ = nullptr;
+  std::recursive_mutex mutex_;
+};
+)__cpp_cb";
+
+const char CB_METHOD_DECL[] =
+R"__cpp_cb(
+  <COMMENTS>
+  <RET_TYPE> <METHOD_NAME>(<PARAMS>);
+
+  virtual <RET_TYPE> On<METHOD_NAME>(<PARAMS>) {}
+)__cpp_cb";
+
+const char CB_HEADER[] =
+R"__cpp_cb(
+#pragma once
+
+#include <app_common.h>
+#include <app_event.h>
+#include <bundle.h>
+#include <rpc-port-parcel.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <mutex>
+#include <list>
+#include <atomic>
+
+)__cpp_cb";
+
+#endif  // IDLC_CPP_GEN_CPP_GROUP_HEADER_GEN_CB_H_
index adb9801..f6d339c 100644 (file)
@@ -31,6 +31,8 @@
 #include "idlc/gen/cpp_proxy_body_gen.h"
 #include "idlc/gen/cpp_stub_header_gen.h"
 #include "idlc/gen/cpp_stub_body_gen.h"
+#include "idlc/gen/cpp_group_header_gen.h"
+#include "idlc/gen/cpp_group_body_gen.h"
 #include "idlc/gen_cion/c_cion_proxy_header_gen.h"
 #include "idlc/gen_cion/c_cion_proxy_body_gen.h"
 #include "idlc/gen_cion/c_cion_stub_header_gen.h"
@@ -315,8 +317,16 @@ void GenerateGroupCodes(std::shared_ptr<tidl::Options> options,
     }
   } else {
     switch (options->GetLanguage()) {
-      case tidl::Options::LANGUAGE_TYPE_C:
       case tidl::Options::LANGUAGE_TYPE_CPP:
+      {
+        tidl::CppGroupHeaderGen group_header(ps.GetDoc());
+        group_header.Run(options->GetOutput() + ".h");
+        tidl::CppGroupBodyGen group_body(ps.GetDoc());
+        group_body.Run(options->GetOutput() + ".cc");
+        break;
+      }
+
+      case tidl::Options::LANGUAGE_TYPE_C:
       case tidl::Options::LANGUAGE_TYPE_CSHARP:
       case tidl::Options::LANGUAGE_TYPE_JAVA:
       default:
index 51523e4..ac146a7 100644 (file)
@@ -190,17 +190,9 @@ std::shared_ptr<Options> Options::Parse(int argc, char** argv) {
   switch (static_cast<int>(options->type_)) {
   case TYPE_UNKNOWN:
     std::cerr <<
-      "Stub or proxy or group (CION & AITT only) must be specified." << std::endl;
+      "Stub or proxy or group must be specified." << std::endl;
     options->PrintSample();
     return std::shared_ptr<Options>(nullptr);
-  case TYPE_GROUP:
-    if (!options->isCion_ && !options->isAitt_) {
-      std::cerr <<
-        "Group is only allowed for the CION and AITT codes." << std::endl;
-      options->PrintSample();
-      return std::shared_ptr<Options>(nullptr);
-    }
-    break;
   default:
     break;
   }
index b90fa47..785ba2e 100644 (file)
@@ -20,6 +20,9 @@ BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(rpc-port)
 BuildRequires:  pkgconfig(bundle)
 BuildRequires:  pkgconfig(cion)
+BuildRequires:  pkgconfig(capi-appfw-event)
+BuildRequires:  pkgconfig(capi-appfw-app-common)
+
 %if 0%{?gcov:1}
 BuildRequires:  lcov
 %endif
index 191b2b0..80cac8f 100644 (file)
@@ -2,7 +2,15 @@ SET(TOOL_TIDLC "${CMAKE_CURRENT_SOURCE_DIR}/../../idlc/tidlc")
 SET(TARGET_PREBUILD_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/prebuild.sh")
 
 INCLUDE(FindPkgConfig)
-PKG_CHECK_MODULES(PKGS REQUIRED dlog glib-2.0 rpc-port bundle cion)
+PKG_CHECK_MODULES(PKGS REQUIRED
+  dlog
+  glib-2.0
+  rpc-port
+  bundle
+  cion
+  capi-appfw-event
+  capi-appfw-app-common
+)
 
 FOREACH(flag ${PKGS_CFLAGS})
   SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
@@ -54,6 +62,9 @@ SET(TIDL_GEN_SRCS
   MessageProxy.cc
   MessageProxyC.c
   MessageStub.cc
+  FooPubsubGroup.cc
+  FooPubsubCionGroup.cc
+  FooPubsubCionGroupC.c
 )
 
 ADD_CUSTOM_COMMAND(OUTPUT ${TIDL_GEN_SRCS} PRE_BUILD
index 9ad3cf2..41e9df6 100755 (executable)
@@ -17,6 +17,8 @@ FILES_CION[2]="ExCion"
 FILES_CION[3]="DataPort"
 FILES_CION[4]="Foo"
 
+FILES_FOR_GROUP[0]="FooPubsub"
+
 GenerateTIDL() {
   for index in ${!FILES[*]}; do
     echo "Generate ${FILES[index]}"
@@ -36,6 +38,15 @@ GenerateTIDL() {
     ${TIDLC} -s -n -l C -i ${SCRIPT_DIR}/tidl/${INPUT} -o ${TARGET_DIR}/${OUTPUT}
   done
 
+  for index in ${!FILES_FOR_GROUP[*]}; do
+    echo "Generate ${FILES_FOR_GROUP[index]}"
+
+    INPUT="${FILES_FOR_GROUP[index]}.tidl"
+
+    OUTPUT="${FILES_FOR_GROUP[index]}Group"
+    ${TIDLC} -g -l C++ -i ${SCRIPT_DIR}/tidl/${INPUT} -o ${TARGET_DIR}/${OUTPUT}
+  done
+
   for index in ${!FILES_CION[*]}; do
     echo "Generate ${FILES_CION[index]}"
 
@@ -53,6 +64,18 @@ GenerateTIDL() {
     OUTPUT="${FILES_CION[index]}CionStubC"
     ${TIDLC} -b -s -n -c -l C -i ${SCRIPT_DIR}/tidl/${INPUT} -o ${TARGET_DIR}/${OUTPUT}
   done
+
+  for index in ${!FILES_FOR_GROUP[*]}; do
+    echo "Generate ${FILES_FOR_GROUP[index]}"
+
+    INPUT="${FILES_FOR_GROUP[index]}.tidl"
+
+    OUTPUT="${FILES_FOR_GROUP[index]}CionGroup"
+    ${TIDLC} -b -c -g -l C++ -i ${SCRIPT_DIR}/tidl/${INPUT} -o ${TARGET_DIR}/${OUTPUT}
+
+    OUTPUT="${FILES_FOR_GROUP[index]}CionGroupC"
+    ${TIDLC} -b -c -n -g -l C -i ${SCRIPT_DIR}/tidl/${INPUT} -o ${TARGET_DIR}/${OUTPUT}
+  done
 }
 
 echo "############ Generate codes using TIDLC ############"
diff --git a/tests/build_tests/tidl/FooPubsub.tidl b/tests/build_tests/tidl/FooPubsub.tidl
new file mode 100755 (executable)
index 0000000..8e336a0
--- /dev/null
@@ -0,0 +1,9 @@
+struct Foo {
+       int Age;
+       string Name;
+}
+
+interface Runnable {
+       void Run(Foo foo) async;
+}
+