dds_generator.h

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #ifndef dds_generator_H
00009 #define dds_generator_H
00010 
00011 #include "be_extern.h"
00012 
00013 #include "utl_scoped_name.h"
00014 #include "utl_identifier.h"
00015 #include "utl_string.h"
00016 
00017 #include "ast.h"
00018 #include "ast_component_fwd.h"
00019 #include "ast_eventtype_fwd.h"
00020 #include "ast_structure_fwd.h"
00021 #include "ast_union_fwd.h"
00022 #include "ast_valuetype_fwd.h"
00023 
00024 #include "ace/CDR_Base.h"
00025 
00026 #include <string>
00027 #include <vector>
00028 #include <cstring>
00029 
00030 class dds_generator {
00031 public:
00032   virtual ~dds_generator() = 0;
00033 
00034   virtual bool do_included_files() const { return false; }
00035 
00036   virtual void gen_prologue() {}
00037 
00038   virtual void gen_epilogue() {}
00039 
00040   virtual bool gen_const(UTL_ScopedName* /*name*/,
00041                          bool /*nestedInInteface*/,
00042                          AST_Constant* /*constant*/)
00043   { return true; }
00044 
00045   virtual bool gen_enum(AST_Enum* /*node*/, UTL_ScopedName* /*name*/,
00046                         const std::vector<AST_EnumVal*>& /*contents*/,
00047                         const char* /*repoid*/)
00048   { return true; }
00049 
00050   virtual bool gen_struct(AST_Structure* node, UTL_ScopedName* name,
00051                           const std::vector<AST_Field*>& fields,
00052                           AST_Type::SIZE_TYPE size,
00053                           const char* repoid) = 0;
00054 
00055   virtual bool gen_struct_fwd(UTL_ScopedName* /*name*/,
00056                               AST_Type::SIZE_TYPE /*size*/)
00057   { return true; }
00058 
00059   virtual bool gen_typedef(AST_Typedef* node, UTL_ScopedName* name, AST_Type* base,
00060                            const char* repoid) = 0;
00061 
00062   virtual bool gen_interf(AST_Interface* /*node*/, UTL_ScopedName* /*name*/, bool /*local*/,
00063                           const std::vector<AST_Interface*>& /*inherits*/,
00064                           const std::vector<AST_Interface*>& /*inherits_flat*/,
00065                           const std::vector<AST_Attribute*>& /*attrs*/,
00066                           const std::vector<AST_Operation*>& /*ops*/,
00067                           const char* /*repoid*/)
00068   { return true; }
00069 
00070   virtual bool gen_interf_fwd(UTL_ScopedName* /*name*/)
00071   { return true; }
00072 
00073   virtual bool gen_native(AST_Native* /*node*/, UTL_ScopedName* /*name*/, const char* /*repoid*/)
00074   { return true; }
00075 
00076   virtual bool gen_union(AST_Union* node, UTL_ScopedName* name,
00077                          const std::vector<AST_UnionBranch*>& branches,
00078                          AST_Type* discriminator,
00079                          const char* repoid) = 0;
00080 
00081   virtual bool gen_union_fwd(AST_UnionFwd* /*node*/, UTL_ScopedName* /*name*/,
00082                              AST_Type::SIZE_TYPE /*size*/)
00083   { return true; }
00084 
00085   static std::string scoped_helper(UTL_ScopedName* sn, const char* sep);
00086   static std::string module_scope_helper(UTL_ScopedName* sn, const char* sep);
00087 };
00088 
00089 class composite_generator : public dds_generator {
00090 public:
00091   void gen_prologue();
00092 
00093   void gen_epilogue();
00094 
00095   bool gen_const(UTL_ScopedName* name, bool nestedInInteface,
00096                  AST_Constant* constant);
00097 
00098   bool gen_enum(AST_Enum* node, UTL_ScopedName* name,
00099                 const std::vector<AST_EnumVal*>& contents, const char* repoid);
00100 
00101   bool gen_struct(AST_Structure* node, UTL_ScopedName* name,
00102                   const std::vector<AST_Field*>& fields,
00103                   AST_Type::SIZE_TYPE size, const char* repoid);
00104 
00105   bool gen_struct_fwd(UTL_ScopedName* name, AST_Type::SIZE_TYPE size);
00106 
00107   bool gen_typedef(AST_Typedef* node, UTL_ScopedName* name, AST_Type* base, const char* repoid);
00108 
00109   bool gen_interf(AST_Interface* node, UTL_ScopedName* name, bool local,
00110                   const std::vector<AST_Interface*>& inherits,
00111                   const std::vector<AST_Interface*>& inherits_flat,
00112                   const std::vector<AST_Attribute*>& attrs,
00113                   const std::vector<AST_Operation*>& ops, const char* repoid);
00114 
00115   bool gen_interf_fwd(UTL_ScopedName* name);
00116 
00117   bool gen_native(AST_Native* node, UTL_ScopedName* name, const char* repoid);
00118 
00119   bool gen_union(AST_Union* node, UTL_ScopedName* name,
00120                  const std::vector<AST_UnionBranch*>& branches,
00121                  AST_Type* discriminator,
00122                  const char* repoid);
00123 
00124   bool gen_union_fwd(AST_UnionFwd*, UTL_ScopedName* name, AST_Type::SIZE_TYPE size);
00125 
00126   template <typename InputIterator>
00127   composite_generator(InputIterator begin, InputIterator end)
00128   : components_(begin, end) {}
00129 
00130   void add_generator(dds_generator* gen) { components_.push_back(gen); }
00131 
00132 private:
00133   std::vector<dds_generator*> components_;
00134 };
00135 
00136 // common utilities for all "generator" derived classes
00137 
00138 struct NamespaceGuard {
00139   NamespaceGuard()
00140   {
00141     be_global->header_ << "namespace OpenDDS { namespace DCPS {\n\n";
00142     be_global->impl_ << "namespace OpenDDS { namespace DCPS {\n\n";
00143   }
00144   ~NamespaceGuard()
00145   {
00146     be_global->header_ << "}  }\n\n";
00147     be_global->impl_ << "}  }\n\n";
00148   }
00149 };
00150 
00151 struct ScopedNamespaceGuard  {
00152   ScopedNamespaceGuard(UTL_ScopedName* name, std::ostream& os,
00153                        const char* keyword = "namespace")
00154     : os_(os)
00155   {
00156     for (n_ = 0; name->tail();
00157          name = static_cast<UTL_ScopedName*>(name->tail())) {
00158       const char* str = name->head()->get_string();
00159       if (str && str[0]) {
00160         ++n_;
00161         os << keyword << (name->head()->escaped() ? " _" : " ")
00162            << str << " {\n";
00163       }
00164     }
00165     if (std::strcmp(keyword, "module") == 0) semi_ = ";";
00166   }
00167 
00168   ~ScopedNamespaceGuard()
00169   {
00170     for (int i = 0; i < n_; ++i) os_ << '}' << semi_ << '\n';
00171   }
00172 
00173   std::ostream& os_;
00174   std::string semi_;
00175   int n_;
00176 };
00177 
00178 struct Function {
00179   bool has_arg_;
00180   std::string preamble_;
00181 
00182   Function(const char* name, const char* returntype)
00183     : has_arg_(false)
00184   {
00185     using std::string;
00186     ACE_CString ace_exporter = be_global->export_macro();
00187     bool use_exp = ace_exporter != "";
00188     string exporter = use_exp ? (string(" ") + ace_exporter.c_str()) : "";
00189     be_global->header_ << ace_exporter << (use_exp ? "\n" : "")
00190       << returntype << " " << name << "(";
00191     be_global->impl_ << returntype << " " << name << "(";
00192   }
00193 
00194   void addArg(const char* name, const std::string& type)
00195   {
00196     std::string sig = (has_arg_ ? ", " : "") + type + (name[0] ? " " : "")
00197       + (name[0] ? name : "");
00198     be_global->header_ << sig;
00199     be_global->impl_ << sig;
00200     if (name[0]) {
00201       preamble_ += "  ACE_UNUSED_ARG(" + std::string(name) + ");\n";
00202     }
00203     has_arg_ = true;
00204   }
00205 
00206   void endArgs()
00207   {
00208     be_global->header_ << ");\n\n";
00209     be_global->impl_ << ")\n{\n" << preamble_;
00210   }
00211 
00212   ~Function()
00213   {
00214     be_global->impl_ << "}\n\n";
00215   }
00216 };
00217 
00218 inline std::string scoped(UTL_ScopedName* sn)
00219 {
00220   return dds_generator::scoped_helper(sn, "::");
00221 }
00222 
00223 inline std::string module_scope(UTL_ScopedName* sn)
00224 {
00225   return dds_generator::module_scope_helper(sn, "::");
00226 }
00227 
00228 namespace AstTypeClassification {
00229   inline AST_Type* resolveActualType(AST_Type* element)
00230   {
00231     if (element->node_type() == AST_Decl::NT_typedef) {
00232       AST_Typedef* td = AST_Typedef::narrow_from_decl(element);
00233       return td->primitive_base_type();
00234     }
00235 
00236     switch(element->node_type()) {
00237     case AST_Decl::NT_interface_fwd:
00238     {
00239       AST_InterfaceFwd* td = AST_InterfaceFwd::narrow_from_decl(element);
00240       return td->full_definition();
00241       break;
00242     }
00243     case AST_Decl::NT_valuetype_fwd:
00244     {
00245       AST_ValueTypeFwd* td = AST_ValueTypeFwd::narrow_from_decl(element);
00246       return td->full_definition();
00247       break;
00248     }
00249     case AST_Decl::NT_union_fwd:
00250     {
00251       AST_UnionFwd* td = AST_UnionFwd::narrow_from_decl(element);
00252       return td->full_definition();
00253       break;
00254     }
00255     case AST_Decl::NT_struct_fwd:
00256     {
00257       AST_StructureFwd* td = AST_StructureFwd::narrow_from_decl(element);
00258       return td->full_definition();
00259       break;
00260     }
00261     case AST_Decl::NT_component_fwd:
00262     {
00263       AST_ComponentFwd* td = AST_ComponentFwd::narrow_from_decl(element);
00264       return td->full_definition();
00265       break;
00266     }
00267     case AST_Decl::NT_eventtype_fwd:
00268     {
00269       AST_EventTypeFwd* td = AST_EventTypeFwd::narrow_from_decl(element);
00270       return td->full_definition();
00271       break;
00272     }
00273     default :
00274       return element;
00275       break;
00276     }
00277   }
00278 
00279   typedef size_t Classification;
00280   const Classification CL_UNKNOWN = 0, CL_SCALAR = 1, CL_PRIMITIVE = 2,
00281     CL_STRUCTURE = 4, CL_STRING = 8, CL_ENUM = 16, CL_UNION = 32, CL_ARRAY = 64,
00282     CL_SEQUENCE = 128, CL_WIDE = 256, CL_BOUNDED = 512, CL_INTERFACE = 1024,
00283     CL_FIXED = 2048;
00284 
00285   inline Classification classify(AST_Type* type)
00286   {
00287     type = AstTypeClassification::resolveActualType(type);
00288     switch (type->node_type()) {
00289     case AST_Decl::NT_pre_defined: {
00290       AST_PredefinedType* p = AST_PredefinedType::narrow_from_decl(type);
00291       switch (p->pt()) {
00292       case AST_PredefinedType::PT_any:
00293       case AST_PredefinedType::PT_object:
00294         return CL_UNKNOWN;
00295       case AST_PredefinedType::PT_wchar:
00296         return CL_SCALAR | CL_PRIMITIVE | CL_WIDE;
00297       default:
00298         return CL_SCALAR | CL_PRIMITIVE;
00299       }
00300     }
00301     case AST_Decl::NT_array:
00302       return CL_ARRAY;
00303     case AST_Decl::NT_union:
00304       return CL_UNION;
00305     case AST_Decl::NT_string:
00306     case AST_Decl::NT_wstring:
00307       return CL_SCALAR | CL_STRING |
00308         ((AST_String::narrow_from_decl(type)->max_size()->ev()->u.ulval == 0)
00309         ? 0 : CL_BOUNDED) |
00310         ((type->node_type() == AST_Decl::NT_wstring) ? CL_WIDE : 0);
00311     case AST_Decl::NT_sequence:
00312       return CL_SEQUENCE |
00313         ((AST_Sequence::narrow_from_decl(type)->unbounded()) ? 0 : CL_BOUNDED);
00314     case AST_Decl::NT_struct:
00315       return CL_STRUCTURE;
00316     case AST_Decl::NT_enum:
00317       return CL_SCALAR | CL_ENUM;
00318     case AST_Decl::NT_interface:
00319       return CL_INTERFACE;
00320 #ifdef ACE_HAS_CDR_FIXED
00321     case AST_Decl::NT_fixed:
00322       return CL_FIXED;
00323 #endif
00324     default:
00325       return CL_UNKNOWN;
00326     }
00327   }
00328 }
00329 
00330 struct NestedForLoops {
00331   NestedForLoops(const char* type, const char* prefix, AST_Array* arr,
00332                  std::string& indent, bool followTypedefs = false)
00333     : n_(arr->n_dims()), indent_(indent)
00334   {
00335     std::ostringstream index_oss;
00336     size_t i = 0, j = 0;
00337     while (true) {
00338       for (; i < n_; ++i) {
00339         be_global->impl_ <<
00340           indent << "for (" << type << ' ' << prefix << i << " = 0; " <<
00341           prefix << i << " < " << arr->dims()[i - j]->ev()->u.ulval << "; ++" <<
00342           prefix << i << ") {\n";
00343         indent += "  ";
00344         index_oss << "[" << prefix << i << "]";
00345       }
00346       if (!followTypedefs) {
00347         break;
00348       }
00349       AST_Type* const base =
00350         AstTypeClassification::resolveActualType(arr->base_type());
00351       if (base->node_type() == AST_Decl::NT_array) {
00352         arr = AST_Array::narrow_from_decl(base);
00353         n_ += arr->n_dims();
00354         j = i;
00355       } else {
00356         break;
00357       }
00358     }
00359     index_ = index_oss.str();
00360   }
00361 
00362   ~NestedForLoops()
00363   {
00364     for (size_t i = 0; i < n_; ++i) {
00365       indent_.resize(indent_.size() - 2);
00366       be_global->impl_ << indent_ << "}\n";
00367     }
00368   }
00369 
00370   size_t n_;
00371   std::string& indent_;
00372   std::string index_;
00373 };
00374 
00375 enum WrapDirection {WD_OUTPUT, WD_INPUT};
00376 
00377 inline
00378 std::string wrapPrefix(AST_Type* type, WrapDirection wd)
00379 {
00380   switch (type->node_type()) {
00381   case AST_Decl::NT_pre_defined:
00382     {
00383       AST_PredefinedType* p = AST_PredefinedType::narrow_from_decl(type);
00384       switch (p->pt()) {
00385       case AST_PredefinedType::PT_char:
00386         return (wd == WD_OUTPUT)
00387           ? "ACE_OutputCDR::from_char(" : "ACE_InputCDR::to_char(";
00388       case AST_PredefinedType::PT_wchar:
00389         return (wd == WD_OUTPUT)
00390           ? "ACE_OutputCDR::from_wchar(" : "ACE_InputCDR::to_wchar(";
00391       case AST_PredefinedType::PT_octet:
00392         return (wd == WD_OUTPUT)
00393           ? "ACE_OutputCDR::from_octet(" : "ACE_InputCDR::to_octet(";
00394       case AST_PredefinedType::PT_boolean:
00395         return (wd == WD_OUTPUT)
00396           ? "ACE_OutputCDR::from_boolean(" : "ACE_InputCDR::to_boolean(";
00397       default:
00398         return "";
00399       }
00400     }
00401   case AST_Decl::NT_string:
00402     return (wd == WD_OUTPUT)
00403       ? "ACE_OutputCDR::from_string(" : "ACE_InputCDR::to_string(";
00404   case AST_Decl::NT_wstring:
00405     return (wd == WD_OUTPUT)
00406       ? "ACE_OutputCDR::from_wstring(" : "ACE_InputCDR::to_wstring(";
00407   default:
00408     return "";
00409   }
00410 }
00411 
00412 inline
00413 std::string getWrapper(const std::string& name, AST_Type* type, WrapDirection wd)
00414 {
00415   std::string pre = wrapPrefix(type, wd);
00416   return (pre.empty()) ? name : (pre + name + ')');
00417 }
00418 
00419 inline
00420 std::string getEnumLabel(AST_Expression* label_val, AST_Type* disc)
00421 {
00422   std::string e = scoped(disc->name()),
00423     label = label_val->n()->last_component()->get_string();
00424   const size_t colon = e.rfind("::");
00425   if (colon == std::string::npos) {
00426     return label;
00427   }
00428   return e.replace(colon + 2, std::string::npos, label);
00429 }
00430 
00431 struct RestoreOutputStreamState {
00432   explicit RestoreOutputStreamState(std::ostream& o)
00433     : os_(o), state_(o.flags()) {}
00434   ~RestoreOutputStreamState() {
00435     os_.flags(state_);
00436   }
00437   std::ostream& os_;
00438   std::ios_base::fmtflags state_;
00439 };
00440 
00441 inline
00442 std::ostream& operator<<(std::ostream& o,
00443                          const AST_Expression::AST_ExprValue& ev)
00444 {
00445   RestoreOutputStreamState ross(o);
00446   switch (ev.et) {
00447   case AST_Expression::EV_octet:
00448     return o << static_cast<int>(ev.u.oval);
00449   case AST_Expression::EV_short:
00450     return o << ev.u.sval;
00451   case AST_Expression::EV_ushort:
00452     return o << ev.u.usval << 'u';
00453   case AST_Expression::EV_long:
00454     return o << ev.u.lval;
00455   case AST_Expression::EV_ulong:
00456     return o << ev.u.ulval << 'u';
00457   case AST_Expression::EV_longlong:
00458     return o << ev.u.llval << "LL";
00459   case AST_Expression::EV_ulonglong:
00460     return o << ev.u.ullval << "ULL";
00461   case AST_Expression::EV_wchar:
00462     return o << "L'" << static_cast<char>(ev.u.wcval) << '\'';
00463   case AST_Expression::EV_char:
00464     return o << '\'' << ev.u.cval << '\'';
00465   case AST_Expression::EV_bool:
00466     return o << std::boolalpha << static_cast<bool>(ev.u.bval);
00467   case AST_Expression::EV_float:
00468     return o << ev.u.fval << 'f';
00469   case AST_Expression::EV_double:
00470     return o << ev.u.dval;
00471   case AST_Expression::EV_wstring:
00472     return o << "L\"" << ev.u.wstrval << '"';
00473   case AST_Expression::EV_string:
00474     return o << '"' << ev.u.strval->get_string() << '"';
00475 #ifdef ACE_HAS_CDR_FIXED
00476   case AST_Expression::EV_fixed:
00477     {
00478       char buf[ACE_CDR::Fixed::MAX_STRING_SIZE];
00479       ev.u.fixedval.to_string(buf, sizeof buf);
00480       return o << "\"" << buf << "\"";
00481     }
00482 #endif
00483   default:
00484     return o;
00485   }
00486 }
00487 
00488 inline
00489 void generateBranchLabels(AST_UnionBranch* branch, AST_Type* discriminator,
00490                           size_t& n_labels, bool& has_default)
00491 {
00492   for (unsigned long j = 0; j < branch->label_list_length(); ++j) {
00493     ++n_labels;
00494     AST_UnionLabel* label = branch->label(j);
00495     if (label->label_kind() == AST_UnionLabel::UL_default) {
00496       be_global->impl_ << "  default:\n";
00497       has_default = true;
00498     } else if (discriminator->node_type() == AST_Decl::NT_enum) {
00499       be_global->impl_ << "  case "
00500         << getEnumLabel(label->label_val(), discriminator) << ":\n";
00501     } else {
00502       be_global->impl_ << "  case " << *label->label_val()->ev() << ":\n";
00503     }
00504   }
00505 }
00506 
00507 // see TAO_IDL_BE be_union::gen_empty_default_label()
00508 inline bool needSyntheticDefault(AST_Type* disc, size_t n_labels)
00509 {
00510   AST_Decl::NodeType nt = disc->node_type();
00511   if (nt == AST_Decl::NT_enum) return true;
00512 
00513   AST_PredefinedType* pdt = AST_PredefinedType::narrow_from_decl(disc);
00514   switch (pdt->pt()) {
00515   case AST_PredefinedType::PT_boolean:
00516     return n_labels < 2;
00517   case AST_PredefinedType::PT_char:
00518     return n_labels < ACE_OCTET_MAX;
00519   case AST_PredefinedType::PT_short:
00520   case AST_PredefinedType::PT_ushort:
00521     return n_labels < ACE_UINT16_MAX;
00522   case AST_PredefinedType::PT_long:
00523   case AST_PredefinedType::PT_ulong:
00524     return n_labels < ACE_UINT32_MAX;
00525   default:
00526     return true;
00527   }
00528 }
00529 
00530 typedef std::string (*CommonFn)(const std::string& name, AST_Type* type,
00531                                 const std::string& prefix, std::string& intro,
00532                                 const std::string&);
00533 
00534 inline void generateCaseBody(CommonFn commonFn,
00535                              AST_UnionBranch* branch,
00536                              const char* statementPrefix,
00537                              const char* namePrefix,
00538                              const std::string& uni,
00539                              bool generateBreaks,
00540                              bool parens)
00541 {
00542   using namespace AstTypeClassification;
00543   std::string intro, name = branch->local_name()->get_string();
00544   if (namePrefix == std::string(">> ")) {
00545     std::string brType = scoped(branch->field_type()->name()), forany;
00546     AST_Type* br = resolveActualType(branch->field_type());
00547     Classification br_cls = classify(br);
00548     if (!br->in_main_file()
00549         && br->node_type() != AST_Decl::NT_pre_defined) {
00550       be_global->add_referenced(br->file_name().c_str());
00551     }
00552     std::string rhs;
00553     if (br_cls & CL_STRING) {
00554       if (be_global->language_mapping() == BE_GlobalData::LANGMAP_FACE_CXX) {
00555         brType = std::string("FACE::") + ((br_cls & CL_WIDE) ? "W" : "")
00556           + "String_var";
00557       } else {
00558         brType = std::string("CORBA::") + ((br_cls & CL_WIDE) ? "W" : "")
00559           + "String_var";
00560       }
00561       rhs = "tmp.out()";
00562     } else if (br_cls & CL_ARRAY) {
00563       forany = "      " + brType + "_forany fa = tmp;\n";
00564       rhs = getWrapper("fa", br, WD_INPUT);
00565     } else {
00566       rhs = getWrapper("tmp", br, WD_INPUT);
00567     }
00568     be_global->impl_ <<
00569       "    {\n"
00570       "      " << brType << " tmp;\n" << forany <<
00571       "      if (strm >> " << rhs << ") {\n"
00572       "        uni." << name << "(tmp);\n"
00573       "        uni._d(disc);\n"
00574       "        return true;\n"
00575       "      }\n"
00576       "      return false;\n"
00577       "    }\n";
00578   } else {
00579     const char* breakString = (generateBreaks) ? "      break;\n" : "";
00580 
00581     std::string expr = commonFn(name + (parens ? "()" : ""), branch->field_type(),
00582                                 std::string(namePrefix) + "uni", intro, uni);
00583     be_global->impl_ <<
00584       "    {\n" <<
00585       (intro.length() ? "    " : "") << intro;
00586     if (*statementPrefix) {
00587       be_global->impl_ <<
00588         "      " << statementPrefix << " " << expr << ";\n" <<
00589         (statementPrefix == std::string("return") ? "" : breakString);
00590     } else {
00591       be_global->impl_ << expr << breakString;
00592     }
00593     be_global->impl_<<
00594       "    }\n";
00595   }
00596 }
00597 
00598 inline void generateSwitchBodyForUnion(CommonFn commonFn,
00599                                        const std::vector<AST_UnionBranch*>& branches, AST_Type* discriminator,
00600                                        const char* statementPrefix, const char* namePrefix = "",
00601                                        const std::string& uni = "",
00602                                        bool forceDisableDefault = false,
00603                                        bool parens = true)
00604 {
00605   size_t n_labels = 0;
00606   bool has_default = false;
00607   for (size_t i = 0; i < branches.size(); ++i) {
00608     AST_UnionBranch* branch = branches[i];
00609     if (forceDisableDefault) {
00610       bool foundDefault = false;
00611       for (unsigned long j = 0; j < branch->label_list_length(); ++j) {
00612         if (branch->label(j)->label_kind() == AST_UnionLabel::UL_default) {
00613           foundDefault = true;
00614         }
00615       }
00616       if (foundDefault) {
00617         has_default = true;
00618         continue;
00619       }
00620     }
00621     generateBranchLabels(branch, discriminator, n_labels, has_default);
00622     generateCaseBody(commonFn, branch, statementPrefix, namePrefix, uni, true, parens);
00623   }
00624   if (!has_default && needSyntheticDefault(discriminator, n_labels)) {
00625     be_global->impl_ <<
00626       "  default:\n" <<
00627       ((namePrefix == std::string(">> ")) ? "    uni._d(disc);\n" : "") <<
00628       "    break;\n";
00629   }
00630 }
00631 
00632 inline void generateSwitchForUnion(const std::string& switchExpr, CommonFn commonFn,
00633                                    const std::vector<AST_UnionBranch*>& branches, AST_Type* discriminator,
00634                                    const char* statementPrefix, const char* namePrefix = "",
00635                                    const std::string& uni = "", bool forceDisableDefault = false, bool parens = true)
00636 {
00637   using namespace AstTypeClassification;
00638   AST_Type* dt = resolveActualType(discriminator);
00639   AST_PredefinedType* bt = AST_PredefinedType::narrow_from_decl(dt);
00640   if (bt && bt->pt() == AST_PredefinedType::PT_boolean) {
00641     AST_UnionBranch* true_branch = 0;
00642     AST_UnionBranch* false_branch = 0;
00643     AST_UnionBranch* default_branch = 0;
00644     for (std::vector<AST_UnionBranch*>::const_iterator pos = branches.begin(), limit = branches.end();
00645          pos != limit;
00646          ++pos) {
00647       AST_UnionBranch* branch = *pos;
00648       for (unsigned long j = 0; j < branch->label_list_length(); ++j) {
00649         AST_UnionLabel* label = branch->label(j);
00650         if (label->label_kind() == AST_UnionLabel::UL_default) {
00651           default_branch = branch;
00652         }
00653         if (label->label_val()->ev()->u.bval) {
00654           true_branch = branch;
00655         }
00656         if (!label->label_val()->ev()->u.bval) {
00657           false_branch = branch;
00658         }
00659       }
00660     }
00661 
00662     be_global->impl_ <<
00663       "  if (" << switchExpr << ") \n";
00664     if (true_branch || default_branch) {
00665       generateCaseBody(commonFn, true_branch ? true_branch : default_branch, statementPrefix, namePrefix, uni, false, parens);
00666     }
00667     be_global->impl_ <<
00668       "  else \n";
00669     if (false_branch || default_branch) {
00670       generateCaseBody(commonFn, false_branch ? false_branch : default_branch, statementPrefix, namePrefix, uni, false, parens);
00671     }
00672   }
00673   else {
00674     be_global->impl_ <<
00675       "  switch (" << switchExpr << ") {\n";
00676     generateSwitchBodyForUnion(commonFn, branches, discriminator, statementPrefix, namePrefix, uni, forceDisableDefault, parens);
00677     be_global->impl_ <<
00678       "  }\n";
00679   }
00680 }
00681 
00682 #endif

Generated on Fri Feb 12 20:05:21 2016 for OpenDDS by  doxygen 1.4.7