]> git.buserror.net Git - polintos/scott/priv.git/blob - idlcomp/languages/c++/c++.h
Initial struct marshalling.
[polintos/scott/priv.git] / idlcomp / languages / c++ / c++.h
1 #ifndef IDLC_CPP_H
2 #define IDLC_CPP_H
3
4 #include <fstream>
5 #include <list>
6
7 #include <lang.h>
8 #include <util.h>
9
10 using std::ofstream;
11 using std::ostream;
12
13 // Output the namespace-qualified symbol name, including
14 // user namespaces.   A prefix for the final component (i.e. the
15 // actual name) can optionally be specified.
16
17 void cpp_output_name(ostream &file, Symbol *sym, const char *prefix = "");
18
19 // Output the C++ type, not including the array, including
20 // a trailing space.
21
22 void cpp_output_type(ostream &file, Type *t, bool array, bool is_mutable);
23 void cpp_output_type(ostream &file, CompiledBasicType &t, bool is_mutable);
24
25 // Output the param's fully-qualified type, a space, and the name
26 // of the param.
27
28 void cpp_output_one_param(ostream &file, Param *p, bool is_server,
29                           bool is_copy = false);
30
31 enum CPPTraversal {
32         trav_full,         // Full, final output
33         trav_obj_def,      // Object struct definition
34         trav_obj_stub,     // Object pointer stub,
35                       // so it can be used in structs.
36         trav_nsdecl,       // _ns declaration
37         trav_forward,      // Forward declaration of
38                       // structs/interfaces in nsdecl
39
40         num_traversals,
41         
42         // Values beyond this point are not part of the
43         // above sequential pass scheme; they are merely
44         // for dynamic dispatch.
45         trav_marshall,
46         trav_unmarshall,
47 };
48
49 // Per-symbol language-private data
50 struct CPPData : public Releasable {
51         // The traversal indices are also passed as "arg1" to determine
52         // which pass to generate.  Higher numbers are performed first.
53         
54         int traversed[num_traversals];
55
56         CPPData() : Releasable(1)
57         {
58                 memset(traversed, 0, sizeof(traversed));
59         }
60 };
61
62 static inline CPPData &cpp_symdata(Symbol *sym)
63 {
64         if (!sym->lang_priv)
65                 sym->lang_priv = new CPPData;
66
67         CPPData *ptr = dynamic_cast<CPPData *>(sym->lang_priv);
68         assert(ptr);
69         return *ptr;
70 }
71         
72 // Each IDL namespace is mapped to a C++ header file,
73 // represented by a CPPFile.
74
75 class CPPFile : public LangCallback {
76         Indent indent;
77         string dirname;
78         ofstream file;
79         UserNameSpace *ns;
80         StrList *fqname;
81
82         //// Interface caller-side members:
83         
84         // Outputs the body of the internal _i_<ifacename> struct,
85         // containing a vtable pointer (and definition).
86
87         void output_internal(Interface *sym);
88         
89         // Outputs the user-visible class wrapper that is used to
90         // allow implicit upcasts.
91         
92         void output_wrapper(Interface *sym);
93
94         // Output implementations of the cast methods prototyped in the wrapper.
95         // The implementation is delayed to avoid circular dependency problems.
96
97         void output_casts(Interface *sym);
98         
99         //// Marshalling methods
100         
101         void output_marshall_pass(Struct *sym, int pass);
102         void output_marshall_method(Struct *sym);
103         void output_marshall_inline_method(Struct *sym);
104         void marshall_members(Struct *sym);
105
106         void output_marshall_array(Datum *d);
107         void output_marshall(Struct *sym, Datum *d);
108         void output_marshall(Interface *sym, Datum *d);
109         void output_marshall(Enum *sym, Datum *d);
110         void output_marshall(BitField *sym, Datum *d);
111         void output_marshall(BasicType *sym, Datum *d);
112         void output_marshall(CompiledBasicType &cbt, Datum *d);
113
114         void align_type(Symbol *sym);
115         void grow_buf();
116
117         // Output the downcast and implicit upcast methods for
118         // the given interface/superinterface pair.
119
120         static void wrapper_cast_callback(Interface *iface, void *arg);
121         void output_downcast(Interface *iface, Interface *super);
122         void output_upcast(Interface *iface, Interface *super);
123
124         static void wrapper_cast_proto_callback(Interface *iface, void *arg);
125         void output_downcast_proto(Interface *iface, Interface *super);
126         void output_upcast_proto(Interface *iface, Interface *super);
127
128         static void wrapper_method_proto_callback(Interface *iface, void *arg);
129         static void wrapper_method_callback(Interface *iface, void *arg);
130
131         void output_iface_tbl(Interface *iface);
132         static void tbl_callback(Interface *iface, void *arg);
133         void output_iface_tbl_entry(Interface *iface, Interface *super);
134
135         static void output_method_ptrs_callback(Interface *iface, void *arg);
136         void output_method_ptrs(Interface *iface);
137         void output_methods(Interface *iface, Interface *super, bool prototype);
138         void output_method_defs(Interface *iface);
139
140         void output_one_method(Interface *iface, Method *m,
141                                bool prototype, bool retval);
142         void output_one_method_ptr(Method *m, Interface *iface);
143         
144         //// Misc members:
145
146         // Output the static const guid[] value, and the IFaceInfo struct.
147
148         void output_guid(const uint64_t *guid);
149         void output_ifaceinfo(Interface *iface);
150
151         // Output a datum in the given struct, along with any necessary
152         // padding.  Return the offset of the next datum.
153         
154         int output_datum(Struct *ns, Datum *d, int offset);
155
156         void output_vstruct_info(Struct *sym);
157         void output_vstruct_main(Struct *sym);
158         void output_struct_ctor(Struct *sym, bool extra_vstruct);
159         int output_struct_ctor_rec1(Struct *sym, int num);
160         int output_struct_ctor_rec2(Struct *sym, int num);
161
162         void output_bf_elem(Datum *d, int pos, int bits, string &prefix);
163         void output_bf(BitField *bf, int bits, int typebits, string &prefix);
164                 
165         // Call ns_in on the symbol in order to declare the containing
166         // namespace.  Call ns_out when finished.  ns_out also takes care
167         // of inserting the extra newline separating declarations.  The
168         // "extra" parameter allows extra output passes to have unique
169         // #ifndef names, and should have a trailing underscore.
170         
171         void ns_in(Symbol *sym, const char *extra = "DEF_");
172         void ns_out(Symbol *sym);
173
174         // As above, but also outputs non-user namespaces (optionally
175         // including "sym" itself).
176
177         void all_ns_in(Symbol *sym, bool include_self = false,
178                        const char *extra = "DEF_");
179         void all_ns_out(Symbol *sym, bool include_self = false);
180
181         // Output a protective #ifndef/#define block to keep a type
182         // from being declared more than once.  Call ifndef_out()
183         // for the #endif.
184         
185         void ifndef_in(Symbol *sym, const char *extra = "DEF_");
186         void ifndef_out();
187         
188         // Return the namespace-qualified symbol name, excluding
189         // user namespaces.  This is used when defining a name
190         // which (if it is nested) has been previously forward
191         // declared.  A prefix for the final component (i.e. the
192         // actual name) can optionally be specified.
193         
194         String &get_definition_name(Symbol *sym, const char *prefix = "");
195         
196         // Output the _ns declaration of a struct or interface.
197         // If a callback is supplied, it is called inside the
198         // namespace, before any namespace members have been
199         // emitted.
200         
201         void output_nsdecl_begin(NameSpace *ns);
202         void output_nsdecl_children(NameSpace *ns);
203         void output_nsdecl_end(NameSpace *ns);
204         void output_nsdecl(NameSpace *ns);
205
206         void output_aliases_and_types(NameSpace *ns);
207         
208         // When a top-level struct or interface is about to be generated,
209         // it is scanned for other types which need to be generated.  If the
210         // full definition is needed, it goes on the need_to_declare list;
211         // otherwise, it goes on the need_to_forward_declare list.  When
212         // processing the lists, if a node has already been marked as
213         // traversed, it is skipped.
214         
215         // Full declaration is needed for superstructs, superinterfaces,
216         // inline structs (once implemented) used, and typedefs used.
217         // It is also necessary to fully declare any type which contains
218         // a type whose forward declaration is needed, as such types
219         // cannot (as far as I know) be forward-declared.
220         
221         std::list<Symbol *> need_to_declare;
222         
223         // Forward declaration is needed for types used via a pointer only.
224         
225         std::list<Symbol *> need_to_forward_declare;
226         
227         void declare_dependencies(Struct *sym);
228         void declare_dependencies(Interface *iface, bool need_obj_def = false);
229         void declare_type_dependency(Type *t, bool need_obj_def = false);
230
231         // This is the traversal of the first namespace; any symbol
232         // whose last traversal is at least this has been written to
233         // at least one of the included namespaces (and/or the
234         // current namespace).
235
236         int first_traversal;
237
238         bool pass_needed(Symbol *sym, int pass)
239         {
240                 return first_traversal > cpp_symdata(sym).traversed[pass];
241         }
242
243         void output_pass(Symbol *sym, int pass)
244         {
245                 if (pass_needed(sym, pass)) {
246                         cpp_symdata(sym).traversed[pass] = traversal;
247                         sym->output_lang(this, pass);
248                 }
249         }
250
251         bool do_extra_newline;
252
253         void downscope()
254         {
255                 indent.indent_level++;
256                 do_extra_newline = false;
257         }
258         
259         void upscope()
260         {
261                 indent.indent_level--;
262                 do_extra_newline = true;
263         }
264         
265         void extra_newline()
266         {
267                 if (do_extra_newline)
268                         file << "\n";
269                 
270                 do_extra_newline = true;
271         }
272
273 public:
274         CPPFile(UserNameSpace *ns, const char *dir);
275         virtual ~CPPFile();
276
277         void output(UserNameSpace *sym, int pass = trav_full, void *arg2 = NULL);
278         void output(Struct *sym, int pass = trav_full, void *arg2 = NULL);
279         void output(Interface *sym, int pass = trav_full, void *arg2 = NULL);
280         void output(BitField *sym, int pass = trav_full, void *arg2 = NULL);
281         void output(Enum *sym, int pass = trav_full, void *arg2 = NULL);
282         void output(BasicType *sym, int pass = trav_full, void *arg2 = NULL);
283         void output(Alias *sym, int pass = trav_full, void *arg2 = NULL);
284         void output(TypeDef *sym, int pass = trav_full, void *arg2 = NULL);
285         void output(Datum *sym, int pass = trav_full, void *arg2 = NULL);
286
287         void marshall(Struct *sym);
288         void marshall(Interface *sym);
289         void marshall(BitField *sym);
290         void marshall(Enum *sym);
291         void marshall(BasicType *sym);
292
293         void unmarshall(Struct *sym);
294         void unmarshall(Interface *sym);
295         void unmarshall(BitField *sym);
296         void unmarshall(Enum *sym);
297         void unmarshall(BasicType *sym);
298 };
299
300 class CPPBinding : public Language {
301 public:
302         CPPBinding()
303         {
304                 name = "C++";
305                 next = first_lang;
306                 first_lang = this;
307         }
308
309         void output_root(UserNameSpace *ns, const char *dir);
310         void output_server(UserNameSpace *ns, const char *dir);
311 };
312
313 #endif