1 |
/* |
---|
2 |
* |
---|
3 |
* D-Bus++ - C++ bindings for D-Bus |
---|
4 |
* |
---|
5 |
* Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com> |
---|
6 |
* |
---|
7 |
* |
---|
8 |
* This library is free software; you can redistribute it and/or |
---|
9 |
* modify it under the terms of the GNU Lesser General Public |
---|
10 |
* License as published by the Free Software Foundation; either |
---|
11 |
* version 2.1 of the License, or (at your option) any later version. |
---|
12 |
* |
---|
13 |
* This library is distributed in the hope that it will be useful, |
---|
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
16 |
* Lesser General Public License for more details. |
---|
17 |
* |
---|
18 |
* You should have received a copy of the GNU Lesser General Public |
---|
19 |
* License along with this library; if not, write to the Free Software |
---|
20 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
21 |
* |
---|
22 |
*/ |
---|
23 |
|
---|
24 |
|
---|
25 |
#include "xml2cpp.h" |
---|
26 |
|
---|
27 |
#include <dbus/dbus.h> |
---|
28 |
|
---|
29 |
#include <string> |
---|
30 |
#include <map> |
---|
31 |
#include <iostream> |
---|
32 |
#include <fstream> |
---|
33 |
#include <sstream> |
---|
34 |
|
---|
35 |
using namespace std; |
---|
36 |
using namespace DBus; |
---|
37 |
|
---|
38 |
static const char* tab = " "; |
---|
39 |
|
---|
40 |
static const char* header = "\n\ |
---|
41 |
/*\n\ |
---|
42 |
* This file was automatically generated by dbusxx-xml2cpp; DO NOT EDIT!\n\ |
---|
43 |
*/\n\ |
---|
44 |
\n\ |
---|
45 |
"; |
---|
46 |
|
---|
47 |
static const char* dbus_includes = "\n\ |
---|
48 |
#include <dbus-c++/dbus.h>\n\ |
---|
49 |
\n\ |
---|
50 |
"; |
---|
51 |
|
---|
52 |
typedef map<string,string> TypeCache; |
---|
53 |
|
---|
54 |
void usage( const char* argv0 ) |
---|
55 |
{ |
---|
56 |
cerr << endl << "Usage: " << argv0 << " <xmlfile> [ --proxy=<outfile.h> ] [ --adaptor=<outfile.h> ]" |
---|
57 |
<< endl << endl; |
---|
58 |
exit(-1); |
---|
59 |
} |
---|
60 |
|
---|
61 |
void underscorize( string& str ) |
---|
62 |
{ |
---|
63 |
for(unsigned int i = 0; i < str.length(); ++i) |
---|
64 |
{ |
---|
65 |
if(!isalpha(str[i]) && !isdigit(str[i])) str[i] = '_'; |
---|
66 |
} |
---|
67 |
} |
---|
68 |
|
---|
69 |
string stub_name( string name ) |
---|
70 |
{ |
---|
71 |
underscorize(name); |
---|
72 |
|
---|
73 |
return "_" + name + "_stub"; |
---|
74 |
} |
---|
75 |
|
---|
76 |
int char_to_atomic_type( char t ) |
---|
77 |
{ |
---|
78 |
if(strchr("ybnqiuxtdsgavre", t)) |
---|
79 |
return t; |
---|
80 |
|
---|
81 |
return DBUS_TYPE_INVALID; |
---|
82 |
} |
---|
83 |
|
---|
84 |
const char* atomic_type_to_string( char t ) |
---|
85 |
{ |
---|
86 |
static struct { const char type; const char *name; } atos[] = |
---|
87 |
{ |
---|
88 |
{ 'y', "::DBus::Byte" }, |
---|
89 |
{ 'b', "::DBus::Bool" }, |
---|
90 |
{ 'n', "::DBus::Int16" }, |
---|
91 |
{ 'q', "::DBus::UInt16" }, |
---|
92 |
{ 'i', "::DBus::Int32" }, |
---|
93 |
{ 'u', "::DBus::UInt32" }, |
---|
94 |
{ 'x', "::DBus::Int64" }, |
---|
95 |
{ 't', "::DBus::UInt64" }, |
---|
96 |
{ 'd', "::DBus::Double" }, |
---|
97 |
{ 's', "::DBus::String" }, |
---|
98 |
{ 'o', "::DBus::Path" }, |
---|
99 |
{ 'g', "::DBus::Signature" }, |
---|
100 |
{ 'v', "::DBus::Variant" }, |
---|
101 |
{ '\0', "" } |
---|
102 |
}; |
---|
103 |
int i; |
---|
104 |
|
---|
105 |
for(i = 0; atos[i].type; ++i) |
---|
106 |
{ |
---|
107 |
if(atos[i].type == t) break; |
---|
108 |
} |
---|
109 |
return atos[i].name; |
---|
110 |
} |
---|
111 |
|
---|
112 |
bool is_atomic_type( const string& type ) |
---|
113 |
{ |
---|
114 |
return type.length() == 1 && char_to_atomic_type(type[0]) != DBUS_TYPE_INVALID; |
---|
115 |
} |
---|
116 |
|
---|
117 |
void _parse_signature( const string& signature, string& type, unsigned int& i ) |
---|
118 |
{ |
---|
119 |
for(; i < signature.length(); ++i) |
---|
120 |
{ |
---|
121 |
switch(signature[i]) |
---|
122 |
{ |
---|
123 |
case 'a': |
---|
124 |
{ |
---|
125 |
switch(signature[++i]) |
---|
126 |
{ |
---|
127 |
case '{': |
---|
128 |
{ |
---|
129 |
type += "std::map< "; |
---|
130 |
|
---|
131 |
const char* atom = atomic_type_to_string(signature[++i]); |
---|
132 |
if(!atom) |
---|
133 |
{ |
---|
134 |
cerr << "invalid signature" << endl; |
---|
135 |
exit(-1); |
---|
136 |
} |
---|
137 |
type += atom; |
---|
138 |
type += ", "; |
---|
139 |
++i; |
---|
140 |
break; |
---|
141 |
} |
---|
142 |
default: |
---|
143 |
{ |
---|
144 |
type += "std::vector< "; |
---|
145 |
break; |
---|
146 |
} |
---|
147 |
} |
---|
148 |
_parse_signature(signature, type, i); |
---|
149 |
type += " >"; |
---|
150 |
continue; |
---|
151 |
} |
---|
152 |
case '(': |
---|
153 |
{ |
---|
154 |
type += "::DBus::Struct< "; |
---|
155 |
++i; |
---|
156 |
_parse_signature(signature, type, i); |
---|
157 |
type += " >"; |
---|
158 |
continue; |
---|
159 |
} |
---|
160 |
case ')': |
---|
161 |
case '}': |
---|
162 |
{ |
---|
163 |
return; |
---|
164 |
} |
---|
165 |
default: |
---|
166 |
{ |
---|
167 |
const char* atom = atomic_type_to_string(signature[i]); |
---|
168 |
if(!atom) |
---|
169 |
{ |
---|
170 |
cerr << "invalid signature" << endl; |
---|
171 |
exit(-1); |
---|
172 |
} |
---|
173 |
type += atom; |
---|
174 |
|
---|
175 |
if(signature[i+1] != ')' && signature[i+1] != '}' && i+1 < signature.length()) |
---|
176 |
{ |
---|
177 |
type += ", "; |
---|
178 |
} |
---|
179 |
break; |
---|
180 |
} |
---|
181 |
} |
---|
182 |
} |
---|
183 |
} |
---|
184 |
|
---|
185 |
string signature_to_type( const string& signature ) |
---|
186 |
{ |
---|
187 |
string type; |
---|
188 |
unsigned int i = 0; |
---|
189 |
_parse_signature(signature, type, i); |
---|
190 |
return type; |
---|
191 |
} |
---|
192 |
|
---|
193 |
void generate_proxy( Xml::Document& doc, const char* filename ) |
---|
194 |
{ |
---|
195 |
cerr << "writing " << filename << endl; |
---|
196 |
|
---|
197 |
ofstream file(filename); |
---|
198 |
if(file.bad()) |
---|
199 |
{ |
---|
200 |
cerr << "unable to write file " << filename << endl; |
---|
201 |
exit(-1); |
---|
202 |
} |
---|
203 |
|
---|
204 |
file << header; |
---|
205 |
string filestring = filename; |
---|
206 |
underscorize(filestring); |
---|
207 |
|
---|
208 |
string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H"; |
---|
209 |
|
---|
210 |
file << "#ifndef " << cond_comp << endl; |
---|
211 |
file << "#define " << cond_comp << endl; |
---|
212 |
|
---|
213 |
file << dbus_includes; |
---|
214 |
|
---|
215 |
Xml::Node& root = *(doc.root); |
---|
216 |
Xml::Nodes interfaces = root["interface"]; |
---|
217 |
|
---|
218 |
for(Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i) |
---|
219 |
{ |
---|
220 |
Xml::Node& iface = **i; |
---|
221 |
Xml::Nodes methods = iface["method"]; |
---|
222 |
Xml::Nodes signals = iface["signal"]; |
---|
223 |
Xml::Nodes properties = iface["property"]; |
---|
224 |
Xml::Nodes ms; |
---|
225 |
ms.insert(ms.end(), methods.begin(), methods.end()); |
---|
226 |
ms.insert(ms.end(), signals.begin(), signals.end()); |
---|
227 |
|
---|
228 |
string ifacename = iface.get("name"); |
---|
229 |
if(ifacename == "org.freedesktop.DBus.Introspectable" |
---|
230 |
||ifacename == "org.freedesktop.DBus.Properties") |
---|
231 |
{ |
---|
232 |
cerr << "skipping interface " << ifacename << endl; |
---|
233 |
continue; |
---|
234 |
} |
---|
235 |
|
---|
236 |
istringstream ss(ifacename); |
---|
237 |
string nspace; |
---|
238 |
unsigned int nspaces = 0; |
---|
239 |
|
---|
240 |
while(ss.str().find('.', ss.tellg()) != string::npos) |
---|
241 |
{ |
---|
242 |
getline(ss, nspace, '.'); |
---|
243 |
|
---|
244 |
file << "namespace " << nspace << " {" << endl; |
---|
245 |
|
---|
246 |
++nspaces; |
---|
247 |
} |
---|
248 |
file << endl; |
---|
249 |
|
---|
250 |
string ifaceclass; |
---|
251 |
|
---|
252 |
getline(ss, ifaceclass); |
---|
253 |
|
---|
254 |
cerr << "generating code for interface " << ifacename << "..." << endl; |
---|
255 |
|
---|
256 |
file << "class " << ifaceclass << endl |
---|
257 |
<< " : public ::DBus::InterfaceProxy" << endl |
---|
258 |
<< "{" << endl |
---|
259 |
<< "public:" << endl |
---|
260 |
<< endl |
---|
261 |
<< tab << ifaceclass << "()" << endl |
---|
262 |
<< tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << endl |
---|
263 |
<< tab << "{" << endl; |
---|
264 |
|
---|
265 |
for(Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) |
---|
266 |
{ |
---|
267 |
Xml::Node& signal = **si; |
---|
268 |
|
---|
269 |
string marshname = "_" + signal.get("name") + "_stub"; |
---|
270 |
|
---|
271 |
file << tab << tab << "connect_signal(" |
---|
272 |
<< ifaceclass << ", " << signal.get("name") << ", " << stub_name(signal.get("name")) |
---|
273 |
<< ");" << endl; |
---|
274 |
} |
---|
275 |
|
---|
276 |
file << tab << "}" << endl |
---|
277 |
<< endl; |
---|
278 |
|
---|
279 |
file << "public:" << endl |
---|
280 |
<< endl |
---|
281 |
<< tab << "/* methods exported by this interface," << endl |
---|
282 |
<< tab << " * this functions will invoke the corresponding methods on the remote objects" << endl |
---|
283 |
<< tab << " */" << endl; |
---|
284 |
|
---|
285 |
for(Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) |
---|
286 |
{ |
---|
287 |
Xml::Node& method = **mi; |
---|
288 |
Xml::Nodes args = method["arg"]; |
---|
289 |
Xml::Nodes args_in = args.select("direction","in"); |
---|
290 |
Xml::Nodes args_out = args.select("direction","out"); |
---|
291 |
|
---|
292 |
if(args_out.size() == 0 || args_out.size() > 1 ) |
---|
293 |
{ |
---|
294 |
file << tab << "void "; |
---|
295 |
} |
---|
296 |
else if(args_out.size() == 1) |
---|
297 |
{ |
---|
298 |
file << tab << signature_to_type(args_out.front()->get("type")) << " "; |
---|
299 |
} |
---|
300 |
|
---|
301 |
file << method.get("name") << "( "; |
---|
302 |
|
---|
303 |
unsigned int i = 0; |
---|
304 |
for(Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) |
---|
305 |
{ |
---|
306 |
Xml::Node& arg = **ai; |
---|
307 |
file << "const " << signature_to_type(arg.get("type")) << "& "; |
---|
308 |
|
---|
309 |
string arg_name = arg.get("name"); |
---|
310 |
if(arg_name.length()) |
---|
311 |
file << arg_name; |
---|
312 |
else |
---|
313 |
file << "argin" << i; |
---|
314 |
|
---|
315 |
if((i+1 != args_in.size() || args_out.size() > 1)) |
---|
316 |
file << ", "; |
---|
317 |
} |
---|
318 |
|
---|
319 |
if(args_out.size() > 1) |
---|
320 |
{ |
---|
321 |
unsigned int i = 0; |
---|
322 |
for(Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) |
---|
323 |
{ |
---|
324 |
Xml::Node& arg = **ao; |
---|
325 |
file << signature_to_type(arg.get("type")) << "&"; |
---|
326 |
|
---|
327 |
string arg_name = arg.get("name"); |
---|
328 |
if(arg_name.length()) |
---|
329 |
file << " " << arg_name; |
---|
330 |
else |
---|
331 |
file << " argout" << i; |
---|
332 |
|
---|
333 |
if(i+1 != args_out.size()) |
---|
334 |
file << ", "; |
---|
335 |
} |
---|
336 |
} |
---|
337 |
file << " )" << endl; |
---|
338 |
|
---|
339 |
file << tab << "{" << endl |
---|
340 |
<< tab << tab << "::DBus::CallMessage call;" << endl; |
---|
341 |
|
---|
342 |
if(args_in.size() > 0) |
---|
343 |
{ |
---|
344 |
file << tab << tab << "::DBus::MessageIter wi = call.writer();" << endl |
---|
345 |
<< endl; |
---|
346 |
} |
---|
347 |
|
---|
348 |
unsigned int j = 0; |
---|
349 |
for(Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++j) |
---|
350 |
{ |
---|
351 |
Xml::Node& arg = **ai; |
---|
352 |
string arg_name = arg.get("name"); |
---|
353 |
if(arg_name.length()) |
---|
354 |
file << tab << tab << "wi << " << arg_name << ";" << endl; |
---|
355 |
else |
---|
356 |
file << tab << tab << "wi << argin" << j << ";" << endl; |
---|
357 |
} |
---|
358 |
|
---|
359 |
file << tab << tab << "call.member(\"" << method.get("name") << "\");" << endl |
---|
360 |
<< tab << tab << "::DBus::Message ret = invoke_method(call);" << endl; |
---|
361 |
|
---|
362 |
|
---|
363 |
if(args_out.size() > 0) |
---|
364 |
{ |
---|
365 |
file << tab << tab << "::DBus::MessageIter ri = ret.reader();" << endl |
---|
366 |
<< endl; |
---|
367 |
} |
---|
368 |
|
---|
369 |
if(args_out.size() == 1) |
---|
370 |
{ |
---|
371 |
file << tab << tab << signature_to_type(args_out.front()->get("type")) << " argout;" << endl; |
---|
372 |
file << tab << tab << "ri >> argout;" << endl; |
---|
373 |
file << tab << tab << "return argout;" << endl; |
---|
374 |
} |
---|
375 |
else if(args_out.size() > 1) |
---|
376 |
{ |
---|
377 |
unsigned int i = 0; |
---|
378 |
for(Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) |
---|
379 |
{ |
---|
380 |
Xml::Node& arg = **ao; |
---|
381 |
|
---|
382 |
string arg_name = arg.get("name"); |
---|
383 |
if(arg_name.length()) |
---|
384 |
file << tab << tab << "ri >> " << arg.get("name") << ";" << endl; |
---|
385 |
else |
---|
386 |
file << tab << tab << "ri >> argout" << i << ";" << endl; |
---|
387 |
} |
---|
388 |
} |
---|
389 |
|
---|
390 |
file << tab << "}" << endl |
---|
391 |
<< endl; |
---|
392 |
} |
---|
393 |
|
---|
394 |
file << endl |
---|
395 |
<< "public:" << endl |
---|
396 |
<< endl |
---|
397 |
<< tab << "/* signal handlers for this interface" << endl |
---|
398 |
<< tab << " */" << endl; |
---|
399 |
|
---|
400 |
for(Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) |
---|
401 |
{ |
---|
402 |
Xml::Node& signal = **si; |
---|
403 |
Xml::Nodes args = signal["arg"]; |
---|
404 |
|
---|
405 |
file << tab << "virtual void " << signal.get("name") << "( "; |
---|
406 |
|
---|
407 |
unsigned int i = 0; |
---|
408 |
for(Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) |
---|
409 |
{ |
---|
410 |
Xml::Node& arg = **ai; |
---|
411 |
file << "const " << signature_to_type(arg.get("type")) << "& "; |
---|
412 |
|
---|
413 |
string arg_name = arg.get("name"); |
---|
414 |
if(arg_name.length()) |
---|
415 |
file << arg_name; |
---|
416 |
else |
---|
417 |
file << "argin" << i; |
---|
418 |
|
---|
419 |
if((ai+1 != args.end())) |
---|
420 |
file << ", "; |
---|
421 |
} |
---|
422 |
file << " ) = 0;" << endl; |
---|
423 |
} |
---|
424 |
|
---|
425 |
file << endl |
---|
426 |
<< "private:" << endl |
---|
427 |
<< endl |
---|
428 |
<< tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl |
---|
429 |
<< tab << " */" << endl; |
---|
430 |
|
---|
431 |
for(Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) |
---|
432 |
{ |
---|
433 |
Xml::Node& signal = **si; |
---|
434 |
Xml::Nodes args = signal["arg"]; |
---|
435 |
|
---|
436 |
file << tab << "void " << stub_name(signal.get("name")) << "( const ::DBus::SignalMessage& sig )" << endl |
---|
437 |
<< tab << "{" << endl; |
---|
438 |
|
---|
439 |
if(args.size() > 0) |
---|
440 |
{ |
---|
441 |
file << tab << tab << "::DBus::MessageIter ri = sig.reader();" << endl |
---|
442 |
<< endl; |
---|
443 |
} |
---|
444 |
|
---|
445 |
unsigned int i = 0; |
---|
446 |
for(Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) |
---|
447 |
{ |
---|
448 |
Xml::Node& arg = **ai; |
---|
449 |
file << tab << tab << signature_to_type(arg.get("type")) << " " ; |
---|
450 |
|
---|
451 |
string arg_name = arg.get("name"); |
---|
452 |
if(arg_name.length()) |
---|
453 |
file << arg_name << ";" << " ri >> " << arg_name << ";" << endl; |
---|
454 |
else |
---|
455 |
file << "arg" << i << ";" << " ri >> " << "arg" << i << ";" << endl; |
---|
456 |
} |
---|
457 |
|
---|
458 |
file << tab << tab << signal.get("name") << "("; |
---|
459 |
|
---|
460 |
unsigned int j = 0; |
---|
461 |
for(Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++j) |
---|
462 |
{ |
---|
463 |
Xml::Node& arg = **ai; |
---|
464 |
|
---|
465 |
string arg_name = arg.get("name"); |
---|
466 |
if(arg_name.length()) |
---|
467 |
file << arg_name; |
---|
468 |
else |
---|
469 |
file << "arg" << j; |
---|
470 |
|
---|
471 |
if(ai+1 != args.end()) |
---|
472 |
file << ", "; |
---|
473 |
} |
---|
474 |
|
---|
475 |
file << ");" << endl; |
---|
476 |
|
---|
477 |
file << tab << "}" << endl; |
---|
478 |
} |
---|
479 |
|
---|
480 |
|
---|
481 |
file << "};" << endl |
---|
482 |
<< endl; |
---|
483 |
|
---|
484 |
for(unsigned int i = 0; i < nspaces; ++i) |
---|
485 |
{ |
---|
486 |
file << "} "; |
---|
487 |
} |
---|
488 |
file << endl; |
---|
489 |
} |
---|
490 |
|
---|
491 |
file << "#endif//" << cond_comp << endl; |
---|
492 |
|
---|
493 |
file.close(); |
---|
494 |
} |
---|
495 |
|
---|
496 |
void generate_adaptor( Xml::Document& doc, const char* filename ) |
---|
497 |
{ |
---|
498 |
cerr << "writing " << filename << endl; |
---|
499 |
|
---|
500 |
ofstream file(filename); |
---|
501 |
if(file.bad()) |
---|
502 |
{ |
---|
503 |
cerr << "unable to write file " << filename << endl; |
---|
504 |
exit(-1); |
---|
505 |
} |
---|
506 |
|
---|
507 |
file << header; |
---|
508 |
string filestring = filename; |
---|
509 |
underscorize(filestring); |
---|
510 |
|
---|
511 |
string cond_comp = "__dbusxx__" + filestring + "__ADAPTOR_MARSHAL_H"; |
---|
512 |
|
---|
513 |
file << "#ifndef " << cond_comp << endl |
---|
514 |
<< "#define " << cond_comp << endl; |
---|
515 |
|
---|
516 |
file << dbus_includes; |
---|
517 |
|
---|
518 |
Xml::Node& root = *(doc.root); |
---|
519 |
Xml::Nodes interfaces = root["interface"]; |
---|
520 |
|
---|
521 |
for(Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i) |
---|
522 |
{ |
---|
523 |
Xml::Node& iface = **i; |
---|
524 |
Xml::Nodes methods = iface["method"]; |
---|
525 |
Xml::Nodes signals = iface["signal"]; |
---|
526 |
Xml::Nodes properties = iface["property"]; |
---|
527 |
Xml::Nodes ms; |
---|
528 |
ms.insert(ms.end(), methods.begin(), methods.end()); |
---|
529 |
ms.insert(ms.end(), signals.begin(), signals.end()); |
---|
530 |
|
---|
531 |
string ifacename = iface.get("name"); |
---|
532 |
if(ifacename == "org.freedesktop.DBus.Introspectable" |
---|
533 |
||ifacename == "org.freedesktop.DBus.Properties") |
---|
534 |
{ |
---|
535 |
cerr << "skipping interface " << ifacename << endl; |
---|
536 |
continue; |
---|
537 |
} |
---|
538 |
|
---|
539 |
istringstream ss(ifacename); |
---|
540 |
string nspace; |
---|
541 |
unsigned int nspaces = 0; |
---|
542 |
|
---|
543 |
while(ss.str().find('.', ss.tellg()) != string::npos) |
---|
544 |
{ |
---|
545 |
getline(ss, nspace, '.'); |
---|
546 |
|
---|
547 |
file << "namespace " << nspace << " {" << endl; |
---|
548 |
|
---|
549 |
++nspaces; |
---|
550 |
} |
---|
551 |
file << endl; |
---|
552 |
|
---|
553 |
string ifaceclass; |
---|
554 |
|
---|
555 |
getline(ss, ifaceclass); |
---|
556 |
|
---|
557 |
cerr << "generating code for interface " << ifacename << "..." << endl; |
---|
558 |
|
---|
559 |
file << "class " << ifaceclass << endl |
---|
560 |
<< ": public ::DBus::InterfaceAdaptor" << endl |
---|
561 |
<< "{" << endl |
---|
562 |
<< "public:" << endl |
---|
563 |
<< endl |
---|
564 |
<< tab << ifaceclass << "()" << endl |
---|
565 |
<< tab << ": ::DBus::InterfaceAdaptor(\"" << ifacename << "\")" << endl |
---|
566 |
<< tab << "{" << endl; |
---|
567 |
|
---|
568 |
for(Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) |
---|
569 |
{ |
---|
570 |
Xml::Node& property = **pi; |
---|
571 |
|
---|
572 |
file << tab << tab << "bind_property(" |
---|
573 |
<< property.get("name") << ", " |
---|
574 |
<< "\"" << property.get("type") << "\", " |
---|
575 |
<< ( property.get("access").find("read") != string::npos |
---|
576 |
? "true" |
---|
577 |
: "false" ) |
---|
578 |
<< ", " |
---|
579 |
<< ( property.get("access").find("write") != string::npos |
---|
580 |
? "true" |
---|
581 |
: "false" ) |
---|
582 |
<< ");" << endl; |
---|
583 |
} |
---|
584 |
|
---|
585 |
for(Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) |
---|
586 |
{ |
---|
587 |
Xml::Node& method = **mi; |
---|
588 |
|
---|
589 |
file << tab << tab << "register_method(" |
---|
590 |
<< ifaceclass << ", " << method.get("name") << ", "<< stub_name(method.get("name")) |
---|
591 |
<< ");" << endl; |
---|
592 |
} |
---|
593 |
|
---|
594 |
file << tab << "}" << endl |
---|
595 |
<< endl; |
---|
596 |
|
---|
597 |
file << tab << "::DBus::IntrospectedInterface* const introspect() const " << endl |
---|
598 |
<< tab << "{" << endl; |
---|
599 |
|
---|
600 |
for(Xml::Nodes::iterator mi = ms.begin(); mi != ms.end(); ++mi) |
---|
601 |
{ |
---|
602 |
Xml::Node& method = **mi; |
---|
603 |
Xml::Nodes args = method["arg"]; |
---|
604 |
|
---|
605 |
file << tab << tab << "static ::DBus::IntrospectedArgument " << method.get("name") << "_args[] = " << endl |
---|
606 |
<< tab << tab << "{" << endl; |
---|
607 |
|
---|
608 |
for(Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai) |
---|
609 |
{ |
---|
610 |
Xml::Node& arg = **ai; |
---|
611 |
|
---|
612 |
file << tab << tab << tab << "{ "; |
---|
613 |
|
---|
614 |
if(arg.get("name").length()) |
---|
615 |
{ |
---|
616 |
file << "\"" << arg.get("name") << "\", "; |
---|
617 |
} |
---|
618 |
else |
---|
619 |
{ |
---|
620 |
file << "0, "; |
---|
621 |
} |
---|
622 |
file << "\"" << arg.get("type") << "\", " |
---|
623 |
<< ( arg.get("direction") == "in" ? "true" : "false" ) |
---|
624 |
<< " }," << endl; |
---|
625 |
} |
---|
626 |
file << tab << tab << tab << "{ 0, 0, 0 }" << endl |
---|
627 |
<< tab << tab << "};" << endl; |
---|
628 |
} |
---|
629 |
|
---|
630 |
file << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_methods[] = " << endl |
---|
631 |
<< tab << tab << "{" << endl; |
---|
632 |
|
---|
633 |
for(Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) |
---|
634 |
{ |
---|
635 |
Xml::Node& method = **mi; |
---|
636 |
|
---|
637 |
file << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; |
---|
638 |
} |
---|
639 |
|
---|
640 |
file << tab << tab << tab << "{ 0, 0 }" << endl |
---|
641 |
<< tab << tab << "};" << endl; |
---|
642 |
|
---|
643 |
file << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_signals[] = " << endl |
---|
644 |
<< tab << tab << "{" << endl; |
---|
645 |
|
---|
646 |
for(Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) |
---|
647 |
{ |
---|
648 |
Xml::Node& method = **si; |
---|
649 |
|
---|
650 |
file << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; |
---|
651 |
} |
---|
652 |
|
---|
653 |
file << tab << tab << tab << "{ 0, 0 }" << endl |
---|
654 |
<< tab << tab << "};" << endl; |
---|
655 |
|
---|
656 |
file << tab << tab << "static ::DBus::IntrospectedProperty " << ifaceclass << "_properties[] = " << endl |
---|
657 |
<< tab << tab << "{" << endl; |
---|
658 |
|
---|
659 |
for(Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) |
---|
660 |
{ |
---|
661 |
Xml::Node& property = **pi; |
---|
662 |
|
---|
663 |
file << tab << tab << tab << "{ " |
---|
664 |
<< "\"" << property.get("name") << "\", " |
---|
665 |
<< "\"" << property.get("type") << "\", " |
---|
666 |
<< ( property.get("access").find("read") != string::npos |
---|
667 |
? "true" |
---|
668 |
: "false" ) |
---|
669 |
<< ", " |
---|
670 |
<< ( property.get("access").find("write") != string::npos |
---|
671 |
? "true" |
---|
672 |
: "false" ) |
---|
673 |
<< " }," << endl; |
---|
674 |
} |
---|
675 |
|
---|
676 |
|
---|
677 |
file << tab << tab << tab << "{ 0, 0, 0, 0 }" << endl |
---|
678 |
<< tab << tab << "};" << endl; |
---|
679 |
|
---|
680 |
file << tab << tab << "static ::DBus::IntrospectedInterface " << ifaceclass << "_interface = " << endl |
---|
681 |
<< tab << tab << "{" << endl |
---|
682 |
<< tab << tab << tab << "\"" << ifacename << "\"," << endl |
---|
683 |
<< tab << tab << tab << ifaceclass << "_methods," << endl |
---|
684 |
<< tab << tab << tab << ifaceclass << "_signals," << endl |
---|
685 |
<< tab << tab << tab << ifaceclass << "_properties" << endl |
---|
686 |
<< tab << tab << "};" << endl |
---|
687 |
<< tab << tab << "return &" << ifaceclass << "_interface;" << endl |
---|
688 |
<< tab << "}" << endl |
---|
689 |
<< endl; |
---|
690 |
|
---|
691 |
file << "public:" << endl |
---|
692 |
<< endl |
---|
693 |
<< tab << "/* properties exposed by this interface, use" << endl |
---|
694 |
<< tab << " * property() and property(value) to get and set a particular property" << endl |
---|
695 |
<< tab << " */" << endl; |
---|
696 |
|
---|
697 |
for(Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) |
---|
698 |
{ |
---|
699 |
Xml::Node& property = **pi; |
---|
700 |
string name = property.get("name"); |
---|
701 |
string type = property.get("type"); |
---|
702 |
string type_name = signature_to_type(type); |
---|
703 |
|
---|
704 |
file << tab << "::DBus::PropertyAdaptor< " << type_name << " > " << name << ";" << endl; |
---|
705 |
} |
---|
706 |
|
---|
707 |
file << endl; |
---|
708 |
|
---|
709 |
file << "public:" << endl |
---|
710 |
<< endl |
---|
711 |
<< tab << "/* methods exported by this interface," << endl |
---|
712 |
<< tab << " * you will have to implement them in your ObjectAdaptor" << endl |
---|
713 |
<< tab << " */" << endl; |
---|
714 |
|
---|
715 |
for(Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) |
---|
716 |
{ |
---|
717 |
Xml::Node& method = **mi; |
---|
718 |
Xml::Nodes args = method["arg"]; |
---|
719 |
Xml::Nodes args_in = args.select("direction","in"); |
---|
720 |
Xml::Nodes args_out = args.select("direction","out"); |
---|
721 |
|
---|
722 |
file << tab << "virtual "; |
---|
723 |
|
---|
724 |
if(args_out.size() == 0 || args_out.size() > 1 ) |
---|
725 |
{ |
---|
726 |
file << "void "; |
---|
727 |
} |
---|
728 |
else if(args_out.size() == 1) |
---|
729 |
{ |
---|
730 |
file << signature_to_type(args_out.front()->get("type")) << " "; |
---|
731 |
} |
---|
732 |
|
---|
733 |
file << method.get("name") << "( "; |
---|
734 |
|
---|
735 |
unsigned int i = 0; |
---|
736 |
for(Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) |
---|
737 |
{ |
---|
738 |
Xml::Node& arg = **ai; |
---|
739 |
file << "const " << signature_to_type(arg.get("type")) << "& "; |
---|
740 |
|
---|
741 |
string arg_name = arg.get("name"); |
---|
742 |
if(arg_name.length()) |
---|
743 |
file << arg_name; |
---|
744 |
|
---|
745 |
if((i+1 != args_in.size() || args_out.size() > 1)) |
---|
746 |
file << ", "; |
---|
747 |
} |
---|
748 |
|
---|
749 |
if(args_out.size() > 1) |
---|
750 |
{ |
---|
751 |
unsigned int i = 0; |
---|
752 |
for(Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) |
---|
753 |
{ |
---|
754 |
Xml::Node& arg = **ao; |
---|
755 |
file << signature_to_type(arg.get("type")) << "&"; |
---|
756 |
|
---|
757 |
string arg_name = arg.get("name"); |
---|
758 |
if(arg_name.length()) |
---|
759 |
file << " " << arg_name; |
---|
760 |
|
---|
761 |
if(i+1 != args_out.size()) |
---|
762 |
file << ", "; |
---|
763 |
} |
---|
764 |
} |
---|
765 |
file << " ) = 0;" << endl; |
---|
766 |
} |
---|
767 |
|
---|
768 |
file << endl |
---|
769 |
<< "public:" << endl |
---|
770 |
<< endl |
---|
771 |
<< tab << "/* signal emitters for this interface" << endl |
---|
772 |
<< tab << " */" << endl; |
---|
773 |
|
---|
774 |
for(Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) |
---|
775 |
{ |
---|
776 |
Xml::Node& signal = **si; |
---|
777 |
Xml::Nodes args = signal["arg"]; |
---|
778 |
|
---|
779 |
file << tab << "void " << signal.get("name") << "( "; |
---|
780 |
|
---|
781 |
unsigned int i = 0; |
---|
782 |
for(Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i) |
---|
783 |
{ |
---|
784 |
Xml::Node& arg = **a; |
---|
785 |
|
---|
786 |
file << "const " << signature_to_type(arg.get("type")) << "& arg" << i+1; |
---|
787 |
|
---|
788 |
if(i+1 != args.size()) |
---|
789 |
file << ", "; |
---|
790 |
} |
---|
791 |
|
---|
792 |
file << " )" << endl |
---|
793 |
<< tab << "{" << endl |
---|
794 |
<< tab << tab << "::DBus::SignalMessage sig(\"" << signal.get("name") <<"\");" << endl;; |
---|
795 |
|
---|
796 |
|
---|
797 |
if(args.size() > 0) |
---|
798 |
{ |
---|
799 |
file << tab << tab << "::DBus::MessageIter wi = sig.writer();" << endl; |
---|
800 |
|
---|
801 |
for(unsigned int i = 0; i < args.size(); ++i) |
---|
802 |
{ |
---|
803 |
file << tab << tab << "wi << arg" << i+1 << ";" << endl; |
---|
804 |
} |
---|
805 |
} |
---|
806 |
|
---|
807 |
file << tab << tab << "emit_signal(sig);" << endl |
---|
808 |
<< tab << "}" << endl; |
---|
809 |
} |
---|
810 |
|
---|
811 |
file << endl |
---|
812 |
<< "private:" << endl |
---|
813 |
<< endl |
---|
814 |
<< tab << "/* unmarshalers (to unpack the DBus message before calling the actual interface method)" << endl |
---|
815 |
<< tab << " */" << endl; |
---|
816 |
|
---|
817 |
for(Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) |
---|
818 |
{ |
---|
819 |
Xml::Node& method = **mi; |
---|
820 |
Xml::Nodes args = method["arg"]; |
---|
821 |
Xml::Nodes args_in = args.select("direction","in"); |
---|
822 |
Xml::Nodes args_out = args.select("direction","out"); |
---|
823 |
|
---|
824 |
file << tab << "::DBus::Message " << stub_name(method.get("name")) << "( const ::DBus::CallMessage& call )" << endl |
---|
825 |
<< tab << "{" << endl |
---|
826 |
<< tab << tab << "::DBus::MessageIter ri = call.reader();" << endl |
---|
827 |
<< endl; |
---|
828 |
|
---|
829 |
unsigned int i = 1; |
---|
830 |
for(Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) |
---|
831 |
{ |
---|
832 |
Xml::Node& arg = **ai; |
---|
833 |
file << tab << tab << signature_to_type(arg.get("type")) << " argin" << i << ";" |
---|
834 |
<< " ri >> argin" << i << ";" << endl; |
---|
835 |
} |
---|
836 |
|
---|
837 |
if(args_out.size() == 0) |
---|
838 |
{ |
---|
839 |
file << tab << tab; |
---|
840 |
} |
---|
841 |
else if(args_out.size() == 1) |
---|
842 |
{ |
---|
843 |
file << tab << tab << signature_to_type(args_out.front()->get("type")) << " argout1 = "; |
---|
844 |
} |
---|
845 |
else |
---|
846 |
{ |
---|
847 |
unsigned int i = 1; |
---|
848 |
for(Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) |
---|
849 |
{ |
---|
850 |
Xml::Node& arg = **ao; |
---|
851 |
file << tab << tab << signature_to_type(arg.get("type")) << " argout" << i << ";" << endl; |
---|
852 |
} |
---|
853 |
file << tab << tab; |
---|
854 |
} |
---|
855 |
|
---|
856 |
file << method.get("name") << "("; |
---|
857 |
|
---|
858 |
for(unsigned int i = 0; i < args_in.size(); ++i) |
---|
859 |
{ |
---|
860 |
file << "argin" << i+1; |
---|
861 |
|
---|
862 |
if((i+1 != args_in.size() || args_out.size() > 1)) |
---|
863 |
file << ", "; |
---|
864 |
} |
---|
865 |
|
---|
866 |
if(args_out.size() > 1) |
---|
867 |
for(unsigned int i = 0; i < args_out.size(); ++i) |
---|
868 |
{ |
---|
869 |
file << "argout" << i+1; |
---|
870 |
|
---|
871 |
if(i+1 != args_out.size()) |
---|
872 |
file << ", "; |
---|
873 |
} |
---|
874 |
|
---|
875 |
file << ");" << endl; |
---|
876 |
|
---|
877 |
file << tab << tab << "::DBus::ReturnMessage reply(call);" << endl; |
---|
878 |
|
---|
879 |
if(args_out.size() > 0) |
---|
880 |
{ |
---|
881 |
file << tab << tab << "::DBus::MessageIter wi = reply.writer();" << endl; |
---|
882 |
|
---|
883 |
for(unsigned int i = 0; i < args_out.size(); ++i) |
---|
884 |
{ |
---|
885 |
file << tab << tab << "wi << argout" << i+1 << ";" << endl; |
---|
886 |
} |
---|
887 |
} |
---|
888 |
|
---|
889 |
file << tab << tab << "return reply;" << endl; |
---|
890 |
|
---|
891 |
file << tab << "}" << endl; |
---|
892 |
} |
---|
893 |
|
---|
894 |
file << "};" << endl |
---|
895 |
<< endl; |
---|
896 |
|
---|
897 |
for(unsigned int i = 0; i < nspaces; ++i) |
---|
898 |
{ |
---|
899 |
file << "} "; |
---|
900 |
} |
---|
901 |
file << endl; |
---|
902 |
} |
---|
903 |
|
---|
904 |
file << "#endif//" << cond_comp << endl; |
---|
905 |
|
---|
906 |
file.close(); |
---|
907 |
} |
---|
908 |
|
---|
909 |
int main( int argc, char** argv ) |
---|
910 |
{ |
---|
911 |
if(argc < 2) |
---|
912 |
{ |
---|
913 |
usage(argv[0]); |
---|
914 |
} |
---|
915 |
|
---|
916 |
bool proxy_mode, adaptor_mode; |
---|
917 |
char *proxy, *adaptor; |
---|
918 |
|
---|
919 |
proxy_mode = false; |
---|
920 |
proxy = 0; |
---|
921 |
|
---|
922 |
adaptor_mode = false; |
---|
923 |
adaptor = 0; |
---|
924 |
|
---|
925 |
for(int a = 1; a < argc; ++a) |
---|
926 |
{ |
---|
927 |
if(!strncmp(argv[a], "--proxy=", 8)) |
---|
928 |
{ |
---|
929 |
proxy_mode = true; |
---|
930 |
proxy = argv[a] +8; |
---|
931 |
} |
---|
932 |
else |
---|
933 |
if(!strncmp(argv[a], "--adaptor=", 10)) |
---|
934 |
{ |
---|
935 |
adaptor_mode = true; |
---|
936 |
adaptor = argv[a] +10; |
---|
937 |
} |
---|
938 |
} |
---|
939 |
|
---|
940 |
if(!proxy_mode && !adaptor_mode) usage(argv[0]); |
---|
941 |
|
---|
942 |
ifstream xmlfile(argv[1]); |
---|
943 |
|
---|
944 |
if(xmlfile.bad()) |
---|
945 |
{ |
---|
946 |
cerr << "unable to open file " << argv[1] << endl; |
---|
947 |
return -1; |
---|
948 |
} |
---|
949 |
|
---|
950 |
Xml::Document doc; |
---|
951 |
|
---|
952 |
try |
---|
953 |
{ |
---|
954 |
xmlfile >> doc; |
---|
955 |
//cout << doc.to_xml(); |
---|
956 |
} |
---|
957 |
catch(Xml::Error& e) |
---|
958 |
{ |
---|
959 |
cerr << "error parsing " << argv[1] << ": " << e.what() << endl; |
---|
960 |
return -1; |
---|
961 |
} |
---|
962 |
|
---|
963 |
if(!doc.root) |
---|
964 |
{ |
---|
965 |
cerr << "empty document" << endl; |
---|
966 |
return -1; |
---|
967 |
} |
---|
968 |
|
---|
969 |
if(proxy_mode) generate_proxy(doc, proxy); |
---|
970 |
if(adaptor_mode) generate_adaptor(doc, adaptor); |
---|
971 |
|
---|
972 |
return 0; |
---|
973 |
} |
---|