root/trunk/libffado/external/dbus/tools/xml2cpp.cpp

Revision 962, 23.6 kB (checked in by ppalmers, 16 years ago)

apply patch of ticket #82

Line 
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 }
Note: See TracBrowser for help on using the browser.