1 // idlcomp/languages/c++/main.cc -- C++ IDL binding
3 // A lot of the complexity in here would just go away if C++ could handle
4 // out-of-order declarations.
6 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
8 // This software is provided 'as-is', without any express or implied warranty.
9 // In no event will the authors or contributors be held liable for any damages
10 // arising from the use of this software.
12 // Permission is hereby granted to everyone, free of charge, to use, copy,
13 // modify, prepare derivative works of, publish, distribute, perform,
14 // sublicense, and/or sell copies of the Software, provided that the above
15 // copyright notice and disclaimer of warranty be included in all copies or
16 // substantial portions of this software.
18 // FIXME: escape C++ reserved words
22 #include <sys/types.h>
28 CPPBinding cppbinding;
30 CPPFile::CPPFile(UserNameSpace *NS, const char *dir) :
33 indent.indent_level = 0;
34 indent.align_spaces = 0;
35 do_extra_newline = true;
38 dirname.append(1, '/');
39 dirname.append(ns->name);
40 string headername(dirname);
41 headername.append(".h");
43 file.open(headername.c_str());
44 if (!file.is_open()) {
45 fprintf(stderr, "Could not create output file \"%s\": %s.\n",
46 headername.c_str(), strerror(errno));
51 if (mkdir(dirname.c_str(), 0777) < 0) {
52 fprintf(stderr, "Could not create output directory \"%s\": %s.\n",
53 dir, strerror(errno));
58 file << "// " << *ns->get_fq_name()->flatten()
59 << "\n// This is a C++ language binding generated by idlc.\n"
60 << "// Do not modify this file directly.\n\n";
62 fqname = ns->get_fq_name();
63 String *fqname_flat = ns->get_fq_name()->flatten("_IDLNS_");
64 file << "#ifndef IDL_HDR_" << *fqname_flat
65 << "\n#define IDL_HDR_" << *fqname_flat << "\n\n";
67 file << "#include <orb.h>\n";
69 first_traversal = ++traversal;
70 assert(first_traversal >= 0);
72 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
73 Symbol *sym = (*i).second;
74 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(sym);
77 file << "#include \"" << **ns->name << '/' << **uns->name << ".h\"\n";
79 // Process namespaces first, to minimize duplicate definitions
80 // if this namespace depends on something declared in a sub
87 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
88 Symbol *sym = (*i).second;
89 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(sym);
92 output_pass(sym, trav_nsdecl);
95 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
96 Symbol *sym = (*i).second;
97 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(sym);
100 output_pass(sym, trav_full);
108 assert(indent.indent_level == 0);
111 void CPPFile::ifndef_in(Symbol *sym, const char *extra)
113 StrList *fqname = sym->get_fq_name();
114 String *fqname_flat = fqname->flatten("_IDLNS_");
116 assert(indent.indent_level == 0);
118 file << "\n#ifndef IDL_DUP_" << extra << *fqname_flat
119 << "\n#define IDL_DUP_" << extra << *fqname_flat << "\n";
122 void CPPFile::ifndef_out()
124 file << "\n#endif\n";
127 void CPPFile::ns_in(Symbol *sym, const char *extra)
129 // Only output user namespaces here; if we're defining a nested type,
130 // it will have been forward declared already, and thus the
131 // non-user-namespaces can be specified directly in the definition.
133 // For non-forward-declarables such as metadata, use all_ns_in.
135 StrList *ns_fqname = sym->find_toplevel_type()->get_ns()->get_fq_name();
137 ifndef_in(sym, extra);
139 for (StrList::const_iterator i = ns_fqname->begin();
140 i != ns_fqname->end(); ++i) {
141 const String *str = *i;
142 file << "namespace " << *str << " {\n";
148 void CPPFile::ns_out(Symbol *sym)
151 assert(indent.indent_level == 0);
153 for (Symbol *s = sym->find_toplevel_type()->get_ns(); s != toplevel;
160 void CPPFile::all_ns_in(Symbol *sym, bool include_self, const char *extra)
162 NameSpace *ns = sym->find_toplevel_type()->get_ns();
163 StrList *ns_fqname = ns->get_fq_name();
165 ifndef_in(sym, extra);
167 for (StrList::const_iterator i = ns_fqname->begin();
168 i != ns_fqname->end(); ++i) {
169 const String *str = *i;
170 file << "namespace " << *str << " {\n";
173 stack<SymbolRef> typens;
178 for (Symbol *s = sym; s != ns; s = s->get_ns())
181 while (!typens.empty()) {
182 Symbol *s = typens.top();
184 file << "namespace " << **s->name << "_ns {\n";
190 void CPPFile::all_ns_out(Symbol *sym, bool include_self)
193 assert(indent.indent_level == 0);
198 for (Symbol *s = sym; s != toplevel; s = s->get_ns())
204 String &CPPFile::get_definition_name(Symbol *sym, const char *prefix)
206 NameSpace *ns = sym->get_ns();
207 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(ns);
211 str = &get_definition_name(ns);
212 str->append("_ns::");
218 str->append(**sym->name);
222 void cpp_output_name(ostream &file, Symbol *sym, const char *prefix)
224 StrList *sl = sym->get_fq_name("_ns");
227 file << "::" << *sl->flatten("::") << "::" << prefix << **sym->name;
230 void CPPFile::output(UserNameSpace *sym, int pass, void *arg2)
232 assert(indent.indent_level == 0);
233 delete new CPPFile(sym, dirname.c_str());
236 static inline int round_up_bits(int bits)
238 assert(bits >= 1 && bits <= 64);
250 // FIXME: Inline arrays...
251 void cpp_output_type(ostream &file, Type *t, bool array, bool is_mutable)
254 file << "::System::RunTime::";
262 cpp_output_name(file, t);
265 Struct *str = dynamic_cast<Struct *>(t);
269 file << ", ::System::RunTime::ORBMM>";
275 // FIXME: Inline arrays...
276 void cpp_output_type(ostream &file, CompiledBasicType &t, bool is_mutable)
279 file << "::System::RunTime::";
287 if (t.flags.field.Bool) {
288 // Don't rely on C++ to provide any particular representation
291 } else if (t.flags.field.Float) {
297 if (t.flags.field.Unsigned)
300 file << "int" << round_up_bits(t.bits) << "_t";
304 file << ", ::System::RunTime::ORBMM>";
309 // FIXME: implement padding
310 int CPPFile::output_datum(Struct *ns, Datum *d, int offset)
313 cpp_output_type(file, d->type, is_array(d->def.basictype),
314 !d->def.flags.field.Immutable);
316 Struct *dtype = dynamic_cast<Struct *>(*d->type);
317 if (dtype && !dtype->is_inline() && !d->is_array())
320 cpp_output_type(file, d->def.basictype,
321 !d->def.flags.field.Immutable);
327 void CPPFile::declare_type_dependency(Type *t, bool need_obj_def)
329 Symbol *toplevel_type = t->find_toplevel_type();
331 assert(indent.indent_level == 0);
333 output_pass(toplevel_type, trav_nsdecl);
335 if (t == toplevel_type)
336 output_pass(t, trav_forward);
338 if (dynamic_cast<Interface *>(t))
339 output_pass(t, need_obj_def ? trav_obj_def : trav_obj_stub);
340 else if (!dynamic_cast<Struct *>(t) || need_obj_def)
341 output_pass(t, trav_full);
344 void CPPFile::declare_dependencies(Interface *iface, bool need_obj_def)
346 for (Interface::methods_iterator i = iface->methods_begin();
347 i != iface->methods_end(); ++i)
350 for (Method::entries_iterator j = m->entries_begin();
351 j != m->entries_end(); ++j)
355 declare_type_dependency(p->type, need_obj_def);
359 for (Interface::supers_iterator i = iface->supers_begin();
360 i != iface->supers_end(); ++i)
362 Interface *super = *i;
363 declare_type_dependency(super);
367 void CPPFile::declare_dependencies(Struct *str)
369 for (NameSpace::const_iterator i = str->begin(); i != str->end(); ++i) {
370 Symbol *sym = (*i).second;
371 Datum *d = dynamic_cast<Datum *>(sym);
374 declare_type_dependency(d->type, d->is_inline());
379 Struct *mstr = dynamic_cast<Struct *>(sym);
381 declare_dependencies(mstr);
385 Interface *miface = dynamic_cast<Interface *>(sym);
387 declare_dependencies(miface);
391 void CPPFile::output_guid(const uint64_t *guid64)
393 const unsigned char *guid = reinterpret_cast<const unsigned char *>(guid64);
396 file << indent << "__attribute__((weak))\n"
397 << indent << "::System::RunTime::GUID _guid = {\n"
400 for (int i = 0; i < 16; i++) {
402 file << '\n' << indent << "\t ";
404 sprintf(guidhex, "0x%02x, ", *guid++);
411 do_extra_newline = true;
414 void CPPFile::output_nsdecl_begin(NameSpace *ns)
416 // If indent level is not zero, this is a nested struct or interface.
417 if (indent.indent_level == 0)
422 file << indent << "namespace " << **ns->name << "_ns {\n";
426 void CPPFile::output_nsdecl_children(NameSpace *ns)
428 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
429 Symbol *sym = (*i).second;
431 assert(pass_needed(sym, trav_forward));
432 assert(pass_needed(sym, trav_nsdecl));
434 // If it's a Method or a non-const Datum, this is a no-op.
435 output_pass(sym, trav_forward);
436 output_pass(sym, trav_nsdecl);
440 void CPPFile::output_nsdecl_end(NameSpace *ns)
444 file << indent << "}\n";
446 if (indent.indent_level == 1)
450 void CPPFile::output_nsdecl(NameSpace *ns)
452 output_nsdecl_begin(ns);
453 output_nsdecl_children(ns);
454 output_nsdecl_end(ns);
457 void CPPFile::output_aliases_and_types(NameSpace *ns)
459 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
460 Symbol *sym = (*i).second;
461 if (dynamic_cast<Alias *>(sym) || dynamic_cast<Type *>(sym))
462 output_pass(sym, trav_full);
466 void CPPFile::output_vstruct_info(Struct *sym)
468 all_ns_in(sym, true, "VINFO_");
470 file << indent << "__attribute__((weak)) "
471 "unsigned long * _guids[] = {\n";
473 stack<StructRef> supers;
476 for (Struct *i = sym; i; i = i->get_super()) {
481 for (int i = 0; i < sym->chainlen; i++) {
482 Struct *super = supers.top();
485 file << indent << '\t';
486 cpp_output_name(file, super);
487 file << "_ns::_guid.l,\n";
490 file << indent << "};\n\n"
491 << indent << "__attribute__((weak)) "
492 "::System::RunTime::VStructInfo _info = {\n"
493 << indent << "\t_guids, " << sym->chainlen << ",\n"
494 // << indent << "\t_marshall, _unmarshall,\n"
498 all_ns_out(sym, true);
501 void CPPFile::output_vstruct_main(Struct *sym)
503 assert(sym->is_virtual());
504 Struct *super = sym->get_super();
506 const char *name = sym->name->c_str();
509 assert(sym == System_VStruct);
510 file << indent << "const ::System::RunTime::VStructInfo "
511 "*const _infoptr;\n\n";
514 file << indent << name
515 << "(const ::System::RunTime::VStructInfo *realinfo = &"
516 << name << "_ns::_info) :\n"
522 cpp_output_name(file, super);
524 file << "(realinfo)\n"
530 << indent << "static __attribute__((weak)) " << name << " *downcast(::System::VStruct *base)\n"
532 << indent << "\tif (!base)\n"
533 << indent << "\t\treturn NULL;\n\n"
534 << indent << "\tconst ::System::RunTime::VStructInfo *info = base->_infoptr;\n\n"
535 << indent << "\tif (info->chainlen < " << sym->chainlen << ")\n"
536 << indent << "\t\treturn NULL;\n\n"
537 << indent << "\tif (::System::RunTime::guids_equal(info->guids["
538 << sym->chainlen - 1 << "], " << name << "_ns::_guid.l))\n"
539 << indent << "\t\treturn static_cast<" << name << " *>(base);\n\n"
540 << indent << "\treturn NULL;\n"
543 do_extra_newline = true;
546 // Output an init method that initializes all the elements in the
547 // struct; this is useful for throwing exceptions. Due to the
548 // annoying, apparently unwaiveable-by-the-struct requirement that any
549 // struct with a ctor be initialized using the ctor (and thus at
550 // runtime, not statically), this can't be an actual ctor in
551 // non-virtual structs.
553 // In virtual structs, there's already a ctor, so it wouldn't
554 // matter. It'd generally be best to be consistent and use the
555 // init method for both, but the main intended use for this is
556 // throwing exceptions (which are virtual), and it'd be
557 // unfortunate to cripple 99% of the uses with unnecessary
558 // syntactic cruft. The init method will remain available
559 // for vstructs so that things won't break if a non-vstruct
560 // gets made virtual (or if a user really wants to be consistent
561 // between both types in their own code).
563 void CPPFile::output_struct_ctor(Struct *sym, bool extra_vstruct)
565 const char *method_name = extra_vstruct ? sym->name->c_str() : " _init";
567 file << '\n' << indent << **sym->name;
568 indent.align_spaces = sym->name->length() + 1;
570 if (!extra_vstruct) {
572 indent.align_spaces += 7;
576 output_struct_ctor_rec1(sym, 0);
579 Struct *super = sym->get_super();
581 file << ",\n" << indent
582 << "const ::System::RunTime::VStructInfo *_realinfo = &"
583 << **sym->name << "_ns::_info) :\n";
585 indent.align_spaces = 0;
591 cpp_output_name(file, super);
593 file << "(_realinfo";
596 indent.align_spaces = 0;
597 file << ")\n" << indent << "{\n";
599 indent.indent_level++;
601 output_struct_ctor_rec2(sym, 0);
604 file << indent << "return *this;\n";
606 indent.indent_level--;
607 file << indent << "}\n";
610 int CPPFile::output_struct_ctor_rec1(Struct *sym, int num)
612 if (sym->get_super())
613 num = output_struct_ctor_rec1(sym->get_super(), num);
615 for (Struct::entries_iterator i = sym->entries_begin();
616 i != sym->entries_end(); ++i)
619 file << ",\n" << indent;
621 output_datum(sym, *i, -1);
622 file << "_arg" << num;
628 int CPPFile::output_struct_ctor_rec2(Struct *sym, int num)
630 if (sym->get_super())
631 num = output_struct_ctor_rec2(sym->get_super(), num);
633 for (Struct::entries_iterator i = sym->entries_begin();
634 i != sym->entries_end(); ++i)
637 file << indent << **d->name << " = _arg" << ++num << ";\n";
643 void CPPFile::output(Struct *sym, int pass, void *arg2)
647 // If indent level is not zero, this is a nested struct or interface.
648 if (indent.indent_level == 0)
649 output_pass(sym, trav_forward);
651 if (sym->is_virtual()) {
652 output_nsdecl_begin(sym);
653 output_nsdecl_children(sym);
654 output_guid(sym->def.guid);
655 output_marshall_pass(sym, trav_nsdecl);
656 output_nsdecl_end(sym);
658 output_nsdecl_begin(sym);
659 output_nsdecl_children(sym);
660 output_marshall_pass(sym, trav_nsdecl);
661 output_nsdecl_end(sym);
667 bool nested = indent.indent_level != 0;
674 file << indent << "struct " << **sym->name << ";\n";
683 output_pass(sym, trav_nsdecl);
684 Struct *super = sym->get_super();
687 output_pass(super, trav_full);
689 if (sym->is_virtual())
690 output_vstruct_info(sym);
692 declare_dependencies(sym);
695 file << indent << "struct " << get_definition_name(sym);
698 const String *supername = super->get_fq_name("_ns")
700 file << " :\n" << indent << "public ::" << *supername;
703 file << "\n" << indent << "{\n";
706 if (sym->is_virtual())
707 output_vstruct_main(sym);
710 for (Struct::entries_iterator i = sym->entries_begin();
711 i != sym->entries_end(); ++i)
716 offset = output_datum(sym, d, offset);
717 file << **d->name << ";\n";
720 bool empty_struct = true;
721 for (Struct *s = sym; s; s = s->get_super()) {
722 if (s->entries_begin() != s->entries_end()) {
723 empty_struct = false;
729 output_struct_ctor(sym, false);
731 if (sym->is_virtual())
732 output_struct_ctor(sym, true);
736 file << indent << "};\n";
740 all_ns_in(sym, true, "MARSHALL_");
741 output_marshall_pass(sym, trav_full);
742 all_ns_out(sym, true);
744 output_aliases_and_types(sym);
746 for (NameSpace::const_iterator i = sym->begin(); i != sym->end(); ++i) {
747 Symbol *sym2 = (*i).second;
748 output_pass(sym2, trav_full);
755 output_marshall(sym, static_cast<Datum *>(arg2));
763 void CPPFile::output(Interface *sym, int pass, void *arg2)
767 output_nsdecl_begin(sym);
768 output_nsdecl_children(sym);
770 output_guid(sym->def.guid);
771 output_ifaceinfo(sym);
773 output_nsdecl_end(sym);
777 bool nested = indent.indent_level != 0;
784 file << indent << "struct " << **sym->name << ";\n"
785 << indent << "struct _i_" << **sym->name << ";\n";
793 case trav_obj_stub: {
794 output_pass(sym, trav_forward);
796 for (Interface::supers_iterator i = sym->supers_begin();
797 i != sym->supers_end(); ++i)
799 Interface *super = *i;
800 output_pass(super, trav_obj_stub);
803 declare_dependencies(sym);
806 file << indent << "struct "
807 << get_definition_name(sym) << " {\n";
814 file << indent << "};\n";
821 output_pass(sym, trav_obj_stub);
823 for (Interface::supers_iterator i = sym->supers_begin();
824 i != sym->supers_end(); ++i)
826 Interface *super = *i;
827 output_pass(super, trav_full);
830 declare_dependencies(sym);
831 ns_in(sym, "OBJDEF_");
833 file << indent << "struct ";
834 file << get_definition_name(sym, "_i_") << " {\n";
838 output_internal(sym);
841 file << indent << "};\n\n";
849 output_pass(sym, trav_obj_def);
851 declare_dependencies(sym, true);
854 output_method_defs(sym);
857 output_aliases_and_types(sym);
859 for (NameSpace::const_iterator i = sym->begin(); i != sym->end(); ++i) {
860 Symbol *sym2 = (*i).second;
861 output_pass(sym2, trav_full);
867 output_marshall(sym, static_cast<Datum *>(arg2));
876 void CPPFile::output_bf_elem(Datum *d, int pos, int bits,
880 BitField *bf = dynamic_cast<BitField *>(t);
881 Enum *en = dynamic_cast<Enum *>(t);
885 if (!d->name->compare(0, 4, "get_") ||
886 !d->name->compare(0, 4, "set_"))
889 fieldname.append(**d->name);
892 string newprefix(prefix);
893 newprefix.append(**d->name);
894 newprefix.append("_IDLNS_");
895 output_bf(bf, d->def.icon, bits, newprefix);
897 // FIXME: getters and setters
898 } else if (en || !t) {
899 file << indent << "uint" << bits << "_t "
900 << prefix << fieldname << ':' << d->def.icon << ";\n";
902 // This is checked here rather than in input.cc, because
905 fprintf(stderr, "idlc: Bad input: \"%s\" cannot be the type of \"%s\"\n",
906 t->get_fq_name()->flatten()->c_str(),
907 d->get_fq_name()->flatten()->c_str());
913 void CPPFile::output_bf(BitField *sym, int bits, int typebits,
918 assert(bits == sym->def.bits || bits == typebits);
920 for (BitField::entries_iterator i = sym->entries_begin();
921 i != sym->entries_end(); ++i)
922 size += (*i)->def.icon;
924 if (size > sym->def.bits) {
925 // FIXME: This isn't detected in the front end,
926 // but even once it is, this should stay as a
927 // replacement for input.cc checking.
929 fprintf(stderr, "idlc: \"%s\" is too small (%d bits) for its "
930 "contents (%d bits)\n",
931 sym->get_fq_name()->flatten()->c_str(),
932 sym->def.bits, size);
937 if (target->bitfield_big_endian) {
939 // The prefix is put at the end, so that we can avoid
940 // consecutive underscores or an underscore followed
941 // by a capital, both of which are reserved in C++.
943 file << indent << "uint" << bits << "_t _pad_" << prefix
944 << ':' << bits - size << ";\n";
947 int pos = sym->def.bits;
949 for (BitField::entries_reverse_iterator i = sym->entries_rbegin();
950 i != sym->entries_rend(); ++i)
954 output_bf_elem(d, pos, typebits, prefix);
959 for (BitField::entries_iterator i = sym->entries_begin();
960 i != sym->entries_end(); ++i)
963 output_bf_elem(d, pos, typebits, prefix);
969 void CPPFile::output(BitField *sym, int pass, void *arg2)
978 file << indent << "union " << **sym->name << ";\n";
982 int bits = round_up_bits(sym->def.bits);
985 file << indent << "union ";
986 file << get_definition_name(sym) << " {\n";
989 file << indent << "struct {\n";
993 output_bf(sym, bits, bits, nullprefix);
996 file << indent << "};\n\n"
997 << indent << "uint" << bits << "_t _raw;\n\n"
998 << indent << **sym->name << "()\n"
1000 << indent << "\t_raw = 0;\n"
1001 << indent << "}\n\n"
1002 << indent << **sym->name << "(uint" << bits << "_t _init)\n"
1004 << indent << "\t_raw = _init;\n"
1005 << indent << "}\n\n"
1006 << indent << "operator uint" << bits << "_t()\n"
1008 << indent << "\treturn _raw;\n"
1012 file << indent << "};\n";
1015 output_aliases_and_types(sym);
1020 output_marshall(sym, static_cast<Datum *>(arg2));
1028 void CPPFile::output(Enum *sym, int pass, void *arg2)
1035 case trav_forward: {
1036 bool do_ns_out = false;
1038 if (indent.indent_level == 0) {
1045 file << indent << "struct " << **sym->name << " {\n";
1048 for (Enum::entries_iterator i = sym->entries_begin();
1049 i != sym->entries_end(); ++i)
1053 file << indent << "static const uint"
1054 << round_up_bits(sym->def.bits) << "_t "
1055 << **d->name << " = " << d->def.ucon << ";\n";
1058 file << '\n' << indent << "unsigned int _val;\n\n";
1060 file << indent << **sym->name << "()\n"
1062 << indent << "\t_val = 0;\n"
1063 << indent << "}\n\n";
1065 file << indent << **sym->name << "(unsigned int val)\n"
1067 << indent << "\t_val = val;\n"
1068 << indent << "}\n\n";
1070 file << indent << "operator unsigned int()\n"
1072 << indent << "\treturn _val;\n"
1073 << indent << "}\n\n";
1076 file << indent << "};\n";
1085 // Nothing particular to do here, other than to make sure
1086 // that trav_forward has happened (which will always need to
1087 // be done here if it's not a nested type).
1089 output_pass(sym, trav_forward);
1093 output_marshall(sym, static_cast<Datum *>(arg2));
1101 void CPPFile::output(BasicType *sym, int pass, void *arg2)
1108 case trav_forward: {
1109 bool do_ns_out = false;
1111 if (indent.indent_level == 0) {
1118 file << indent << "typedef ";
1119 assert(!is_array(sym->def));
1120 cpp_output_type(file, sym->def, false);
1121 file << **sym->name << ";\n";
1130 output_pass(sym, trav_forward);
1134 output_marshall(sym, static_cast<Datum *>(arg2));
1142 void CPPFile::output(Alias *sym, int pass, void *arg2)
1149 case trav_forward: {
1150 bool do_ns_out = false;
1152 if (indent.indent_level == 0) {
1159 const String *type = sym->get_concrete_sym()->get_fq_name("_ns")
1162 file << indent << "typedef " << *type << " "
1163 << **sym->name << ";\n";
1172 output_pass(sym, trav_forward);
1180 void CPPFile::output(TypeDef *sym, int pass, void *arg2)
1189 output_pass(sym->get_concrete_sym(), trav_forward);
1191 bool do_ns_out = false;
1193 if (indent.indent_level == 0) {
1200 const String *type = sym->get_concrete_sym()->get_fq_name("_ns")
1203 file << indent << "typedef " << *type << " "
1204 << **sym->name << ";\n";
1217 void CPPFile::output(Datum *sym, int pass, void *arg2)
1219 assert(sym->def.flags.field.Const);
1229 declare_type_dependency(sym->type, false);
1231 bool do_ns_out = false;
1233 if (indent.indent_level == 0) {
1240 file << indent << "static const ";
1242 assert(!is_array(sym->def.basictype));
1245 cpp_output_type(file, sym->type, false, false);
1247 cpp_output_type(file, sym->def.basictype, false);
1249 file << **sym->name << " = ";
1251 CompiledBasicType *def;
1253 Symbol *real_type = sym->type->get_concrete_sym();
1254 BasicType *bt = dynamic_cast<BasicType *>(real_type);
1259 def = &sym->def.basictype;
1262 if (def->flags.field.Float) {
1263 file << sym->def.fcon;
1264 } else if (def->flags.field.Bool) {
1265 if (sym->def.ucon == 0)
1270 if (def->flags.field.Unsigned) {
1271 file << "0x" << std::hex << sym->def.ucon << std::dec << 'U';
1273 file << sym->def.icon;
1292 void CPPBinding::output_root(UserNameSpace *ns, const char *dir)
1294 delete new CPPFile(ns, dir);