1 // idlcomp/languages/c++/main.cc -- C++ IDL binding
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal with
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 // of the Software, and to permit persons to whom the Software is furnished to do
10 // so, subject to the following conditions:
12 // * Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimers.
15 // * Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimers in the
17 // documentation and/or other materials provided with the distribution.
19 // * The names of the Software's authors and/or contributors
20 // may not be used to endorse or promote products derived from
21 // this Software without specific prior written permission.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
31 // FIXME: escape C++ reserved words
35 #include <sys/types.h>
41 CPPBinding cppbinding;
43 CPPFile::CPPFile(UserNameSpace *NS, const char *dir) :
46 indent.indent_level = 0;
47 indent.align_spaces = 0;
48 do_extra_newline = true;
51 dirname.append(1, '/');
52 dirname.append(ns->name);
53 string headername(dirname);
54 headername.append(".h");
56 file.open(headername.c_str());
57 if (!file.is_open()) {
58 fprintf(stderr, "Could not create output file \"%s\": %s.\n",
59 headername.c_str(), strerror(errno));
64 if (mkdir(dirname.c_str(), 0777) < 0) {
65 fprintf(stderr, "Could not create output directory \"%s\": %s.\n",
66 dir, strerror(errno));
71 file << "// " << *ns->get_fq_name()->flatten(".")
72 << "\n// This is a C++ language binding generated by idlc.\n"
73 << "// Do not modify this file directly.\n\n";
75 fqname = ns->get_fq_name();
76 String *fqname_flat = ns->get_fq_name()->flatten("_IDLNS_");
77 file << "#ifndef IDL_HDR_" << *fqname_flat
78 << "\n#define IDL_HDR_" << *fqname_flat << "\n\n";
80 file << "#include <orb.h>\n";
82 first_traversal = ++traversal;
83 assert(first_traversal >= 0);
85 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
86 Symbol *sym = (*i).second;
87 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(sym);
90 file << "#include \"" << **ns->name << '/' << **uns->name << ".h\"\n";
92 // Process namespaces first, to minimize duplicate definitions
93 // if this namespace depends on something declared in a sub
100 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
101 Symbol *sym = (*i).second;
102 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(sym);
105 output_pass(sym, trav_nsdecl);
108 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
109 Symbol *sym = (*i).second;
110 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(sym);
113 output_pass(sym, trav_full);
121 assert(indent.indent_level == 0);
124 void CPPFile::ifndef_in(Symbol *sym, const char *extra)
126 StrList *fqname = sym->get_fq_name();
127 String *fqname_flat = fqname->flatten("_IDLNS_");
129 assert(indent.indent_level == 0);
131 file << "\n#ifndef IDL_DUP_" << extra << *fqname_flat
132 << "\n#define IDL_DUP_" << extra << *fqname_flat << "\n";
135 void CPPFile::ifndef_out()
137 file << "\n#endif\n";
140 void CPPFile::ns_in(Symbol *sym, const char *extra)
142 // Only output user namespaces here; if we're defining a nested type,
143 // it will have been forward declared already, and thus the
144 // non-user-namespaces can be specified directly in the definition.
146 // For non-forward-declarables such as metadata, use all_ns_in.
148 StrList *ns_fqname = sym->find_toplevel_type()->get_ns()->get_fq_name();
150 ifndef_in(sym, extra);
152 for (StrList::const_iterator i = ns_fqname->begin();
153 i != ns_fqname->end(); ++i) {
154 const String *str = *i;
155 file << "namespace " << *str << " {\n";
161 void CPPFile::ns_out(Symbol *sym)
164 assert(indent.indent_level == 0);
166 for (Symbol *s = sym->find_toplevel_type()->get_ns(); s != toplevel;
173 void CPPFile::all_ns_in(Symbol *sym, bool include_self, const char *extra)
175 NameSpace *ns = sym->find_toplevel_type()->get_ns();
176 StrList *ns_fqname = ns->get_fq_name();
178 ifndef_in(sym, extra);
180 for (StrList::const_iterator i = ns_fqname->begin();
181 i != ns_fqname->end(); ++i) {
182 const String *str = *i;
183 file << "namespace " << *str << " {\n";
186 stack<SymbolRef> typens;
191 for (Symbol *s = sym; s != ns; s = s->get_ns())
194 while (!typens.empty()) {
195 Symbol *s = typens.top();
197 file << "namespace " << **s->name << "_ns {\n";
203 void CPPFile::all_ns_out(Symbol *sym, bool include_self)
206 assert(indent.indent_level == 0);
211 for (Symbol *s = sym; s != toplevel; s = s->get_ns())
217 String &CPPFile::get_definition_name(Symbol *sym, const char *prefix)
219 NameSpace *ns = sym->get_ns();
220 UserNameSpace *uns = dynamic_cast<UserNameSpace *>(ns);
224 str = &get_definition_name(ns);
225 str->append("_ns::");
231 str->append(**sym->name);
235 void cpp_output_name(ostream &file, Symbol *sym, const char *prefix)
237 StrList *sl = sym->get_fq_name("_ns");
240 file << "::" << *sl->flatten("::") << "::" << prefix << **sym->name;
243 void CPPFile::output(UserNameSpace *sym, int pass, void *arg2)
245 assert(indent.indent_level == 0);
246 delete new CPPFile(sym, dirname.c_str());
249 static inline int round_up_bits(int bits)
251 assert(bits >= 1 && bits <= 64);
263 // FIXME: Inline arrays...
264 void cpp_output_type(ostream &file, Type *t, bool array, bool is_mutable)
267 file << "::System::RunTime::";
275 cpp_output_name(file, t);
283 // FIXME: Inline arrays...
284 void cpp_output_type(ostream &file, CompiledBasicType &t, bool is_mutable)
287 file << "::System::RunTime::";
295 if (t.flags.field.Bool) {
296 // Don't rely on C++ to provide any particular representation
299 } else if (t.flags.field.Float) {
305 if (t.flags.field.Unsigned)
308 file << "int" << round_up_bits(t.bits) << "_t";
317 // FIXME: implement padding
318 int CPPFile::output_datum(Struct *ns, Datum *d, int offset)
321 cpp_output_type(file, d->type, is_array(d->def.basictype),
322 !d->def.flags.field.Immutable);
324 Struct *dtype = dynamic_cast<Struct *>(*d->type);
325 if (dtype && !dtype->is_inline())
328 cpp_output_type(file, d->def.basictype,
329 !d->def.flags.field.Immutable);
335 void CPPFile::declare_type_dependency(Type *t, bool need_obj_def)
337 Symbol *toplevel_type = t->find_toplevel_type();
339 assert(indent.indent_level == 0);
341 output_pass(toplevel_type, trav_nsdecl);
343 if (t == toplevel_type)
344 output_pass(t, trav_forward);
346 if (dynamic_cast<Interface *>(t))
347 output_pass(t, need_obj_def ? trav_obj_def : trav_obj_stub);
348 else if (!dynamic_cast<Struct *>(t) || need_obj_def)
349 output_pass(t, trav_full);
352 void CPPFile::declare_dependencies(Interface *iface, bool need_obj_def)
354 for (Interface::methods_iterator i = iface->methods_begin();
355 i != iface->methods_end(); ++i)
358 for (Method::entries_iterator j = m->entries_begin();
359 j != m->entries_end(); ++j)
363 declare_type_dependency(p->type, need_obj_def);
367 for (Interface::supers_iterator i = iface->supers_begin();
368 i != iface->supers_end(); ++i)
370 Interface *super = *i;
371 declare_type_dependency(super);
375 void CPPFile::declare_dependencies(Struct *str)
377 for (NameSpace::const_iterator i = str->begin(); i != str->end(); ++i) {
378 Symbol *sym = (*i).second;
379 Datum *d = dynamic_cast<Datum *>(sym);
382 declare_type_dependency(d->type, d->is_inline());
387 Struct *mstr = dynamic_cast<Struct *>(sym);
389 declare_dependencies(mstr);
393 Interface *miface = dynamic_cast<Interface *>(sym);
395 declare_dependencies(miface);
399 void CPPFile::output_guid(const uint64_t *guid64)
401 const unsigned char *guid = reinterpret_cast<const unsigned char *>(guid64);
404 file << indent << "static const __attribute__((unused)) union {\n"
405 << indent << "\tunsigned char c[16];\n"
406 << indent << "\tunsigned long l[];\n"
407 << indent << "} _guid = {\n"
410 for (int i = 0; i < 16; i++) {
412 file << '\n' << indent << "\t ";
414 sprintf(guidhex, "0x%02x, ", *guid++);
421 do_extra_newline = true;
424 void CPPFile::output_nsdecl(NameSpace *ns, nsdecl_callback cb)
426 // If indent level is not zero, this is a nested struct or interface.
427 if (indent.indent_level == 0)
432 file << indent << "namespace " << **ns->name << "_ns {\n";
438 for (NameSpace::const_iterator i = ns->begin(); i != ns->end(); ++i) {
439 Symbol *sym = (*i).second;
441 assert(pass_needed(sym, trav_forward));
442 assert(pass_needed(sym, trav_nsdecl));
444 // If it's a Method or a non-const Datum, this is a no-op.
445 output_pass(sym, trav_forward);
446 output_pass(sym, trav_nsdecl);
451 file << indent << "}\n";
453 if (indent.indent_level == 1)
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_ns(CPPFile *cpp, NameSpace *sym)
468 Struct *str = dynamic_cast<Struct *>(sym);
470 assert(str->is_virtual());
472 cpp->output_guid(str->def.guid);
475 void CPPFile::output_vstruct_info(Struct *sym)
477 all_ns_in(sym, true, "VINFO_");
479 file << indent << "static const __attribute__((unused)) "
480 "unsigned long *const _guids[] = {\n";
482 stack<StructRef> supers;
485 for (Struct *i = sym; i; i = i->get_super()) {
490 for (int i = 0; i < sym->chainlen; i++) {
491 Struct *super = supers.top();
494 file << indent << '\t';
495 cpp_output_name(file, super);
496 file << "_ns::_guid.l,\n";
499 file << indent << "};\n\n"
500 << indent << "static const __attribute__((unused)) "
501 "::System::RunTime::VStructInfo _info = {\n"
502 << indent << "\t_guids, " << sym->chainlen << '\n'
506 all_ns_out(sym, true);
509 void CPPFile::output_vstruct_main(Struct *sym)
511 assert(sym->is_virtual());
512 Struct *super = sym->get_super();
514 const char *name = sym->name->c_str();
517 assert(sym == System_VStruct);
518 file << indent << "const ::System::RunTime::VStructInfo "
519 "*const _infoptr;\n\n";
522 file << indent << name
523 << "(const ::System::RunTime::VStructInfo *realinfo = &"
524 << name << "_ns::_info) :\n"
530 cpp_output_name(file, super);
532 file << "(realinfo)\n"
538 << indent << "static " << name << " *downcast(::System::VStruct *base)\n"
540 << indent << "\tif (!base)\n"
541 << indent << "\t\treturn NULL;\n\n"
542 << indent << "\tconst ::System::RunTime::VStructInfo *info = base->_infoptr;\n\n"
543 << indent << "\tif (info->chainlen < " << sym->chainlen << ")\n"
544 << indent << "\t\treturn NULL;\n\n"
545 << indent << "\tif (::System::RunTime::guids_equal(info->guids["
546 << sym->chainlen - 1 << "], " << name << "_ns::_guid.l))\n"
547 << indent << "\t\treturn static_cast<" << name << " *>(base);\n\n"
548 << indent << "\treturn NULL;\n"
551 do_extra_newline = true;
554 // Output an init method that initializes all the elements in the
555 // struct; this is useful for throwing exceptions. Due to the
556 // annoying, apparently unwaiveable-by-the-struct requirement that any
557 // struct with a ctor be initialized using the ctor (and thus at
558 // runtime, not statically), this can't be an actual ctor in
559 // non-virtual structs.
561 // In virtual structs, there's already a ctor, so it wouldn't
562 // matter. It'd generally be best to be consistent and use the
563 // init method for both, but the main intended use for this is
564 // throwing exceptions (which are virtual), and it'd be
565 // unfortunate to cripple 99% of the uses with unnecessary
566 // syntactic cruft. The init method will remain available
567 // for vstructs so that things won't break if a non-vstruct
568 // gets made virtual (or if a user really wants to be consistent
569 // between both types in their own code).
571 void CPPFile::output_struct_ctor(Struct *sym, bool extra_vstruct)
573 const char *method_name = extra_vstruct ? sym->name->c_str() : " _init";
575 file << '\n' << indent << **sym->name;
576 indent.align_spaces = sym->name->length() + 1;
578 if (!extra_vstruct) {
580 indent.align_spaces += 7;
584 output_struct_ctor_rec1(sym, 0);
587 Struct *super = sym->get_super();
589 file << ",\n" << indent
590 << "const ::System::RunTime::VStructInfo *_realinfo = &"
591 << **sym->name << "_ns::_info) :\n";
593 indent.align_spaces = 0;
599 cpp_output_name(file, super);
601 file << "(_realinfo";
604 indent.align_spaces = 0;
605 file << ")\n" << indent << "{\n";
607 indent.indent_level++;
609 output_struct_ctor_rec2(sym, 0);
612 file << indent << "return *this;\n";
614 indent.indent_level--;
615 file << indent << "}\n";
618 int CPPFile::output_struct_ctor_rec1(Struct *sym, int num)
620 if (sym->get_super())
621 num = output_struct_ctor_rec1(sym->get_super(), num);
623 for (Struct::entries_iterator i = sym->entries_begin();
624 i != sym->entries_end(); ++i)
627 file << ",\n" << indent;
629 output_datum(sym, *i, -1);
630 file << "_arg" << num;
636 int CPPFile::output_struct_ctor_rec2(Struct *sym, int num)
638 if (sym->get_super())
639 num = output_struct_ctor_rec2(sym->get_super(), num);
641 for (Struct::entries_iterator i = sym->entries_begin();
642 i != sym->entries_end(); ++i)
645 file << indent << **d->name << " = _arg" << ++num << ";\n";
651 void CPPFile::output(Struct *sym, int pass, void *arg2)
655 if (sym->is_virtual()) {
656 output_nsdecl(sym, output_vstruct_ns);
664 bool nested = indent.indent_level != 0;
671 file << indent << "struct " << **sym->name << ";\n";
680 output_pass(sym, trav_nsdecl);
681 Struct *super = sym->get_super();
684 output_pass(super, trav_full);
686 if (sym->is_virtual())
687 output_vstruct_info(sym);
689 declare_dependencies(sym);
692 file << indent << "struct " << get_definition_name(sym);
695 const String *supername = super->get_fq_name("_ns")
697 file << " :\n" << indent << "public ::" << *supername;
700 file << "\n" << indent << "{\n";
703 if (sym->is_virtual())
704 output_vstruct_main(sym);
707 for (Struct::entries_iterator i = sym->entries_begin();
708 i != sym->entries_end(); ++i)
713 offset = output_datum(sym, d, offset);
714 file << **d->name << ";\n";
717 bool empty_struct = true;
718 for (Struct *s = sym; s; s = s->get_super()) {
719 if (s->entries_begin() != s->entries_end()) {
720 empty_struct = false;
726 output_struct_ctor(sym, false);
728 if (sym->is_virtual())
729 output_struct_ctor(sym, true);
733 file << indent << "};\n";
737 output_aliases_and_types(sym);
739 for (NameSpace::const_iterator i = sym->begin(); i != sym->end(); ++i) {
740 Symbol *sym2 = (*i).second;
741 output_pass(sym2, trav_full);
752 void CPPFile::output_iface_ns(CPPFile *file, NameSpace *sym)
754 Interface *i = dynamic_cast<Interface *>(sym);
757 file->output_guid(i->def.guid);
760 void CPPFile::output(Interface *sym, int pass, void *arg2)
764 output_nsdecl(sym, output_iface_ns);
768 bool nested = indent.indent_level != 0;
775 file << indent << "struct " << **sym->name << ";\n"
776 << indent << "struct _i_" << **sym->name << ";\n";
784 case trav_obj_stub: {
785 output_pass(sym, trav_forward);
787 for (Interface::supers_iterator i = sym->supers_begin();
788 i != sym->supers_end(); ++i)
790 Interface *super = *i;
791 output_pass(super, trav_obj_stub);
794 declare_dependencies(sym);
797 file << indent << "struct "
798 << get_definition_name(sym) << " {\n";
805 file << indent << "};\n";
812 output_pass(sym, trav_obj_stub);
814 for (Interface::supers_iterator i = sym->supers_begin();
815 i != sym->supers_end(); ++i)
817 Interface *super = *i;
818 output_pass(super, trav_full);
821 declare_dependencies(sym);
822 ns_in(sym, "OBJDEF_");
824 file << indent << "struct ";
825 file << get_definition_name(sym, "_i_") << " {\n";
829 output_internal(sym);
832 file << indent << "};\n\n";
840 output_pass(sym, trav_obj_def);
842 declare_dependencies(sym, true);
845 output_method_defs(sym);
848 output_aliases_and_types(sym);
850 for (NameSpace::const_iterator i = sym->begin(); i != sym->end(); ++i) {
851 Symbol *sym2 = (*i).second;
852 output_pass(sym2, trav_full);
863 void CPPFile::output_bf_elem(Datum *d, int pos, int bits,
867 BitField *bf = dynamic_cast<BitField *>(t);
868 Enum *en = dynamic_cast<Enum *>(t);
872 if (!d->name->compare(0, 4, "get_") ||
873 !d->name->compare(0, 4, "set_"))
876 fieldname.append(**d->name);
879 string newprefix(prefix);
880 newprefix.append(**d->name);
881 newprefix.append("_IDLNS_");
882 output_bf(bf, d->def.icon, bits, newprefix);
884 // FIXME: getters and setters
885 } else if (en || !t) {
886 file << indent << "uint" << bits << "_t "
887 << prefix << fieldname << ':' << d->def.icon << ";\n";
889 // This is checked here rather than in input.cc, because
892 fprintf(stderr, "idlc: Bad input: \"%s\" cannot be the type of \"%s\"\n",
893 t->get_fq_name()->flatten()->c_str(),
894 d->get_fq_name()->flatten()->c_str());
900 void CPPFile::output_bf(BitField *sym, int bits, int typebits,
905 assert(bits == sym->def.bits || bits == typebits);
907 for (BitField::entries_iterator i = sym->entries_begin();
908 i != sym->entries_end(); ++i)
909 size += (*i)->def.icon;
911 if (size > sym->def.bits) {
912 // FIXME: This isn't detected in the front end,
913 // but even once it is, this should stay as a
914 // replacement for input.cc checking.
916 fprintf(stderr, "idlc: \"%s\" is too small (%d bits) for its "
917 "contents (%d bits)\n",
918 sym->get_fq_name()->flatten()->c_str(),
919 sym->def.bits, size);
924 if (target->bitfield_big_endian) {
926 // The prefix is put at the end, so that we can avoid
927 // consecutive underscores or an underscore followed
928 // by a capital, both of which are reserved in C++.
930 file << indent << "uint" << bits << "_t _pad_" << prefix
931 << ':' << bits - size << ";\n";
934 int pos = sym->def.bits;
936 for (BitField::entries_reverse_iterator i = sym->entries_rbegin();
937 i != sym->entries_rend(); ++i)
941 output_bf_elem(d, pos, typebits, prefix);
946 for (BitField::entries_iterator i = sym->entries_begin();
947 i != sym->entries_end(); ++i)
950 output_bf_elem(d, pos, typebits, prefix);
956 void CPPFile::output(BitField *sym, int pass, void *arg2)
965 file << indent << "union " << **sym->name << ";\n";
969 int bits = round_up_bits(sym->def.bits);
972 file << indent << "union ";
973 file << get_definition_name(sym) << " {\n";
976 file << indent << "struct {\n";
980 output_bf(sym, bits, bits, nullprefix);
983 file << indent << "};\n\n"
984 << indent << "uint" << bits << "_t _raw;\n\n"
985 << indent << **sym->name << "()\n"
987 << indent << "\t_raw = 0;\n"
989 << indent << **sym->name << "(uint" << bits << "_t _init)\n"
991 << indent << "\t_raw = _init;\n"
993 << indent << "operator uint" << bits << "_t()\n"
995 << indent << "\treturn _raw;\n"
999 file << indent << "};\n";
1002 output_aliases_and_types(sym);
1012 void CPPFile::output(Enum *sym, int pass, void *arg2)
1019 case trav_forward: {
1020 bool do_ns_out = false;
1022 if (indent.indent_level == 0) {
1029 file << indent << "struct " << **sym->name << " {\n";
1032 for (Enum::entries_iterator i = sym->entries_begin();
1033 i != sym->entries_end(); ++i)
1037 file << indent << "static const uint"
1038 << round_up_bits(sym->def.bits) << "_t "
1039 << **d->name << " = " << d->def.ucon << ";\n";
1042 file << '\n' << indent << "unsigned int _val;\n\n";
1044 file << indent << **sym->name << "()\n"
1046 << indent << "\t_val = 0;\n"
1047 << indent << "}\n\n";
1049 file << indent << **sym->name << "(unsigned int val)\n"
1051 << indent << "\t_val = val;\n"
1052 << indent << "}\n\n";
1054 file << indent << "operator unsigned int()\n"
1056 << indent << "\treturn _val;\n"
1057 << indent << "}\n\n";
1060 file << indent << "};\n";
1069 // Nothing particular to do here, other than to make sure
1070 // that trav_forward has happened (which will always need to
1071 // be done here if it's not a nested type).
1073 output_pass(sym, trav_forward);
1081 void CPPFile::output(BasicType *sym, int pass, void *arg2)
1088 case trav_forward: {
1089 bool do_ns_out = false;
1091 if (indent.indent_level == 0) {
1098 file << indent << "typedef ";
1099 assert(!is_array(sym->def));
1100 cpp_output_type(file, sym->def, false);
1101 file << **sym->name << ";\n";
1110 output_pass(sym, trav_forward);
1118 void CPPFile::output(Alias *sym, int pass, void *arg2)
1125 case trav_forward: {
1126 bool do_ns_out = false;
1128 if (indent.indent_level == 0) {
1135 const String *type = sym->get_concrete_sym()->get_fq_name("_ns")
1138 file << indent << "typedef " << *type << " "
1139 << **sym->name << ";\n";
1148 output_pass(sym, trav_forward);
1156 void CPPFile::output(TypeDef *sym, int pass, void *arg2)
1165 output_pass(sym->get_concrete_sym(), trav_forward);
1167 bool do_ns_out = false;
1169 if (indent.indent_level == 0) {
1176 const String *type = sym->get_concrete_sym()->get_fq_name("_ns")
1179 file << indent << "typedef " << *type << " "
1180 << **sym->name << ";\n";
1193 void CPPFile::output(Datum *sym, int pass, void *arg2)
1195 assert(sym->def.flags.field.Const);
1205 declare_type_dependency(sym->type, false);
1207 bool do_ns_out = false;
1209 if (indent.indent_level == 0) {
1216 file << indent << "static const ";
1218 assert(!is_array(sym->def.basictype));
1221 cpp_output_type(file, sym->type, false, false);
1223 cpp_output_type(file, sym->def.basictype, false);
1225 file << **sym->name << " = ";
1227 CompiledBasicType *def;
1229 Symbol *real_type = sym->type->get_concrete_sym();
1230 BasicType *bt = dynamic_cast<BasicType *>(real_type);
1235 def = &sym->def.basictype;
1238 if (def->flags.field.Float) {
1239 file << sym->def.fcon;
1240 } else if (def->flags.field.Bool) {
1241 if (sym->def.ucon == 0)
1246 if (def->flags.field.Unsigned) {
1247 file << "0x" << std::hex << sym->def.ucon << std::dec << 'U';
1249 file << sym->def.icon;
1268 void CPPBinding::output_root(UserNameSpace *ns, const char *dir)
1270 delete new CPPFile(ns, dir);