root/branches/libffado-2.0/external/dbus/tools/xml2cpp.cpp

Revision 1235, 23.7 kB (checked in by ppalmers, 16 years ago)

svn merge -r 1231:1234 svn+ssh://ffadosvn@ffado.org/ffado/trunk/libffado

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