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

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1