1 // idlcomp/languages/c++/interface-caller.cc -- caller-side interface definitions
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
18 struct callback_data {
25 void CPPFile::output_iface_tbl_entry(Interface *iface, Interface *super)
27 file << indent << "::System::RunTime::IFaceTable "
28 << *super->get_fq_name()->flatten("_IDLNS_") << ";\n";
31 void CPPFile::tbl_callback(Interface *super, void *arg)
33 const callback_data *data = static_cast<const callback_data *>(arg);
34 data->file->output_iface_tbl_entry(data->iface, super);
37 void CPPFile::output_iface_tbl(Interface *iface)
39 file << indent << "struct iface_table {\n";
41 indent.indent_level++;
43 output_iface_tbl_entry(iface, iface);
45 callback_data data = { this, iface };
47 iface->for_each_super<tbl_callback>(&data);
48 file << indent << "unsigned char *_end;\n";
50 indent.indent_level--;
52 file << indent << "} iface_table;\n\n";
55 void cpp_output_one_param(ostream &file, Param *p,
56 bool is_server, bool is_copy)
58 bool is_mutable = p->def.flags.field.Shared ||
59 p->def.flags.field.Push ||
61 (p->def.flags.field.Inline ||
64 if (dynamic_cast<Interface *>(*p->type)) {
65 cpp_output_name(file, p->type);
68 cpp_output_type(file, p->type, p->is_array(), is_mutable);
70 cpp_output_type(file, p->def.basictype, is_mutable);
73 if (p->def.flags.field.Out)
76 if (dynamic_cast<Struct *>(*p->type) && !p->is_inline())
82 void CPPFile::output_one_method(Interface *iface, Method *m,
83 bool prototype, bool retval)
85 const String &nsname = get_definition_name(iface);
87 file << '\n' << indent << "inline ";
93 file << get_definition_name(iface) << "::";
95 file << **m->name << '(';
98 indent.align_spaces = m->name->length() + 8;
100 indent.align_spaces = m->name->length() + nsname.length() + 10;
103 indent.align_spaces += 5;
106 for (Method::entries_iterator i = m->entries_begin();
107 i != m->entries_end(); ++i)
110 file << ",\n" << indent;
114 cpp_output_one_param(file, *i, false);
118 indent.align_spaces = 0;
125 file << '\n' << indent << "{\n";
128 // FIXME: It'd be nice to skip the NULL test in this cast,
131 file << indent << "_ptr->info->methods." << **m->name
134 cpp_output_name(file, m->get_ns());
136 file << ">(*this)._ptr";
138 indent.align_spaces = m->name->length() + 21;
140 for (Method::entries_iterator i = m->entries_begin();
141 i != m->entries_end(); ++i)
144 file << ",\n" << indent << **p->name;
148 indent.align_spaces = 0;
151 file << indent << "}\n";
154 void CPPFile::output_methods(Interface *iface, Interface *super, bool prototype)
156 for (Interface::methods_iterator m = super->methods_begin();
157 m != super->methods_end(); ++m)
159 output_one_method(iface, *m, prototype, false);
162 if (method has at least one out parameter)
163 output_one_method(iface, *m, prototype, true);
168 void CPPFile::output_one_method_ptr(Method *m, Interface *iface)
170 Interface *super = static_cast<Interface *>(m->get_ns());
173 file << indent << "void (*" << **m->name << ")(void *_this";
174 indent.align_spaces = m->name->length() + 9;
176 for (Method::entries_iterator p = m->entries_begin();
177 p != m->entries_end(); ++p)
179 file << ",\n" << indent;
180 cpp_output_one_param(file, *p, false);
184 indent.align_spaces = 0;
187 void CPPFile::output_method_ptrs_callback(Interface *super, void *arg)
189 const callback_data *data = static_cast<const callback_data *>(arg);
191 for (Interface::methods_iterator m = super->methods_begin();
192 m != super->methods_end(); ++m)
193 data->file->output_one_method_ptr(*m, data->iface);
196 void CPPFile::output_method_ptrs(Interface *iface)
198 file << indent << "struct methods {\n";
201 callback_data data = { this, iface };
203 output_method_ptrs_callback(iface, &data);
204 iface->for_each_super<output_method_ptrs_callback>(&data);
207 file << indent << "} methods;\n";
210 void CPPFile::output_internal(Interface *iface)
212 file << indent << "struct info_type {\n";
214 indent.indent_level++;
217 if (iface->supers_empty()) {
218 // No supers. If it's System.Object, output the top-level
219 // info_type. Otherwise, inherit from System.Object.
221 if (iface != System_Object) {
222 yyerrorf("Interface \"%s\" has no superinterface and "
223 "is not \"System.Object\".",
224 iface->get_fq_name()->flatten()->c_str());
229 file << indent << "ptrdiff_t concrete;\n"
230 << indent << "::System::RunTime::IFaceTable "
231 "*concrete_IFaceTable;\n";
233 Interface *super = *iface->supers_begin();
236 cpp_output_name(file, super, "_i_");
237 file << "::info_type parent;\n";
242 output_iface_tbl(iface);
243 output_method_ptrs(iface);
245 indent.indent_level--;
247 file << indent << "};\n\n"
248 << indent << "const info_type *const info;\n";
250 file << '\n' << indent << "_i_" << **iface->name << '(';
251 indent.align_spaces = iface->name->length() + 4;
252 cpp_output_name(file, iface, "_i_");
254 file << "::info_type *INFO) :\n"
255 << indent << "info(INFO)\n";
257 indent.align_spaces = 0;
258 file << indent << "{}\n";
261 void CPPFile::output_downcast_proto(Interface *iface, Interface *super)
263 file << '\n' << indent << "static inline " << **iface->name << " downcast(";
264 cpp_output_type(file, super, false, false);
265 file << "oldptr);\n";
268 void CPPFile::output_downcast(Interface *iface, Interface *super)
270 const String &name = get_definition_name(iface);
271 const String &iname = get_definition_name(iface, "_i_");
273 file << '\n' << indent << "inline " << name << ' '
274 << name << "::downcast(";
275 cpp_output_type(file, super, false, false);
278 file << "\n" << indent << "{\n";
280 indent.indent_level++;
282 file << indent << "::System::_i_Object *_llptr = \n"
283 << indent << "\treinterpret_cast< ::System::_i_Object *>(oldptr._ptr);\n"
284 << indent << "return " << name << "(reinterpret_cast< "
286 << indent << "\t(::System::RunTime::downcast(_llptr, "
287 << name << "_ns::_guid.l)));\n";
289 indent.indent_level--;
291 file << indent << "}\n";
294 void CPPFile::output_upcast_proto(Interface *iface, Interface *super)
296 const String &supername = *super->get_fq_name("_ns")->flatten("::");
297 file << indent << "inline operator ::" << supername << "();\n";
300 void CPPFile::output_upcast(Interface *iface, Interface *super)
302 const String &supername = *super->get_fq_name("_ns")->flatten("::");
304 file << '\n' << indent << "inline "
305 << get_definition_name(iface)
306 << "::operator ::" << supername << "()\n"
309 indent.indent_level++;
311 // A space is added after the final '<', as GCC gives a parse
312 // error otherwise. I'm not sure exactly why...
314 file << indent << "uintptr_t ptr = reinterpret_cast<uintptr_t>(_ptr);\n\n"
315 << indent << "if (!_ptr)\n"
316 << indent << "\treturn NULL;\n\n"
317 << indent << "ptr += _ptr->info->iface_table."
318 << *super->get_fq_name()->flatten("_IDLNS_")
320 << indent << "return ::" << supername << "(reinterpret_cast< ";
322 cpp_output_name(file, super, "_i_");
324 file << " *>(ptr));\n";
326 indent.indent_level--;
328 file << indent << "}\n";
331 void CPPFile::wrapper_cast_callback(Interface *super, void *arg)
333 const callback_data *data = static_cast<const callback_data *>(arg);
335 data->file->output_downcast(data->iface, super);
336 data->file->output_upcast(data->iface, super);
339 void CPPFile::wrapper_cast_proto_callback(Interface *super, void *arg)
341 const callback_data *data = static_cast<const callback_data *>(arg);
343 data->file->output_downcast_proto(data->iface, super);
344 data->file->output_upcast_proto(data->iface, super);
347 void CPPFile::output_wrapper(Interface *iface)
349 const String &name = **iface->name;
351 file << indent << "_i_" << name << " *_ptr;\n\n";
353 file << indent << name << "()\n"
355 << indent << "\t_ptr = NULL;\n"
356 << indent << "}\n\n";
358 file << indent << name << "(_i_" << name << " *_other)\n"
360 << indent << "\t_ptr = _other;\n"
361 << indent << "}\n\n";
363 file << indent << "operator _i_" << name << " *()\n"
365 << indent << "\treturn _ptr;\n"
368 do_extra_newline = true;
370 callback_data data = { this, iface, true };
372 iface->for_each_super<wrapper_cast_proto_callback>(&data);
374 output_methods(iface, iface, true);
375 iface->for_each_super<wrapper_method_callback>(&data);
378 void CPPFile::output_casts(Interface *iface)
380 callback_data data = { this, iface };
382 iface->for_each_super<wrapper_cast_callback>(&data);
385 void CPPFile::wrapper_method_callback(Interface *super, void *arg)
387 const callback_data *data = static_cast<const callback_data *>(arg);
389 data->file->output_methods(data->iface, super, data->prototype);
392 void CPPFile::output_method_defs(Interface *iface)
394 output_methods(iface, iface, false);
396 callback_data data = { this, iface, false };
397 iface->for_each_super<wrapper_method_callback>(&data);