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