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