langmap_generator.cpp

Go to the documentation of this file.
00001 /*
00002  * Distributed under the OpenDDS License.
00003  * See: http://www.opendds.org/license.html
00004  */
00005 
00006 #include "langmap_generator.h"
00007 #include "be_extern.h"
00008 
00009 #include "utl_identifier.h"
00010 
00011 #include "ace/Version.h"
00012 #include "ace/CDR_Base.h"
00013 #ifdef ACE_HAS_CDR_FIXED
00014 #include "ast_fixed.h"
00015 #endif
00016 
00017 #include <map>
00018 #include <iostream>
00019 
00020 using namespace AstTypeClassification;
00021 
00022 namespace {
00023   std::map<AST_PredefinedType::PredefinedType, std::string> primtype_;
00024 
00025   enum Helper {
00026     HLP_STR_VAR, HLP_STR_OUT, HLP_WSTR_VAR, HLP_WSTR_OUT,
00027     HLP_STR_MGR, HLP_WSTR_MGR,
00028     HLP_FIX_VAR, HLP_VAR_VAR, HLP_OUT,
00029     HLP_SEQ, HLP_SEQ_NS, HLP_SEQ_VAR_VAR, HLP_SEQ_FIX_VAR, HLP_SEQ_OUT,
00030     HLP_ARR_VAR_VAR, HLP_ARR_FIX_VAR, HLP_ARR_OUT, HLP_ARR_FORANY,
00031     HLP_FIXED, HLP_FIXED_CONSTANT
00032   };
00033   std::map<Helper, std::string> helpers_;
00034 
00035   std::string map_type(AST_Type* type)
00036   {
00037     if (AST_Typedef::narrow_from_decl(type)) {
00038       return scoped(type->name());
00039     }
00040     const Classification cls = classify(type);
00041     if (cls & CL_PRIMITIVE) {
00042       AST_Type* actual = resolveActualType(type);
00043       return primtype_[AST_PredefinedType::narrow_from_decl(actual)->pt()];
00044     }
00045     if (cls & CL_STRING) {
00046       const AST_PredefinedType::PredefinedType chartype = (cls & CL_WIDE)
00047         ? AST_PredefinedType::PT_wchar : AST_PredefinedType::PT_char;
00048       return primtype_[chartype] + '*';
00049     }
00050     if (cls & (CL_STRUCTURE | CL_UNION | CL_SEQUENCE | CL_ARRAY | CL_ENUM | CL_FIXED)) {
00051       return scoped(type->name());
00052     }
00053     if (cls & CL_INTERFACE) {
00054       return scoped(type->name()) + "_var";
00055     }
00056     return "<<unknown>>";
00057   }
00058 
00059   std::string map_type(AST_Expression::ExprType type)
00060   {
00061     AST_PredefinedType::PredefinedType pt = AST_PredefinedType::PT_void;
00062     switch (type)
00063     {
00064     case AST_Expression::EV_short: pt = AST_PredefinedType::PT_short; break;
00065     case AST_Expression::EV_ushort: pt = AST_PredefinedType::PT_ushort; break;
00066     case AST_Expression::EV_long: pt = AST_PredefinedType::PT_long; break;
00067     case AST_Expression::EV_ulong: pt = AST_PredefinedType::PT_ulong; break;
00068     case AST_Expression::EV_longlong: pt = AST_PredefinedType::PT_longlong; break;
00069     case AST_Expression::EV_ulonglong: pt = AST_PredefinedType::PT_ulonglong; break;
00070     case AST_Expression::EV_float: pt = AST_PredefinedType::PT_float; break;
00071     case AST_Expression::EV_double: pt = AST_PredefinedType::PT_double; break;
00072     case AST_Expression::EV_longdouble: pt = AST_PredefinedType::PT_longdouble; break;
00073     case AST_Expression::EV_char: pt = AST_PredefinedType::PT_char; break;
00074     case AST_Expression::EV_wchar: pt = AST_PredefinedType::PT_wchar; break;
00075     case AST_Expression::EV_octet: pt = AST_PredefinedType::PT_octet; break;
00076     case AST_Expression::EV_bool: pt = AST_PredefinedType::PT_boolean; break;
00077     case AST_Expression::EV_string: pt = AST_PredefinedType::PT_char; break;
00078     case AST_Expression::EV_wstring: pt = AST_PredefinedType::PT_wchar; break;
00079 #ifdef ACE_HAS_CDR_FIXED
00080     case AST_Expression::EV_fixed:
00081       be_global->add_include("FACE/Fixed.h", BE_GlobalData::STREAM_LANG_H);
00082       return helpers_[HLP_FIXED_CONSTANT];
00083 #endif
00084     default: break;
00085     }
00086     if (type == AST_Expression::EV_string || type == AST_Expression::EV_wstring)
00087       return primtype_[pt] + "* const";
00088     return primtype_[pt];
00089   }
00090 
00091   std::string exporter() {
00092     return be_global->export_macro().empty() ? ""
00093       : be_global->export_macro().c_str() + std::string(" ");
00094   }
00095 
00096   void struct_decls(UTL_ScopedName* name, AST_Type::SIZE_TYPE size, const char* struct_or_class = "struct")
00097   {
00098     be_global->add_include("<tao/VarOut_T.h>", BE_GlobalData::STREAM_LANG_H);
00099     const char* const nm = name->last_component()->get_string();
00100     be_global->lang_header_ <<
00101       struct_or_class << ' ' << nm << ";\n";
00102     switch (size) {
00103     case AST_Type::SIZE_UNKNOWN:
00104       be_global->lang_header_ << "/* Unknown size */\n";
00105     case AST_Type::FIXED:
00106       be_global->lang_header_ <<
00107         "typedef " << helpers_[HLP_FIX_VAR] << '<' << nm << "> " << nm << "_var;\n" <<
00108         "typedef " << nm << "& " << nm << "_out;\n";
00109       break;
00110     case AST_Type::VARIABLE:
00111       be_global->lang_header_ <<
00112         "typedef " << helpers_[HLP_VAR_VAR] << '<' << nm << "> " << nm << "_var;\n" <<
00113         "typedef " << helpers_[HLP_OUT] << '<' << nm << "> " << nm << "_out;\n";
00114       break;
00115     }
00116   }
00117 
00118   std::string array_dims(AST_Type* type, ACE_CDR::ULong& elems) {
00119     AST_Array* const arr = AST_Array::narrow_from_decl(type);
00120     std::string ret;
00121     for (ACE_CDR::ULong dim = 0; dim < arr->n_dims(); ++dim) {
00122       elems *= arr->dims()[dim]->ev()->u.ulval;
00123       if (dim) ret += "[0]";
00124     }
00125     AST_Type* base = resolveActualType(arr->base_type());
00126     if (AST_Array::narrow_from_decl(base)) {
00127       ret += "[0]" + array_dims(base, elems);
00128     }
00129     return ret;
00130   }
00131 
00132   void gen_typecode(UTL_ScopedName* name)
00133   {
00134     if (be_global->suppress_typecode()) {
00135       return;
00136     }
00137     const char* const nm = name->last_component()->get_string();
00138     be_global->lang_header_ <<
00139       "extern " << exporter() << "const ::CORBA::TypeCode_ptr _tc_" << nm
00140       << ";\n";
00141     const ScopedNamespaceGuard cppNs(name, be_global->impl_);
00142     be_global->impl_ <<
00143       "const ::CORBA::TypeCode_ptr _tc_" << nm << " = 0;\n";
00144   }
00145 
00146 }
00147 
00148 class GeneratorBase
00149 {
00150 public:
00151   virtual ~GeneratorBase() {}
00152   virtual void init() = 0;
00153   virtual void gen_sequence(UTL_ScopedName* tdname, AST_Sequence* seq) = 0;
00154   virtual bool gen_struct(AST_Structure* s, UTL_ScopedName* name, const std::vector<AST_Field*>& fields, AST_Type::SIZE_TYPE size, const char* x) = 0;
00155 
00156   static std::string generateDefaultValue(AST_Union* the_union, AST_Type* discriminator)
00157   {
00158     std::stringstream first_label;
00159     AST_Union::DefaultValue dv;
00160     the_union->default_value(dv);
00161 
00162     switch (the_union->udisc_type ())
00163       {
00164       case AST_Expression::EV_short:
00165         first_label << dv.u.short_val;
00166         break;
00167       case AST_Expression::EV_ushort:
00168         first_label << dv.u.ushort_val;
00169         break;
00170       case AST_Expression::EV_long:
00171         first_label << dv.u.long_val;
00172         break;
00173       case AST_Expression::EV_ulong:
00174         first_label << dv.u.ulong_val;
00175         break;
00176       case AST_Expression::EV_char:
00177         first_label << (int)dv.u.char_val;
00178         break;
00179       case AST_Expression::EV_bool:
00180         first_label << (dv.u.bool_val == 0 ? "false" : "true");
00181         break;
00182       case AST_Expression::EV_enum:
00183         {
00184           AST_Enum* e = AST_Enum::narrow_from_decl(discriminator);
00185           first_label << scoped(e->value_to_name(dv.u.enum_val));
00186           break;
00187         }
00188       case AST_Expression::EV_longlong:
00189         first_label << dv.u.longlong_val;
00190         break;
00191       case AST_Expression::EV_ulonglong:
00192         first_label << dv.u.ulonglong_val;
00193         break;
00194       default:
00195         std::cerr << "Illegal discriminator for union\n";
00196         break;
00197       }
00198 
00199     return first_label.str();
00200   }
00201 
00202   struct GenerateGettersAndSetters
00203   {
00204     AST_Union* the_union;
00205     AST_Type* discriminator;
00206 
00207     GenerateGettersAndSetters (AST_Union* u, AST_Type* d)
00208       : the_union(u)
00209       , discriminator(d)
00210     { }
00211 
00212     void operator() (AST_UnionBranch* branch)
00213     {
00214       const char* field_name = branch->local_name()->get_string();
00215       std::stringstream first_label;
00216       {
00217         AST_UnionLabel* label = branch->label(0);
00218         if (label->label_kind() == AST_UnionLabel::UL_default) {
00219           first_label << generateDefaultValue(the_union, discriminator);
00220         } else if (discriminator->node_type() == AST_Decl::NT_enum) {
00221           first_label << getEnumLabel(label->label_val(), discriminator);
00222         } else {
00223           first_label << *label->label_val()->ev();
00224         }
00225       }
00226 
00227       AST_Type* field_type = branch->field_type();
00228       const std::string field_type_string = map_type(field_type);
00229       AST_Type* actual_field_type = resolveActualType(field_type);
00230       const Classification cls = classify(actual_field_type);
00231       if (cls & (CL_PRIMITIVE | CL_ENUM)) {
00232         be_global->lang_header_ <<
00233           "  void " << field_name << " (" << field_type_string << " x) {\n"
00234           "    _reset();\n"
00235           "    this->_u." << field_name << " = x;\n"
00236           "    _discriminator = " << first_label.str() << ";\n"
00237           "  }\n"
00238           "  " << field_type_string << ' ' << field_name << " () const {\n"
00239           "    return this->_u." << field_name << ";\n"
00240           "  }\n";
00241       } else if (cls & CL_STRING) {
00242         const std::string& primtype = (cls & CL_WIDE) ? primtype_[AST_PredefinedType::PT_wchar] : primtype_[AST_PredefinedType::PT_char];
00243         const std::string& helper = (cls & CL_WIDE) ? helpers_[HLP_WSTR_VAR] : helpers_[HLP_STR_VAR];
00244         be_global->lang_header_ <<
00245           "  void " << field_name << " (" << primtype << "* x) {\n"
00246           "    _reset();\n" <<
00247           "    this->_u." << field_name << " = x;\n"
00248           "    _discriminator = " << first_label.str() << ";\n"
00249           "  }\n"
00250           "  void " << field_name << " (const " << primtype << "* x) {\n"
00251           "    _reset();\n"
00252           "    this->_u." << field_name << " = ::CORBA::string_dup(x);\n"
00253           "    _discriminator = " << first_label.str() << ";\n"
00254           "  }\n"
00255           "  void " << field_name << " (const " << helper << "& x) {\n"
00256           "    _reset();\n" <<
00257           "    this->_u." << field_name << " = ::CORBA::string_dup(x.in());\n"
00258           "    _discriminator = " << first_label.str() << ";\n"
00259           "  }\n"
00260           "  const " << primtype << "* " << field_name << " () const {\n"
00261           "    return this->_u." << field_name << ";\n"
00262           "  }\n";
00263       } else if (cls & CL_ARRAY) {
00264         be_global->lang_header_ <<
00265           "  void " << field_name << " (" << field_type_string << " x) {\n"
00266           "    _reset();\n" <<
00267           "    this->_u." << field_name << " = " << field_type_string << "_dup(x);\n"
00268           "    _discriminator = " << first_label.str() << ";\n"
00269           "  }\n"
00270           "  " << field_type_string << "_slice* " << field_name << " () const {\n"
00271           "    return this->_u." << field_name << ";\n"
00272           "  }\n";
00273       } else if (cls & (CL_STRUCTURE | CL_UNION | CL_SEQUENCE | CL_FIXED)) {
00274         be_global->lang_header_ <<
00275           "  void " << field_name << " (const " << field_type_string << "& x) {\n"
00276           "    _reset();\n"
00277           "    this->_u." << field_name << " = new " << field_type_string << "(x);\n"
00278           "    _discriminator = " << first_label.str() << ";\n"
00279           "  }\n"
00280           "  const " << field_type_string << "& " << field_name << " () const {\n"
00281           "    return *this->_u." << field_name << ";\n"
00282           "  }\n"
00283           "  " << field_type_string << "& " << field_name << " () {\n"
00284           "    return *this->_u." << field_name << ";\n"
00285           "  }\n";
00286       } else {
00287         std::cerr << "Unsupported type for union element\n";
00288       }
00289     }
00290   };
00291 
00292   static bool hasDefaultLabel (const std::vector<AST_UnionBranch*>& branches)
00293   {
00294     for (std::vector<AST_UnionBranch*>::const_iterator pos = branches.begin(), limit = branches.end();
00295          pos != limit;
00296          ++pos) {
00297       AST_UnionBranch* branch = *pos;
00298       for (unsigned long j = 0; j < branch->label_list_length(); ++j) {
00299         AST_UnionLabel* label = branch->label(j);
00300         if (label->label_kind() == AST_UnionLabel::UL_default) {
00301           return true;
00302         }
00303       }
00304     }
00305     return false;
00306   }
00307 
00308   static size_t countLabels (const std::vector<AST_UnionBranch*>& branches)
00309   {
00310     size_t count = 0;
00311 
00312     for (std::vector<AST_UnionBranch*>::const_iterator pos = branches.begin(), limit = branches.end();
00313          pos != limit;
00314          ++pos) {
00315       count += (*pos)->label_list_length();
00316     }
00317 
00318     return count;
00319   }
00320 
00321   static bool needsDefault (const std::vector<AST_UnionBranch*>& branches, AST_Type* discriminator)
00322   {
00323     return !hasDefaultLabel(branches) && needSyntheticDefault(discriminator, countLabels(branches));
00324   }
00325 
00326   static void generate_union_field (AST_UnionBranch* branch)
00327   {
00328     AST_Type* field_type = branch->field_type();
00329     AST_Type* actual_field_type = resolveActualType(field_type);
00330     const Classification cls = classify(actual_field_type);
00331     if (cls & (CL_PRIMITIVE | CL_ENUM)) {
00332       be_global->lang_header_ <<
00333         "    " << map_type(field_type) << ' ' << branch->local_name()->get_string() << ";\n";
00334     } else if (cls & CL_STRING) {
00335       const AST_PredefinedType::PredefinedType chartype = (cls & CL_WIDE)
00336         ? AST_PredefinedType::PT_wchar : AST_PredefinedType::PT_char;
00337       be_global->lang_header_ <<
00338         "    " << primtype_[chartype] << "* " << branch->local_name()->get_string() << ";\n";
00339     } else if (cls & CL_ARRAY) {
00340       be_global->lang_header_ <<
00341         "    " << map_type(field_type) << "_slice* " << branch->local_name()->get_string() << ";\n";
00342     } else if (cls & (CL_STRUCTURE | CL_UNION | CL_SEQUENCE | CL_FIXED)) {
00343       be_global->lang_header_ <<
00344         "    " << map_type(field_type) << "* " << branch->local_name()->get_string() << ";\n";
00345     } else {
00346       std::cerr << "Unsupported type for union element\n";
00347     }
00348   }
00349 
00350   static std::string generateCopyCtor(const std::string& name, AST_Type* field_type,
00351                                       const std::string&, std::string&,
00352                                       const std::string&)
00353   {
00354     std::stringstream ss;
00355     AST_Type* actual_field_type = resolveActualType(field_type);
00356     const Classification cls = classify(actual_field_type);
00357     if (cls & (CL_PRIMITIVE | CL_ENUM)) {
00358       ss <<
00359         "    this->_u." << name << " = other._u." << name << ";\n";
00360     } else if (cls & CL_STRING) {
00361       ss <<
00362         "    this->_u." << name << " = (other._u." << name << ") ? ::CORBA::string_dup(other._u." << name << ") : 0 ;\n";
00363     } else if (cls & CL_ARRAY) {
00364       ss <<
00365         "    this->_u." << name << " = (other._u." << name << ") ? " << map_type(field_type) << "_dup(other._u." << name << ") : 0 ;\n";
00366     } else if (cls & (CL_STRUCTURE | CL_UNION | CL_SEQUENCE | CL_FIXED)) {
00367       ss <<
00368         "    this->_u." << name << " = (other._u." << name << ") ? new " << map_type(field_type) << "(*other._u." << name << ") : 0;\n";
00369     } else {
00370       std::cerr << "Unsupported type for union element\n";
00371     }
00372 
00373     return ss.str();
00374   }
00375 
00376   static std::string generateAssign(const std::string& name, AST_Type* field_type,
00377                                     const std::string&, std::string&,
00378                                     const std::string&)
00379   {
00380     std::stringstream ss;
00381     AST_Type* actual_field_type = resolveActualType(field_type);
00382     const Classification cls = classify(actual_field_type);
00383     if (cls & (CL_PRIMITIVE | CL_ENUM)) {
00384       ss <<
00385         "      this->_u." << name << " = other._u." << name << ";\n";
00386     } else if (cls & CL_STRING) {
00387       ss <<
00388         "      this->_u." << name << " = (other._u." << name << ") ? ::CORBA::string_dup(other._u." << name << ") : 0 ;\n";
00389     } else if (cls & CL_ARRAY) {
00390       ss <<
00391         "    this->_u." << name << " = (other._u." << name << ") ? " << map_type(field_type) << "_dup(other._u." << name << ") : 0 ;\n";
00392     } else if (cls & (CL_STRUCTURE | CL_UNION | CL_SEQUENCE | CL_FIXED)) {
00393       ss <<
00394         "      this->_u." << name << " = (other._u." << name << ") ? new " << map_type(field_type) << "(*other._u." << name << ") : 0;\n";
00395     } else {
00396       std::cerr << "Unsupported type for union element\n";
00397     }
00398 
00399     return ss.str();
00400   }
00401 
00402   static std::string generateEqual(const std::string& name, AST_Type* field_type,
00403                                    const std::string&, std::string&,
00404                                    const std::string&)
00405   {
00406     std::stringstream ss;
00407 
00408     AST_Type* actual_field_type = resolveActualType(field_type);
00409     const Classification cls = classify(actual_field_type);
00410     if (cls & (CL_PRIMITIVE | CL_ENUM)) {
00411       ss <<
00412         "      return this->_u." << name << " == rhs._u." << name << ";\n";
00413     } else if (cls & CL_STRING) {
00414       ss <<
00415         "      return std::strcmp (this->_u." << name << ", rhs._u." << name << ") == 0 ;\n";
00416     } else if (cls & CL_ARRAY) {
00417       // TODO
00418       ss <<
00419         "      return false;\n";
00420     } else if (cls & (CL_STRUCTURE | CL_UNION | CL_SEQUENCE | CL_FIXED)) {
00421       ss <<
00422         "      return *this->_u." << name << " == *rhs._u." << name << ";\n";
00423     } else {
00424       std::cerr << "Unsupported type for union element\n";
00425     }
00426 
00427     return ss.str();
00428   }
00429 
00430   static std::string generateReset(const std::string& name, AST_Type* field_type,
00431                                    const std::string&, std::string&,
00432                                    const std::string&)
00433   {
00434     std::stringstream ss;
00435 
00436     AST_Type* actual_field_type = resolveActualType(field_type);
00437     const Classification cls = classify(actual_field_type);
00438     if (cls & (CL_PRIMITIVE | CL_ENUM)) {
00439       // Do nothing.
00440     } else if (cls & CL_STRING) {
00441       ss <<
00442         "      ::CORBA::string_free(this->_u." << name << ");\n"
00443         "      this->_u." << name << " = 0;\n";
00444     } else if (cls & CL_ARRAY) {
00445       ss <<
00446         "      " << map_type(field_type) << "_free(this->_u." << name << ");\n"
00447         "      this->_u." << name << " = 0;\n";
00448     } else if (cls & (CL_STRUCTURE | CL_UNION | CL_SEQUENCE | CL_FIXED)) {
00449       ss <<
00450         "      delete this->_u." << name << ";\n"
00451         "      this->_u." << name << " = 0;\n";
00452     } else {
00453       std::cerr << "Unsupported type for union element\n";
00454     }
00455 
00456     return ss.str();
00457   }
00458 
00459   bool gen_union(AST_Union* u, UTL_ScopedName* name, const std::vector<AST_UnionBranch*>& branches, AST_Type* discriminator)
00460   {
00461     const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
00462     const char* const nm = name->last_component()->get_string();
00463     struct_decls(name, u->size_type(), "class");
00464     be_global->lang_header_ <<
00465       "\n"
00466       "class " << exporter() << nm << " \n"
00467       "{\n"
00468       " public:\n"
00469       "  typedef " << nm << "_var _var_type;\n"
00470       "  typedef " << nm << "_out _out_type;\n"
00471       "  " << nm << "();\n"
00472       "  " << nm << "(const " << nm << "&);\n"
00473       "  ~" << nm << "() { _reset(); };\n"
00474       "  " << nm << "& operator=(const " << nm << "&);\n"
00475       "  void _d(" << scoped(discriminator->name()) << " d) { _discriminator = d; }\n"
00476       "  " << scoped(discriminator->name()) << " _d() const { return _discriminator; }\n";
00477 
00478     std::for_each (branches.begin(), branches.end(), GenerateGettersAndSetters(u, discriminator));
00479 
00480     if (needsDefault(branches, discriminator)) {
00481       be_global->lang_header_ <<
00482         "  void _default() {\n"
00483         "    _reset();\n"
00484         "    _discriminator = " << generateDefaultValue(u, discriminator) << ";\n"
00485         "  }\n";
00486     }
00487 
00488     be_global->lang_header_ <<
00489       "  bool operator==(const " << nm << "& rhs) const;\n"
00490       "  bool operator!=(const " << nm << "& rhs) const { return !(*this == rhs); }\n"
00491       "  OPENDDS_POOL_ALLOCATION_HOOKS\n";
00492 
00493     be_global->lang_header_ <<
00494       " private:\n"
00495       "  " << scoped(discriminator->name()) << " _discriminator;\n"
00496       "  union {\n";
00497 
00498     std::for_each (branches.begin(), branches.end(), generate_union_field);
00499 
00500     be_global->lang_header_ <<
00501       "  } _u;\n";
00502 
00503     be_global->lang_header_ <<
00504       "  void _reset();\n"
00505       "};\n\n";
00506 
00507     be_global->add_include("dds/DCPS/PoolAllocationBase.h");
00508     be_global->add_include("<ace/CDR_Stream.h>", BE_GlobalData::STREAM_LANG_H);
00509 
00510     be_global->lang_header_ <<
00511       exporter() << "ACE_CDR::Boolean operator<< (ACE_OutputCDR& os, const " << nm << "& x);\n\n";
00512     be_global->lang_header_ <<
00513       exporter() << "ACE_CDR::Boolean operator>> (ACE_InputCDR& os, " << nm << "& x);\n\n";
00514 
00515     {
00516       const ScopedNamespaceGuard guard(name, be_global->impl_);
00517 
00518       be_global->impl_ <<
00519         nm << "::" << nm << "() { std::memset (this, 0, sizeof (" << nm << ")); }\n\n";
00520 
00521       be_global->impl_ <<
00522         nm << "::" << nm << "(const " << nm << "& other) {\n" <<
00523         "  this->_discriminator = other._discriminator;\n";
00524       generateSwitchForUnion("this->_discriminator", generateCopyCtor, branches, discriminator, "", "", "", false, false);
00525       be_global->impl_ <<
00526         "}\n\n";
00527 
00528       be_global->impl_ <<
00529         nm << "& " << nm << "::operator=(const " << nm << "& other) {\n" <<
00530         "  if (this != &other) {\n" <<
00531         "    _reset();\n" <<
00532         "    this->_discriminator = other._discriminator;\n";
00533       generateSwitchForUnion("this->_discriminator", generateAssign, branches, discriminator, "", "", "", false, false);
00534       be_global->impl_ <<
00535         "  }\n"
00536         "  return *this;\n"
00537         "}\n\n";
00538 
00539       be_global->impl_ <<
00540         "bool " << nm << "::operator==(const " << nm << "& rhs) const\n"
00541         "{\n"
00542         "  if (this->_discriminator != rhs._discriminator) return false;";
00543       generateSwitchForUnion("this->_discriminator", generateEqual, branches, discriminator, "", "", "", false, false);
00544       be_global->impl_ <<
00545         "    return false;\n"
00546         "  }\n";
00547 
00548       be_global->impl_ <<
00549         "void " << nm << "::_reset()\n"
00550         "{\n";
00551       generateSwitchForUnion("this->_discriminator", generateReset, branches, discriminator, "", "", "", false, false);
00552       be_global->impl_ <<
00553         "  }\n";
00554 
00555       be_global->impl_ <<
00556         "ACE_CDR::Boolean operator<< (ACE_OutputCDR &, const " << nm << "&) { return true; }\n\n";
00557       be_global->impl_ <<
00558         "ACE_CDR::Boolean operator>> (ACE_InputCDR &, " << nm << "&) { return true; }\n\n";
00559     }
00560 
00561     gen_typecode(name);
00562     return true;
00563   }
00564 };
00565 
00566 class FaceGenerator : public GeneratorBase
00567 {
00568 public:
00569   virtual void init()
00570   {
00571     be_global->add_include("FACE/types.hpp", BE_GlobalData::STREAM_LANG_H);
00572     be_global->add_include("FACE/StringManager.h", BE_GlobalData::STREAM_LANG_H);
00573     primtype_[AST_PredefinedType::PT_long] = "::FACE::Long";
00574     primtype_[AST_PredefinedType::PT_ulong] = "::FACE::UnsignedLong";
00575     primtype_[AST_PredefinedType::PT_longlong] = "::FACE::LongLong";
00576     primtype_[AST_PredefinedType::PT_ulonglong] = "::FACE::UnsignedLongLong";
00577     primtype_[AST_PredefinedType::PT_short] = "::FACE::Short";
00578     primtype_[AST_PredefinedType::PT_ushort] = "::FACE::UnsignedShort";
00579     primtype_[AST_PredefinedType::PT_float] = "::FACE::Float";
00580     primtype_[AST_PredefinedType::PT_double] = "::FACE::Double";
00581     primtype_[AST_PredefinedType::PT_longdouble] = "::FACE::LongDouble";
00582     primtype_[AST_PredefinedType::PT_char] = "::FACE::Char";
00583     primtype_[AST_PredefinedType::PT_wchar] = "::FACE::WChar";
00584     primtype_[AST_PredefinedType::PT_boolean] = "::FACE::Boolean";
00585     primtype_[AST_PredefinedType::PT_octet] = "::FACE::Octet";
00586     helpers_[HLP_STR_VAR] = "::FACE::String_var";
00587     helpers_[HLP_STR_OUT] = "::FACE::String_out";
00588     helpers_[HLP_WSTR_VAR] = "::FACE::WString_var";
00589     helpers_[HLP_WSTR_OUT] = "::FACE::WString_out";
00590     helpers_[HLP_STR_MGR] = "::OpenDDS::FaceTypes::String_mgr";
00591     helpers_[HLP_WSTR_MGR] = "::OpenDDS::FaceTypes::WString_mgr";
00592     helpers_[HLP_FIX_VAR] = "::TAO_Fixed_Var_T";
00593     helpers_[HLP_VAR_VAR] = "::TAO_Var_Var_T";
00594     helpers_[HLP_OUT] = "::TAO_Out_T";
00595     helpers_[HLP_SEQ] = "::OpenDDS::FaceTypes::Sequence";
00596     helpers_[HLP_SEQ_NS] = "::OpenDDS::FaceTypes";
00597     helpers_[HLP_SEQ_VAR_VAR] = "::OpenDDS::FaceTypes::SequenceVar";
00598     helpers_[HLP_SEQ_FIX_VAR] = "::OpenDDS::FaceTypes::SequenceVar";
00599     helpers_[HLP_SEQ_OUT] = "::TAO_Seq_Out_T";
00600     helpers_[HLP_ARR_VAR_VAR] = "::TAO_VarArray_Var_T";
00601     helpers_[HLP_ARR_FIX_VAR] = "::TAO_FixedArray_Var_T";
00602     helpers_[HLP_ARR_OUT] = "::TAO_Array_Out_T";
00603     helpers_[HLP_ARR_FORANY] = "::TAO_Array_Forany_T";
00604     helpers_[HLP_FIXED] = "::OpenDDS::FaceTypes::Fixed_T";
00605     helpers_[HLP_FIXED_CONSTANT] = "::OpenDDS::FaceTypes::Fixed";
00606   }
00607 
00608   void gen_sequence(UTL_ScopedName* tdname, AST_Sequence* seq)
00609   {
00610     be_global->add_include("<tao/Seq_Out_T.h>", BE_GlobalData::STREAM_LANG_H);
00611     be_global->add_include("FACE/Sequence.h", BE_GlobalData::STREAM_LANG_H);
00612     be_global->add_include("FACE/SequenceVar.h", BE_GlobalData::STREAM_LANG_H);
00613     be_global->add_include("<ace/CDR_Stream.h>", BE_GlobalData::STREAM_LANG_H);
00614     const char* const nm = tdname->last_component()->get_string();
00615     AST_Type* elem = seq->base_type();
00616     const Classification elem_cls = classify(elem);
00617     const bool bounded = !seq->unbounded();
00618     const Helper var = (elem->size_type() == AST_Type::VARIABLE)
00619                         ? HLP_SEQ_VAR_VAR : HLP_SEQ_FIX_VAR,
00620       out = HLP_SEQ_OUT;
00621 
00622     std::string elem_type = map_type(elem), extra_tmp_args;
00623     if (elem_cls & CL_STRING) {
00624       const AST_Expression::ExprType char_type = (elem_cls & CL_WIDE)
00625         ? AST_Expression::EV_wchar : AST_Expression::EV_char;
00626       extra_tmp_args = ", " + helpers_[HLP_SEQ_NS] + "::StringEltPolicy< "
00627         + map_type(char_type) + ">";
00628     } else if (elem_cls & CL_ARRAY) {
00629       extra_tmp_args = ", " + helpers_[HLP_SEQ_NS] + "::ArrayEltPolicy<"
00630         + elem_type + "_forany>";
00631     } else if (elem->size_type() == AST_Type::VARIABLE) {
00632       extra_tmp_args = ", " +  helpers_[HLP_SEQ_NS] + "::VariEltPolicy<"
00633         + elem_type + ">";
00634     }
00635 
00636     std::string bound = helpers_[HLP_SEQ_NS] + "::Unbounded";
00637     if (bounded) {
00638       std::ostringstream oss;
00639       oss << helpers_[HLP_SEQ_NS] << "::Bounded<"
00640         << seq->max_size()->ev()->u.ulval << '>';
00641       bound = oss.str();
00642     }
00643 
00644     const std::string base = helpers_[HLP_SEQ] + "< " + elem_type + ", " + bound
00645                            + extra_tmp_args + " >",
00646       len_type = primtype_[AST_PredefinedType::PT_ulong],
00647       flag_type = primtype_[AST_PredefinedType::PT_boolean];
00648 
00649     be_global->lang_header_ <<
00650       "class " << nm << ";\n"
00651       "typedef " << helpers_[var] << '<' << nm << "> " << nm << "_var;\n"
00652       "typedef " << helpers_[out] << '<' << nm << "> " << nm << "_out;\n\n"
00653       "class " << exporter() << nm << " : public " << base << " {\n"
00654       "public:\n"
00655       "  typedef " << nm << "_var _var_type;\n"
00656       "  typedef " << nm << "_out _out_type;\n\n"
00657       "  " << nm << "() {}\n"
00658       "  " << nm << "(const " << nm << "& seq) : " << base << "(seq) {}\n"
00659       "  friend void swap(" << nm << "& a, " << nm << "& b) { a.swap(b); }\n"
00660       "  " << nm << "& operator=(const " << nm << "& rhs)\n"
00661       "  {\n"
00662       "    " << nm << " tmp(rhs);\n"
00663       "    swap(tmp);\n"
00664       "    return *this;\n"
00665       "  }\n";
00666 
00667     if (bounded) {
00668       be_global->lang_header_ <<
00669         "  " << nm << "(" << len_type << " length, " << elem_type << "* data, "
00670         << flag_type << " release = false)\n"
00671         "    : " << base << "(0u, length, data, release) {}\n";
00672     } else {
00673       be_global->lang_header_ <<
00674         "  " << nm << "(" << len_type << " maximum)\n"
00675         "    : " << base << "(maximum, 0u, 0, true) {}\n"
00676         "  " << nm << "(" << len_type << " maximum, " << len_type << " length, "
00677         << elem_type << "* data, " << flag_type << " release = false)\n"
00678         "    : " << base << "(maximum, length, data, release) {}\n";
00679     }
00680     be_global->lang_header_ <<
00681       "};\n\n";
00682 
00683     be_global->lang_header_ <<
00684       "inline ACE_CDR::Boolean operator<< (ACE_OutputCDR&, const " << nm << "&) { return true; }\n\n";
00685 
00686     be_global->lang_header_ <<
00687       "inline ACE_CDR::Boolean operator>> (ACE_InputCDR&, " << nm << "&) { return true; }\n\n";
00688   }
00689 
00690   bool gen_struct(AST_Structure*, UTL_ScopedName* name,
00691                   const std::vector<AST_Field*>& fields,
00692                   AST_Type::SIZE_TYPE size,
00693                   const char*)
00694   {
00695     const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
00696     const char* const nm = name->last_component()->get_string();
00697     struct_decls(name, size);
00698     be_global->lang_header_ <<
00699       "\n"
00700       "struct " << exporter() << nm << "\n"
00701       "{\n"
00702       "  typedef " << nm << "_var _var_type;\n"
00703       "  typedef " << nm << "_out _out_type;\n\n";
00704 
00705     for (size_t i = 0; i < fields.size(); ++i) {
00706       AST_Type* field_type = fields[i]->field_type();
00707       const std::string field_name = fields[i]->local_name()->get_string();
00708       std::string type_name = map_type(field_type);
00709       const Classification cls = classify(field_type);
00710       if (cls & CL_STRING) {
00711         type_name = helpers_[(cls & CL_WIDE) ? HLP_WSTR_MGR : HLP_STR_MGR];
00712       }
00713       be_global->lang_header_ <<
00714         "  " << type_name << ' ' << field_name << ";\n";
00715     }
00716 
00717     be_global->lang_header_ << "\n"
00718       "  bool operator==(const " << nm << "& rhs) const;\n"
00719       "  bool operator!=(const " << nm << "& rhs) const { return !(*this == rhs); }\n"
00720       "  OPENDDS_POOL_ALLOCATION_HOOKS\n"
00721       "};\n\n";
00722 
00723     be_global->add_include("dds/DCPS/PoolAllocationBase.h");
00724     be_global->add_include("<ace/CDR_Stream.h>", BE_GlobalData::STREAM_LANG_H);
00725 
00726     if (size == AST_Type::VARIABLE) {
00727       be_global->lang_header_ <<
00728         exporter() << "void swap(" << nm << "& lhs, " << nm << "& rhs);\n\n";
00729     }
00730 
00731     be_global->lang_header_ <<
00732       exporter() << "ACE_CDR::Boolean operator<< (ACE_OutputCDR& os, const " << nm << "& x);\n\n";
00733     be_global->lang_header_ <<
00734       exporter() << "ACE_CDR::Boolean operator>> (ACE_InputCDR& os, " << nm << "& x);\n\n";
00735 
00736     {
00737       const ScopedNamespaceGuard guard(name, be_global->impl_);
00738       be_global->impl_ <<
00739         "bool " << nm << "::operator==(const " << nm << "& rhs) const\n"
00740         "{\n";
00741       for (size_t i = 0; i < fields.size(); ++i) {
00742         const std::string field_name = fields[i]->local_name()->get_string();
00743         AST_Type* field_type = resolveActualType(fields[i]->field_type());
00744         const Classification cls = classify(field_type);
00745         if (cls & CL_ARRAY) {
00746           std::string indent("  ");
00747           NestedForLoops nfl("int", "i",
00748             AST_Array::narrow_from_decl(field_type), indent, true);
00749           be_global->impl_ <<
00750             indent << "if (" << field_name << nfl.index_ << " != rhs."
00751             << field_name << nfl.index_ << ") {\n" <<
00752             indent << "  return false;\n" <<
00753             indent << "}\n";
00754         } else {
00755           be_global->impl_ <<
00756             "  if (" << field_name << " != rhs." << field_name << ") {\n"
00757             "    return false;\n"
00758             "  }\n";
00759         }
00760       }
00761       be_global->impl_ << "  return true;\n}\n\n";
00762 
00763       if (size == AST_Type::VARIABLE) {
00764         be_global->impl_ <<
00765           "void swap(" << nm << "& lhs, " << nm << "& rhs)\n"
00766           "{\n"
00767           "  using std::swap;\n";
00768         for (size_t i = 0; i < fields.size(); ++i) {
00769           const std::string fn = fields[i]->local_name()->get_string();
00770           AST_Type* field_type = resolveActualType(fields[i]->field_type());
00771           const Classification cls = classify(field_type);
00772           if (cls & CL_ARRAY) {
00773             ACE_CDR::ULong elems = 1;
00774             const std::string flat_fn = fn + array_dims(field_type, elems);
00775             be_global->add_include("<algorithm>", BE_GlobalData::STREAM_CPP);
00776             be_global->impl_ <<
00777               "  std::swap_ranges(lhs." << flat_fn << ", lhs." << flat_fn
00778                                         << " + " << elems << ", rhs." << flat_fn << ");\n";
00779           } else {
00780             be_global->impl_ <<
00781               "  swap(lhs." << fn << ", rhs." << fn << ");\n";
00782           }
00783         }
00784         be_global->impl_ << "}\n\n";
00785       }
00786 
00787       be_global->impl_ <<
00788         "ACE_CDR::Boolean operator<< (ACE_OutputCDR &, const " << nm << "&) { return true; }\n\n";
00789       be_global->impl_ <<
00790         "ACE_CDR::Boolean operator>> (ACE_InputCDR &, " << nm << "&) { return true; }\n\n";
00791     }
00792 
00793     gen_typecode(name);
00794     return true;
00795   }
00796 
00797   static FaceGenerator instance;
00798 };
00799 FaceGenerator FaceGenerator::instance;
00800 
00801 class SafetyProfileGenerator : public GeneratorBase
00802 {
00803 public:
00804   virtual void init()
00805   {
00806     be_global->add_include("tao/String_Manager_T.h", BE_GlobalData::STREAM_LANG_H);
00807     be_global->add_include("tao/CORBA_String.h", BE_GlobalData::STREAM_LANG_H);
00808     primtype_[AST_PredefinedType::PT_long] = "CORBA::Long";
00809     primtype_[AST_PredefinedType::PT_ulong] = "CORBA::ULong";
00810     primtype_[AST_PredefinedType::PT_longlong] = "CORBA::LongLong";
00811     primtype_[AST_PredefinedType::PT_ulonglong] = "CORBA::UnsignedLongLong";
00812     primtype_[AST_PredefinedType::PT_short] = "CORBA::Short";
00813     primtype_[AST_PredefinedType::PT_ushort] = "CORBA::UShort";
00814     primtype_[AST_PredefinedType::PT_float] = "CORBA::Float";
00815     primtype_[AST_PredefinedType::PT_double] = "CORBA::Double";
00816     primtype_[AST_PredefinedType::PT_longdouble] = "CORBA::LongDouble";
00817     primtype_[AST_PredefinedType::PT_char] = "CORBA::Char";
00818     primtype_[AST_PredefinedType::PT_wchar] = "CORBA::WChar";
00819     primtype_[AST_PredefinedType::PT_boolean] = "CORBA::Boolean";
00820     primtype_[AST_PredefinedType::PT_octet] = "CORBA::Octet";
00821     helpers_[HLP_STR_VAR] = "CORBA::String_var";
00822     helpers_[HLP_STR_OUT] = "CORBA::String_out";
00823     helpers_[HLP_WSTR_VAR] = "CORBA::WString_var";
00824     helpers_[HLP_WSTR_OUT] = "CORBA::WString_out";
00825     helpers_[HLP_STR_MGR] = "::TAO::String_Manager";
00826     helpers_[HLP_WSTR_MGR] = "CORBA::WString_mgr";
00827     helpers_[HLP_FIX_VAR] = "::TAO_Fixed_Var_T";
00828     helpers_[HLP_VAR_VAR] = "::TAO_Var_Var_T";
00829     helpers_[HLP_OUT] = "::TAO_Out_T";
00830     helpers_[HLP_SEQ] = "::OpenDDS::SafetyProfile::Sequence";
00831     helpers_[HLP_SEQ_NS] = "::OpenDDS::SafetyProfile";
00832     helpers_[HLP_SEQ_VAR_VAR] = "::OpenDDS::SafetyProfile::SequenceVar";
00833     helpers_[HLP_SEQ_FIX_VAR] = "::OpenDDS::SafetyProfile::SequenceVar";
00834     helpers_[HLP_SEQ_OUT] = "::TAO_Seq_Out_T";
00835     helpers_[HLP_ARR_VAR_VAR] = "::TAO_VarArray_Var_T";
00836     helpers_[HLP_ARR_FIX_VAR] = "::TAO_FixedArray_Var_T";
00837     helpers_[HLP_ARR_OUT] = "::TAO_Array_Out_T";
00838     helpers_[HLP_ARR_FORANY] = "::TAO_Array_Forany_T";
00839   }
00840 
00841   virtual void gen_sequence(UTL_ScopedName* tdname, AST_Sequence* seq)
00842   {
00843     be_global->add_include("<tao/Seq_Out_T.h>", BE_GlobalData::STREAM_LANG_H);
00844     be_global->add_include("dds/DCPS/SafetyProfileSequence.h", BE_GlobalData::STREAM_LANG_H);
00845     be_global->add_include("dds/DCPS/SafetyProfileSequenceVar.h", BE_GlobalData::STREAM_LANG_H);
00846     const char* const nm = tdname->last_component()->get_string();
00847     AST_Type* elem = seq->base_type();
00848     const Classification elem_cls = classify(elem);
00849     const bool bounded = !seq->unbounded();
00850     const Helper var = (elem->size_type() == AST_Type::VARIABLE)
00851                         ? HLP_SEQ_VAR_VAR : HLP_SEQ_FIX_VAR,
00852       out = HLP_SEQ_OUT;
00853 
00854     std::string elem_type = map_type(elem), extra_tmp_args;
00855     if (elem_cls & CL_STRING) {
00856       const AST_Expression::ExprType char_type = (elem_cls & CL_WIDE)
00857         ? AST_Expression::EV_wchar : AST_Expression::EV_char;
00858       extra_tmp_args = ", " + helpers_[HLP_SEQ_NS] + "::StringEltPolicy< "
00859         + map_type(char_type) + ">";
00860     } else if (elem_cls & CL_ARRAY) {
00861       extra_tmp_args = ", " + helpers_[HLP_SEQ_NS] + "::ArrayEltPolicy<"
00862         + elem_type + "_forany>";
00863     } else if (elem->size_type() == AST_Type::VARIABLE) {
00864       extra_tmp_args = ", " +  helpers_[HLP_SEQ_NS] + "::VariEltPolicy<"
00865         + elem_type + ">";
00866     }
00867 
00868     std::string bound = helpers_[HLP_SEQ_NS] + "::Unbounded";
00869     if (bounded) {
00870       std::ostringstream oss;
00871       oss << helpers_[HLP_SEQ_NS] << "::Bounded<"
00872         << seq->max_size()->ev()->u.ulval << '>';
00873       bound = oss.str();
00874     }
00875 
00876     const std::string base = helpers_[HLP_SEQ] + "< " + elem_type + ", " + bound
00877                            + extra_tmp_args + " >",
00878       len_type = primtype_[AST_PredefinedType::PT_ulong],
00879       flag_type = primtype_[AST_PredefinedType::PT_boolean];
00880 
00881     be_global->lang_header_ <<
00882       "class " << nm << ";\n"
00883       "typedef " << helpers_[var] << '<' << nm << "> " << nm << "_var;\n"
00884       "typedef " << helpers_[out] << '<' << nm << "> " << nm << "_out;\n\n"
00885       "class " << exporter() << nm << " : public " << base << " {\n"
00886       "public:\n"
00887       "  typedef " << nm << "_var _var_type;\n"
00888       "  typedef " << nm << "_out _out_type;\n\n"
00889       "  " << nm << "() {}\n"
00890       "  " << nm << "(const " << nm << "& seq) : " << base << "(seq) {}\n"
00891       "  friend void swap(" << nm << "& a, " << nm << "& b) { a.swap(b); }\n"
00892       "  " << nm << "& operator=(const " << nm << "& rhs)\n"
00893       "  {\n"
00894       "    " << nm << " tmp(rhs);\n"
00895       "    swap(tmp);\n"
00896       "    return *this;\n"
00897       "  }\n";
00898 
00899     if (bounded) {
00900       be_global->lang_header_ <<
00901         "  " << nm << "(" << len_type << " length, " << elem_type << "* data, "
00902         << flag_type << " release = false)\n"
00903         "    : " << base << "(0u, length, data, release) {}\n";
00904     } else {
00905       be_global->lang_header_ <<
00906         "  " << nm << "(" << len_type << " maximum)\n"
00907         "    : " << base << "(maximum, 0u, 0, true) {}\n"
00908         "  " << nm << "(" << len_type << " maximum, " << len_type << " length, "
00909         << elem_type << "* data, " << flag_type << " release = false)\n"
00910         "    : " << base << "(maximum, length, data, release) {}\n";
00911     }
00912     be_global->lang_header_ <<
00913       "};\n\n";
00914 
00915     be_global->lang_header_ <<
00916       "inline ACE_CDR::Boolean operator<< (ACE_OutputCDR&, const " << nm << "&) { return true; }\n\n";
00917 
00918     be_global->lang_header_ <<
00919       "inline ACE_CDR::Boolean operator>> (ACE_InputCDR&, " << nm << "&) { return true; }\n\n";
00920   }
00921 
00922   bool gen_struct(AST_Structure*, UTL_ScopedName* name,
00923                   const std::vector<AST_Field*>& fields,
00924                   AST_Type::SIZE_TYPE size,
00925                   const char*)
00926   {
00927     const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
00928     const char* const nm = name->last_component()->get_string();
00929     struct_decls(name, size);
00930     be_global->lang_header_ <<
00931       "\n"
00932       "struct " << exporter() << nm << " \n"
00933       "{\n"
00934       "  typedef " << nm << "_var _var_type;\n"
00935       "  typedef " << nm << "_out _out_type;\n\n";
00936 
00937     for (size_t i = 0; i < fields.size(); ++i) {
00938       AST_Type* field_type = fields[i]->field_type();
00939       const std::string field_name = fields[i]->local_name()->get_string();
00940       std::string type_name = map_type(field_type);
00941       const Classification cls = classify(field_type);
00942       if (cls & CL_STRING) {
00943         type_name = helpers_[(cls & CL_WIDE) ? HLP_WSTR_MGR : HLP_STR_MGR];
00944       }
00945       be_global->lang_header_ <<
00946         "  " << type_name << ' ' << field_name << ";\n";
00947     }
00948 
00949     be_global->lang_header_ << "\n"
00950       "  bool operator==(const " << nm << "& rhs) const;\n"
00951       "  bool operator!=(const " << nm << "& rhs) const { return !(*this == rhs); }\n"
00952       "  OPENDDS_POOL_ALLOCATION_HOOKS\n"
00953       "};\n\n";
00954 
00955     be_global->add_include("dds/DCPS/PoolAllocationBase.h");
00956     be_global->add_include("<ace/CDR_Stream.h>", BE_GlobalData::STREAM_LANG_H);
00957 
00958     if (size == AST_Type::VARIABLE) {
00959       be_global->lang_header_ <<
00960         exporter() << "void swap(" << nm << "& lhs, " << nm << "& rhs);\n\n";
00961     }
00962 
00963     be_global->lang_header_ <<
00964       exporter() << "ACE_CDR::Boolean operator<< (ACE_OutputCDR& os, const " << nm << "& x);\n\n";
00965     be_global->lang_header_ <<
00966       exporter() << "ACE_CDR::Boolean operator>> (ACE_InputCDR& os, " << nm << "& x);\n\n";
00967 
00968     {
00969       const ScopedNamespaceGuard guard(name, be_global->impl_);
00970       be_global->impl_ <<
00971         "bool " << nm << "::operator==(const " << nm << "& rhs) const\n"
00972         "{\n";
00973       for (size_t i = 0; i < fields.size(); ++i) {
00974         const std::string field_name = fields[i]->local_name()->get_string();
00975         AST_Type* field_type = resolveActualType(fields[i]->field_type());
00976         const Classification cls = classify(field_type);
00977         if (cls & CL_ARRAY) {
00978           std::string indent("  ");
00979           NestedForLoops nfl("int", "i",
00980             AST_Array::narrow_from_decl(field_type), indent, true);
00981           be_global->impl_ <<
00982             indent << "if (" << field_name << nfl.index_ << " != rhs."
00983             << field_name << nfl.index_ << ") {\n" <<
00984             indent << "  return false;\n" <<
00985             indent << "}\n";
00986         } else {
00987           be_global->impl_ <<
00988             "  if (" << field_name << " != rhs." << field_name << ") {\n"
00989             "    return false;\n"
00990             "  }\n";
00991         }
00992       }
00993       be_global->impl_ << "  return true;\n}\n\n";
00994 
00995       if (size == AST_Type::VARIABLE) {
00996         be_global->impl_ <<
00997           "void swap(" << nm << "& lhs, " << nm << "& rhs)\n"
00998           "{\n"
00999           "  using std::swap;\n";
01000         for (size_t i = 0; i < fields.size(); ++i) {
01001           const std::string fn = fields[i]->local_name()->get_string();
01002           AST_Type* field_type = resolveActualType(fields[i]->field_type());
01003           const Classification cls = classify(field_type);
01004           if (cls & CL_ARRAY) {
01005             ACE_CDR::ULong elems = 1;
01006             const std::string flat_fn = fn + array_dims(field_type, elems);
01007             be_global->add_include("<algorithm>", BE_GlobalData::STREAM_CPP);
01008             be_global->impl_ <<
01009               "  std::swap_ranges(lhs." << flat_fn << ", lhs." << flat_fn
01010                                         << " + " << elems << ", rhs." << flat_fn << ");\n";
01011           } else {
01012             be_global->impl_ <<
01013               "  swap(lhs." << fn << ", rhs." << fn << ");\n";
01014           }
01015         }
01016         be_global->impl_ << "}\n\n";
01017       }
01018 
01019       be_global->impl_ <<
01020         "ACE_CDR::Boolean operator<< (ACE_OutputCDR &, const " << nm << "&) { return true; }\n\n";
01021       be_global->impl_ <<
01022         "ACE_CDR::Boolean operator>> (ACE_InputCDR &, " << nm << "&) { return true; }\n\n";
01023     }
01024 
01025     gen_typecode(name);
01026     return true;
01027   }
01028 
01029   static SafetyProfileGenerator instance;
01030 };
01031 SafetyProfileGenerator SafetyProfileGenerator::instance;
01032 
01033 void langmap_generator::init()
01034 {
01035   switch (be_global->language_mapping()) {
01036   case BE_GlobalData::LANGMAP_FACE_CXX:
01037     generator_ = &FaceGenerator::instance;
01038     generator_->init();
01039     break;
01040   case BE_GlobalData::LANGMAP_SP_CXX:
01041     generator_ = &SafetyProfileGenerator::instance;
01042     generator_->init();
01043     break;
01044   default: break;
01045   }
01046 }
01047 
01048 bool langmap_generator::gen_const(UTL_ScopedName* name, bool,
01049                                   AST_Constant* constant)
01050 {
01051   const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
01052   const char* const nm = name->last_component()->get_string();
01053 
01054   const AST_Expression::ExprType type = constant->et();
01055   const bool is_enum = (type == AST_Expression::EV_enum);
01056   const std::string type_name = is_enum
01057     ? scoped(constant->enum_full_name()) : map_type(type);
01058   be_global->lang_header_ <<
01059     "const " << type_name << ' ' << nm << " = ";
01060 
01061   if (is_enum) {
01062     be_global->lang_header_ << scoped(constant->constant_value()->n()) << ";\n";
01063   } else {
01064     be_global->lang_header_ << *constant->constant_value()->ev() << ";\n";
01065   }
01066   return true;
01067 }
01068 
01069 namespace {
01070   void gen_array(UTL_ScopedName* tdname, AST_Array* arr)
01071   {
01072     be_global->add_include("<tao/Array_VarOut_T.h>", BE_GlobalData::STREAM_LANG_H);
01073     be_global->add_include("dds/DCPS/SafetyProfilePool.h", BE_GlobalData::STREAM_LANG_H);
01074     const char* const nm = tdname->last_component()->get_string();
01075     AST_Type* elem = arr->base_type();
01076     const Classification elem_cls = classify(elem);
01077     const Helper var = (elem->size_type() == AST_Type::VARIABLE)
01078                         ? HLP_ARR_VAR_VAR : HLP_ARR_FIX_VAR,
01079       out = HLP_ARR_OUT,
01080       forany = HLP_ARR_FORANY;
01081 
01082     std::ostringstream bound, nofirst, total;
01083     std::string zeros;
01084     for (ACE_CDR::ULong dim = 0; dim < arr->n_dims(); ++dim) {
01085       const ACE_CDR::ULong extent = arr->dims()[dim]->ev()->u.ulval;
01086       bound << '[' << extent << ']';
01087       if (dim) {
01088         nofirst << '[' << extent << ']';
01089         zeros += "[0]";
01090         total << " * ";
01091       }
01092       total << extent;
01093     }
01094 
01095     std::string elem_type = map_type(elem);
01096     if (elem_cls & CL_STRING) {
01097       elem_type = helpers_[(elem_cls & CL_WIDE) ? HLP_WSTR_MGR : HLP_STR_MGR];
01098     }
01099 
01100     std::string out_type = nm;
01101     if (elem->size_type() == AST_Type::VARIABLE) {
01102       out_type = helpers_[out] + '<' + nm + ", " + nm + "_var, " + nm +
01103         "_slice, " + nm + "_tag>";
01104     }
01105 
01106     be_global->lang_header_ <<
01107       "typedef " << elem_type << ' ' << nm << bound.str() << ";\n"
01108       "typedef " << elem_type << ' ' << nm << "_slice" << nofirst.str() << ";\n"
01109       "struct " << nm << "_tag {};\n"
01110       "typedef " << helpers_[var] << '<' << nm << ", " << nm << "_slice, "
01111       << nm << "_tag> " << nm << "_var;\n"
01112       "typedef " << out_type << ' ' << nm << "_out;\n"
01113       "typedef " << helpers_[forany] << '<' << nm << ", " << nm << "_slice, "
01114       << nm << "_tag> " << nm << "_forany;\n\n" <<
01115       exporter() << nm << "_slice* " << nm << "_alloc();\n" <<
01116       exporter() << "void " << nm << "_init_i(" << elem_type << "* begin);\n" <<
01117       exporter() << "void " << nm << "_fini_i(" << elem_type << "* begin);\n" <<
01118       exporter() << "void " << nm << "_free(" << nm << "_slice* slice);\n" <<
01119       exporter() << nm << "_slice* " << nm << "_dup(const " << nm
01120       << "_slice* slice);\n" <<
01121       exporter() << "void " << nm << "_copy(" << nm << "_slice* dst, const "
01122       << nm << "_slice* src);\n\n";
01123     const ScopedNamespaceGuard namespaces(tdname, be_global->impl_);
01124     be_global->impl_ <<
01125       nm << "_slice* " << nm << "_alloc()\n"
01126       "{\n"
01127       "  void* const raw = ACE_Allocator::instance()->malloc"
01128       "(sizeof(" << nm << "));\n"
01129       "  " << nm << "_slice* const slice = static_cast<" << nm << "_slice*"
01130       << ">(raw);\n"
01131       "  " << nm << "_init_i(slice" << zeros << ");\n"
01132       "  return slice;\n"
01133       "}\n\n"
01134       "void " << nm << "_init_i(" << elem_type << "* begin)\n"
01135       "{\n";
01136 
01137     if (elem_cls & (CL_PRIMITIVE | CL_ENUM)) {
01138       be_global->impl_ << "  ACE_UNUSED_ARG(begin);\n";
01139     } else if (elem_cls & CL_ARRAY) {
01140       std::string indent = "  ";
01141       const NestedForLoops nfl("ACE_CDR::ULong", "i", arr, indent);
01142       be_global->impl_ <<
01143         indent << elem_type << "_init_i(begin" << nfl.index_ << ");\n";
01144     } else {
01145       be_global->impl_ <<
01146         "  std::uninitialized_fill_n(begin, " << total.str() << ", "
01147         << elem_type << "());\n";
01148     }
01149 
01150     be_global->impl_ <<
01151       "}\n\n"
01152       "void " << nm << "_fini_i(" << elem_type << "* begin)\n"
01153       "{\n";
01154 
01155     if (elem_cls & (CL_PRIMITIVE | CL_ENUM)) {
01156       be_global->impl_ << "  ACE_UNUSED_ARG(begin);\n";
01157     } else if (elem_cls & CL_ARRAY) {
01158       std::string indent = "  ";
01159       const NestedForLoops nfl("ACE_CDR::ULong", "i", arr, indent);
01160       be_global->impl_ <<
01161         indent << elem_type << "_fini_i(begin" << nfl.index_ << ");\n";
01162     } else {
01163       const std::string::size_type idx_last = elem_type.rfind("::");
01164       const std::string elem_last =
01165         (elem_cls & CL_STRING) ? "StringManager" :
01166         ((idx_last == std::string::npos) ? elem_type
01167           : elem_type.substr(idx_last + 2));
01168       be_global->impl_ <<
01169         "  for (int i = 0; i < " << total.str() << "; ++i) {\n"
01170         "    begin[i]."
01171 #ifdef __SUNPRO_CC
01172         << elem_type << "::"
01173 #endif
01174         "~" << elem_last << "();\n"
01175         "  }\n";
01176     }
01177 
01178     be_global->impl_ <<
01179       "}\n\n"
01180       "void " << nm << "_free(" << nm << "_slice* slice)\n"
01181       "{\n"
01182       "  if (!slice) return;\n"
01183       "  " << nm << "_fini_i(slice" << zeros << ");\n"
01184       "  ACE_Allocator::instance()->free(slice);\n"
01185       "}\n\n" <<
01186       nm << "_slice* " << nm << "_dup(const " << nm << "_slice* slice)\n"
01187       "{\n"
01188       "  " << nm << "_slice* const arr = " << nm << "_alloc();\n"
01189       "  if (arr) " << nm << "_copy(arr, slice);\n"
01190       "  return arr;\n"
01191       "}\n\n"
01192       "void " << nm << "_copy(" << nm << "_slice* dst, const " << nm
01193       << "_slice* src)\n"
01194       "{\n"
01195       "  if (!src || !dst) return;\n";
01196 
01197     {
01198       std::string indent = "  ";
01199       const NestedForLoops nfl("ACE_CDR::ULong", "i", arr, indent);
01200       if (elem_cls & CL_ARRAY) {
01201         be_global->impl_ <<
01202           indent << elem_type << "_copy(dst" << nfl.index_ << ", src"
01203           << nfl.index_ << ");\n";
01204       } else {
01205         be_global->impl_ <<
01206           indent << "dst" << nfl.index_ << " = src" << nfl.index_ << ";\n";
01207       }
01208     }
01209 
01210     be_global->impl_ <<
01211       "}\n\n";
01212 
01213 
01214     be_global->lang_header_ <<
01215       "inline ACE_CDR::Boolean operator<<(ACE_OutputCDR &, const " << nm << "_forany&) { return true; }\n\n"
01216       "inline ACE_CDR::Boolean operator>>(ACE_InputCDR &, " << nm << "_forany&) { return true; }\n\n";
01217   }
01218 }
01219 
01220 bool langmap_generator::gen_enum(AST_Enum*, UTL_ScopedName* name,
01221                                  const std::vector<AST_EnumVal*>& contents,
01222                                  const char*)
01223 {
01224   const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
01225   const char* const nm = name->last_component()->get_string();
01226   be_global->lang_header_ <<
01227     "enum " << nm << " {\n";
01228   for (size_t i = 0; i < contents.size(); ++i) {
01229     be_global->lang_header_ <<
01230       "  " << contents[i]->local_name()->get_string()
01231       << ((i < contents.size() - 1) ? ",\n" : "\n");
01232   }
01233   be_global->lang_header_ <<
01234     "};\n\n"
01235     "typedef " << nm << "& " << nm << "_out;\n";
01236   gen_typecode(name);
01237   return true;
01238 }
01239 
01240 bool langmap_generator::gen_struct_fwd(UTL_ScopedName* name,
01241                                        AST_Type::SIZE_TYPE size)
01242 {
01243   const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
01244   struct_decls(name, size);
01245   return true;
01246 }
01247 
01248 bool langmap_generator::gen_struct(AST_Structure* s, UTL_ScopedName* name,
01249                                    const std::vector<AST_Field*>& fields,
01250                                    AST_Type::SIZE_TYPE size,
01251                                    const char* x)
01252 {
01253   return generator_->gen_struct(s, name, fields, size, x);
01254 }
01255 
01256 namespace {
01257 
01258   // Outside of user's namespace: add Traits for arrays so that they can be
01259   // used in Sequences and Array_var/_out/_forany.
01260   void gen_array_traits(UTL_ScopedName* tdname, AST_Array* arr)
01261   {
01262     const std::string nm = scoped(tdname);
01263     std::string zeros;
01264     for (ACE_CDR::ULong i = 1; i < arr->n_dims(); ++i) zeros += "[0]";
01265     be_global->lang_header_ <<
01266       "namespace TAO {\n"
01267       "template <>\n"
01268       "struct " << exporter() << "Array_Traits<" << nm << "_forany>\n"
01269       "{\n"
01270       "  static void free(" << nm << "_slice* slice)\n"
01271       "  {\n"
01272       "    " << nm << "_free(slice);\n"
01273       "  }\n\n"
01274       "  static " << nm << "_slice* dup(const " << nm << "_slice* slice)\n"
01275       "  {\n"
01276       "    return " << nm << "_dup(slice);\n"
01277       "  }\n\n"
01278       "  static void copy(" << nm << "_slice* dst, const " << nm
01279       << "_slice* src)\n"
01280       "  {\n"
01281       "    " << nm << "_copy(dst, src);\n"
01282       "  }\n\n"
01283       "  static " << nm << "_slice* alloc()\n"
01284       "  {\n"
01285       "    return " << nm << "_alloc();\n"
01286       "  }\n\n"
01287       "  static void zero(" << nm << "_slice* slice)\n"
01288       "  {\n"
01289       "    " << nm << "_fini_i(slice" << zeros << ");\n"
01290       "    " << nm << "_init_i(slice" << zeros << ");\n"
01291       "  }\n"
01292       "  static void construct(" << nm << "_slice* slice)\n"
01293       "  {\n"
01294       "    " << nm << "_init_i(slice" << zeros << ");\n"
01295       "  }\n"
01296       "  static void destroy(" << nm << "_slice* slice)\n"
01297       "  {\n"
01298       "    " << nm << "_fini_i(slice" << zeros << ");\n"
01299       "  }\n"
01300       "};\n}\n\n";
01301   }
01302 
01303 #ifdef ACE_HAS_CDR_FIXED
01304   void gen_fixed(UTL_ScopedName* name, AST_Fixed* fixed)
01305   {
01306     be_global->add_include("FACE/Fixed.h", BE_GlobalData::STREAM_LANG_H);
01307     const char* const nm = name->last_component()->get_string();
01308     be_global->lang_header_ <<
01309       "typedef " << helpers_[HLP_FIXED] << '<' << *fixed->digits()->ev()
01310       << ", " << *fixed->scale()->ev() << "> " << nm << ";\n"
01311       "typedef " << nm << "& " << nm << "_out;\n";
01312   }
01313 #endif
01314 }
01315 
01316 bool langmap_generator::gen_typedef(AST_Typedef*, UTL_ScopedName* name, AST_Type* base,
01317                                     const char*)
01318 {
01319   AST_Array* arr = 0;
01320   {
01321     const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
01322     const char* const nm = name->last_component()->get_string();
01323 
01324     const Classification cls = classify(base);
01325 
01326     switch (base->node_type()) {
01327     case AST_Decl::NT_sequence:
01328       generator_->gen_sequence(name, AST_Sequence::narrow_from_decl(base));
01329       break;
01330     case AST_Decl::NT_array:
01331       gen_array(name, arr = AST_Array::narrow_from_decl(base));
01332       break;
01333     case AST_Decl::NT_fixed:
01334 # ifdef ACE_HAS_CDR_FIXED
01335       gen_fixed(name, AST_Fixed::narrow_from_decl(base));
01336       break;
01337 # else
01338       std::cerr << "ERROR: fixed data type (for " << nm << ") is not supported"
01339         " with this version of ACE+TAO\n";
01340       return false;
01341 # endif
01342     default:
01343       be_global->lang_header_ <<
01344         "typedef " << map_type(base) << ' ' << nm << ";\n";
01345       if ((cls & CL_STRING) == 0) {
01346           be_global->lang_header_ <<
01347             "typedef " << map_type(base) << "_out " << nm << "_out;\n";
01348         }
01349 
01350       AST_Type* actual_base = resolveActualType(base);
01351       if (actual_base->node_type() == AST_Decl::NT_array) {
01352         be_global->lang_header_ <<
01353           "typedef " << map_type(base) << "_var " << nm << "_var;\n" <<
01354           "typedef " << map_type(base) << "_slice " << nm << "_slice;\n" <<
01355           "typedef " << map_type(base) << "_forany " << nm << "_forany;\n\n" <<
01356           "inline " << nm << "_slice *" << nm << "_alloc() { return " << map_type(base) << "_alloc(); }\n" <<
01357           "inline " << nm << "_slice* " << nm << "_dup(" << nm << "_slice *a) { return " << map_type(base) << "_dup(a); }\n" <<
01358           "inline void " << nm << "_copy(" << nm << "_slice* to, const " << nm << "_slice* from) { " << map_type(base) << "_copy(to, from); }\n" <<
01359           "inline void " << nm << "_free(" << nm << "_slice *a) { " << map_type(base) << "_free(a); }\n";
01360       }
01361 
01362       break;
01363     }
01364 
01365     if (cls & CL_STRING) {
01366       const Helper var = (cls & CL_WIDE) ? HLP_WSTR_VAR : HLP_STR_VAR,
01367         out = (cls & CL_WIDE) ? HLP_WSTR_OUT : HLP_STR_OUT;
01368       be_global->lang_header_ <<
01369         "typedef " << helpers_[var] << ' ' << nm << "_var;\n"
01370         "typedef " << helpers_[out] << ' ' << nm << "_out;\n";
01371     }
01372 
01373     gen_typecode(name);
01374   }
01375   if (arr) gen_array_traits(name, arr);
01376   return true;
01377 }
01378 
01379 bool langmap_generator::gen_union_fwd(AST_UnionFwd* node,
01380                                       UTL_ScopedName* name,
01381                                       AST_Type::SIZE_TYPE)
01382 {
01383   const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
01384   struct_decls(name, node->full_definition()->size_type());
01385   return true;
01386 }
01387 
01388 bool langmap_generator::gen_union(AST_Union* u, UTL_ScopedName* name,
01389                                   const std::vector<AST_UnionBranch*>& branches,
01390                                   AST_Type* discriminator,
01391                                   const char*)
01392 {
01393   return generator_->gen_union(u, name, branches, discriminator);
01394 }
01395 
01396 bool langmap_generator::gen_interf_fwd(UTL_ScopedName* name)
01397 {
01398   const ScopedNamespaceGuard namespaces(name, be_global->lang_header_);
01399 
01400   be_global->add_include("<tao/Objref_VarOut_T.h>", BE_GlobalData::STREAM_LANG_H);
01401   const char* const nm = name->last_component()->get_string();
01402   be_global->lang_header_ <<
01403     "class " << nm << ";\n"
01404     "typedef " << nm << '*' << nm << "_ptr;\n"
01405     "typedef TAO_Objref_Var_T<" << nm << "> " << nm << "_var;\n"
01406     "typedef TAO_Objref_Out_T<" << nm << "> " << nm << "_out;\n";
01407 
01408   return true;
01409 }

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