1426 lines
39 KiB
C++
1426 lines
39 KiB
C++
/*
|
|
*
|
|
* D-Bus++ - C++ bindings for D-Bus
|
|
*
|
|
* Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
|
|
*
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
|
|
#include "xml2cpp.h"
|
|
|
|
#include <dbus/dbus.h>
|
|
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <map>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
|
|
using namespace std;
|
|
using namespace DBus;
|
|
|
|
static const char *tab = " ";
|
|
|
|
static const char *header = "\n\
|
|
/*\n\
|
|
* This file was automatically generated by dbusxx-xml2cpp; DO NOT EDIT!\n\
|
|
*/\n\
|
|
\n\
|
|
";
|
|
|
|
static const char *dbus_includes = "\n\
|
|
#include <dbus-c++/dbus.h>\n\
|
|
\n\
|
|
";
|
|
|
|
typedef map<string,string> TypeCache;
|
|
|
|
void usage(const char *argv0)
|
|
{
|
|
cerr << endl << "Usage: " << argv0 << " <xmlfile> [ --proxy=<outfile.h> ] [ --adaptor=<outfile.h> ]"
|
|
<< endl << endl;
|
|
exit(-1);
|
|
}
|
|
|
|
void underscorize(string &str)
|
|
{
|
|
for (unsigned int i = 0; i < str.length(); ++i)
|
|
{
|
|
if (!isalpha(str[i]) && !isdigit(str[i])) str[i] = '_';
|
|
}
|
|
}
|
|
|
|
string stub_name(string name)
|
|
{
|
|
underscorize(name);
|
|
|
|
return "_" + name + "_stub";
|
|
}
|
|
|
|
int char_to_atomic_type(char t)
|
|
{
|
|
if (strchr("ybnqiuxtdsgavre", t))
|
|
return t;
|
|
|
|
return DBUS_TYPE_INVALID;
|
|
}
|
|
|
|
const char *atomic_type_to_string(char t)
|
|
{
|
|
static struct { char type; const char *name; } atos[] =
|
|
{
|
|
{ 'y', "uint8_t" },
|
|
{ 'b', "bool" },
|
|
{ 'n', "int16_t" },
|
|
{ 'q', "uint16_t" },
|
|
{ 'i', "int32_t" },
|
|
{ 'u', "uint32_t" },
|
|
{ 'x', "int64_t" },
|
|
{ 't', "uint64_t" },
|
|
{ 'd', "double" },
|
|
{ 's', "std::string" },
|
|
{ 'o', "::DBus::Path" },
|
|
{ 'g', "::DBus::Signature" },
|
|
{ 'v', "::DBus::Variant" },
|
|
{ '\0', "" }
|
|
};
|
|
int i;
|
|
|
|
for (i = 0; atos[i].type; ++i)
|
|
{
|
|
if (atos[i].type == t) break;
|
|
}
|
|
return atos[i].name;
|
|
}
|
|
|
|
bool is_atomic_type(const string &type)
|
|
{
|
|
return type.length() == 1 && char_to_atomic_type(type[0]) != DBUS_TYPE_INVALID;
|
|
}
|
|
|
|
void _parse_signature(const string &signature, string &type, unsigned int &i)
|
|
{
|
|
for (; i < signature.length(); ++i)
|
|
{
|
|
switch (signature[i])
|
|
{
|
|
case 'a':
|
|
{
|
|
switch (signature[++i])
|
|
{
|
|
case '{':
|
|
{
|
|
type += "std::map< ";
|
|
|
|
const char *atom = atomic_type_to_string(signature[++i]);
|
|
if (!atom)
|
|
{
|
|
cerr << "invalid signature" << endl;
|
|
exit(-1);
|
|
}
|
|
type += atom;
|
|
type += ", ";
|
|
++i;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
type += "std::vector< ";
|
|
break;
|
|
}
|
|
}
|
|
_parse_signature(signature, type, i);
|
|
type += " >";
|
|
continue;
|
|
}
|
|
case '(':
|
|
{
|
|
type += "::DBus::Struct< ";
|
|
++i;
|
|
_parse_signature(signature, type, i);
|
|
type += " >";
|
|
if (signature[i+1])
|
|
{
|
|
type += ", ";
|
|
}
|
|
continue;
|
|
}
|
|
case ')':
|
|
case '}':
|
|
{
|
|
return;
|
|
}
|
|
default:
|
|
{
|
|
const char *atom = atomic_type_to_string(signature[i]);
|
|
if (!atom)
|
|
{
|
|
cerr << "invalid signature" << endl;
|
|
exit(-1);
|
|
}
|
|
type += atom;
|
|
|
|
if (signature[i+1] != ')' && signature[i+1] != '}' && i+1 < signature.length())
|
|
{
|
|
type += ", ";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
string signature_to_type(const string &signature)
|
|
{
|
|
string type;
|
|
unsigned int i = 0;
|
|
_parse_signature(signature, type, i);
|
|
return type;
|
|
}
|
|
|
|
/*! Generate proxy code for a XML introspection
|
|
*/
|
|
void generate_proxy(Xml::Document &doc, const char *filename)
|
|
{
|
|
ostringstream body;
|
|
ostringstream head;
|
|
vector <string> include_vector;
|
|
|
|
head << header;
|
|
string filestring = filename;
|
|
underscorize(filestring);
|
|
|
|
string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H";
|
|
|
|
head << "#ifndef " << cond_comp << endl;
|
|
head << "#define " << cond_comp << endl;
|
|
|
|
head << dbus_includes;
|
|
|
|
Xml::Node &root = *(doc.root);
|
|
Xml::Nodes interfaces = root["interface"];
|
|
|
|
// iterate over all interface definitions
|
|
for (Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i)
|
|
{
|
|
Xml::Node &iface = **i;
|
|
Xml::Nodes methods = iface["method"];
|
|
Xml::Nodes signals = iface["signal"];
|
|
Xml::Nodes properties = iface["property"];
|
|
Xml::Nodes ms;
|
|
ms.insert(ms.end(), methods.begin(), methods.end());
|
|
ms.insert(ms.end(), signals.begin(), signals.end());
|
|
|
|
// gets the name of a interface: <interface name="XYZ">
|
|
string ifacename = iface.get("name");
|
|
|
|
// these interface names are skipped. Not sure why...
|
|
if (ifacename == "org.freedesktop.DBus.Introspectable"
|
|
||ifacename == "org.freedesktop.DBus.Properties")
|
|
{
|
|
cerr << "skipping interface " << ifacename << endl;
|
|
continue;
|
|
}
|
|
|
|
istringstream ss(ifacename);
|
|
string nspace;
|
|
unsigned int nspaces = 0;
|
|
|
|
// prints all the namespaces defined with <interface name="X.Y.Z">
|
|
while (ss.str().find('.', ss.tellg()) != string::npos)
|
|
{
|
|
getline(ss, nspace, '.');
|
|
|
|
body << "namespace " << nspace << " {" << endl;
|
|
|
|
++nspaces;
|
|
}
|
|
body << endl;
|
|
|
|
string ifaceclass;
|
|
|
|
getline(ss, ifaceclass);
|
|
|
|
// a "_proxy" is added to class name to distinguish between proxy and adaptor
|
|
ifaceclass += "_proxy";
|
|
|
|
cerr << "generating code for interface " << ifacename << "..." << endl;
|
|
|
|
// the code from class definiton up to opening of the constructor is generated...
|
|
body << "class " << ifaceclass << endl
|
|
<< " : public ::DBus::InterfaceProxy" << endl
|
|
<< "{" << endl
|
|
<< "public:" << endl
|
|
<< endl
|
|
<< tab << ifaceclass << "()" << endl
|
|
<< tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << endl
|
|
<< tab << "{" << endl;
|
|
|
|
// generates code to connect all the signal stubs; this is still inside the constructor
|
|
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
|
|
{
|
|
Xml::Node &signal = **si;
|
|
|
|
string marshname = "_" + signal.get("name") + "_stub";
|
|
|
|
body << tab << tab << "connect_signal("
|
|
<< ifaceclass << ", " << signal.get("name") << ", " << stub_name(signal.get("name"))
|
|
<< ");" << endl;
|
|
}
|
|
|
|
// the constructor ends here
|
|
body << tab << "}" << endl
|
|
<< endl;
|
|
|
|
// write public block header for properties
|
|
body << "public:" << endl << endl
|
|
<< tab << "/* properties exported by this interface */" << endl;
|
|
|
|
// this loop generates all properties
|
|
for (Xml::Nodes::iterator pi = properties.begin ();
|
|
pi != properties.end (); ++pi)
|
|
{
|
|
Xml::Node & property = **pi;
|
|
string prop_name = property.get ("name");
|
|
string property_access = property.get ("access");
|
|
if (property_access == "read" || property_access == "readwrite")
|
|
{
|
|
body << tab << tab << "const " << signature_to_type (property.get("type"))
|
|
<< " " << prop_name << "() {" << endl;
|
|
body << tab << tab << tab << "::DBus::CallMessage call ;\n ";
|
|
body << tab << tab << tab
|
|
<< "call.member(\"Get\"); call.interface(\"org.freedesktop.DBus.Properties\");"
|
|
<< endl;
|
|
body << tab << tab << tab
|
|
<< "::DBus::MessageIter wi = call.writer(); " << endl;
|
|
body << tab << tab << tab
|
|
<< "const std::string interface_name = \"" << ifacename << "\";"
|
|
<< endl;
|
|
body << tab << tab << tab
|
|
<< "const std::string property_name = \"" << prop_name << "\";"
|
|
<< endl;
|
|
body << tab << tab << tab << "wi << interface_name;" << endl;
|
|
body << tab << tab << tab << "wi << property_name;" << endl;
|
|
body << tab << tab << tab
|
|
<< "::DBus::Message ret = this->invoke_method (call);" << endl;
|
|
body << tab << tab << tab
|
|
<< "::DBus::MessageIter ri = ret.reader ();" << endl;
|
|
body << tab << tab << tab << "::DBus::Variant argout; " << endl;
|
|
body << tab << tab << tab << "ri >> argout;" << endl;
|
|
body << tab << tab << tab << "return argout;" << endl;
|
|
body << tab << tab << "};" << endl;
|
|
}
|
|
|
|
if (property_access == "write" || property_access == "readwrite")
|
|
{
|
|
body << tab << tab << "void " << prop_name << "( const "<< signature_to_type (property.get("type")) << " & input" << ") {" << endl;
|
|
body << tab << tab << tab << "::DBus::CallMessage call ;\n ";
|
|
body << tab << tab << tab <<"call.member(\"Set\"); call.interface( \"org.freedesktop.DBus.Properties\");"<< endl;
|
|
body << tab << tab << tab <<"::DBus::MessageIter wi = call.writer(); " << endl;
|
|
body << tab << tab << tab <<"::DBus::Variant value;" << endl;
|
|
body << tab << tab << tab <<"::DBus::MessageIter vi = value.writer ();" << endl;
|
|
body << tab << tab << tab <<"vi << input;" << endl;
|
|
body << tab << tab << tab <<"const std::string interface_name = \"" << ifacename << "\";" << endl;
|
|
body << tab << tab << tab <<"const std::string property_name = \"" << prop_name << "\";"<< endl;
|
|
body << tab << tab << tab <<"wi << interface_name;" << endl;
|
|
body << tab << tab << tab <<"wi << property_name;" << endl;
|
|
body << tab << tab << tab <<"wi << value;" << endl;
|
|
body << tab << tab << tab <<"::DBus::Message ret = this->invoke_method (call);" << endl;
|
|
body << tab << tab << "};" << endl;
|
|
}
|
|
}
|
|
|
|
// write public block header for methods
|
|
body << "public:" << endl
|
|
<< endl
|
|
<< tab << "/* methods exported by this interface," << endl
|
|
<< tab << " * this functions will invoke the corresponding methods on the remote objects" << endl
|
|
<< tab << " */" << endl;
|
|
|
|
// this loop generates all methods
|
|
for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi)
|
|
{
|
|
Xml::Node &method = **mi;
|
|
Xml::Nodes args = method["arg"];
|
|
Xml::Nodes args_in = args.select("direction","in");
|
|
Xml::Nodes args_out = args.select("direction","out");
|
|
Xml::Nodes annotations = method["annotation"];
|
|
Xml::Nodes annotations_noreply = annotations.select("name","org.freedesktop.DBus.NoReply");
|
|
string arg_object;
|
|
|
|
if (args_out.size() > 0)
|
|
{
|
|
string arg_object = args_out.front()->get("object");
|
|
}
|
|
|
|
if (args_out.size() == 0 || args_out.size() > 1)
|
|
{
|
|
body << tab << "void ";
|
|
}
|
|
else if (args_out.size() == 1)
|
|
{
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << arg_object << " ";
|
|
}
|
|
else
|
|
{
|
|
body << tab << signature_to_type(args_out.front()->get("type")) << " ";
|
|
}
|
|
}
|
|
|
|
body << method.get("name") << "(";
|
|
|
|
// generate all 'in' arguments for a method signature
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
string arg_object = arg.get("object");
|
|
|
|
// generate basic signature only if no object name available...
|
|
if (!arg_object.length())
|
|
{
|
|
body << "const " << signature_to_type(arg.get("type")) << "& ";
|
|
}
|
|
// ...or generate object style if available
|
|
else
|
|
{
|
|
body << "const " << arg_object << "& ";
|
|
|
|
// store a object name to later generate header includes
|
|
include_vector.push_back (arg_object);
|
|
}
|
|
|
|
string arg_name = arg.get("name");
|
|
if (arg_name.length())
|
|
body << arg_name;
|
|
else
|
|
body << "argin" << i;
|
|
|
|
if ((i+1 != args_in.size() || args_out.size() > 1))
|
|
body << ", ";
|
|
}
|
|
|
|
if (args_out.size() > 1)
|
|
{
|
|
// generate all 'out' arguments for a method signature
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i)
|
|
{
|
|
Xml::Node &arg = **ao;
|
|
string arg_object = arg.get("object");
|
|
|
|
// generate basic signature only if no object name available...
|
|
if (!arg_object.length())
|
|
{
|
|
body << signature_to_type(arg.get("type")) << "&";
|
|
}
|
|
// ...or generate object style if available
|
|
else
|
|
{
|
|
body << arg_object << "& ";
|
|
|
|
// store a object name to later generate header includes
|
|
include_vector.push_back (arg_object);
|
|
}
|
|
|
|
string arg_name = arg.get("name");
|
|
if (arg_name.length())
|
|
body << " " << arg_name;
|
|
else
|
|
body << " argout" << i;
|
|
|
|
if (i+1 != args_out.size())
|
|
body << ", ";
|
|
}
|
|
}
|
|
body << ")" << endl;
|
|
|
|
body << tab << "{" << endl
|
|
<< tab << tab << "::DBus::CallMessage call;" << endl;
|
|
|
|
if (args_in.size() > 0)
|
|
{
|
|
body << tab << tab << "::DBus::MessageIter wi = call.writer();" << endl
|
|
<< endl;
|
|
}
|
|
|
|
// generate all 'in' arguments for a method body
|
|
unsigned int j = 0;
|
|
for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++j)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
string arg_name = arg.get("name");
|
|
string arg_object = arg.get("object");
|
|
|
|
if (!arg_name.length())
|
|
{
|
|
arg_name = "argin" + j;
|
|
}
|
|
|
|
// generate extra code to wrap object
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << signature_to_type(arg.get("type")) << "_" << arg_name << ";" << endl;
|
|
body << tab << tab << "_" << arg_name << " << " << arg_name << ";" << endl;
|
|
|
|
arg_name = string ("_") + arg_name;
|
|
}
|
|
|
|
body << tab << tab << "wi << " << arg_name << ";" << endl;
|
|
}
|
|
|
|
body << tab << tab << "call.member(\"" << method.get("name") << "\");" << endl;
|
|
|
|
// generate noreply method calls
|
|
unsigned int k = 0;
|
|
string invoke_method = "::DBus::Message ret = invoke_method";
|
|
for (Xml::Nodes::iterator an = annotations_noreply.begin(); an != annotations_noreply.end(); ++an, ++k)
|
|
{
|
|
Xml::Node &annotation = **an;
|
|
string annotation_value = annotation.get("value");
|
|
|
|
if (annotation_value == "yes")
|
|
{
|
|
if (args_out.size ())
|
|
{
|
|
cerr << "Function: " << method.get("name") << ":" << endl;
|
|
cerr << "Option' org.freedesktop.DBus.NoReply' not allowed for methods with 'out' variables!" << endl << "-> Option ignored!" << endl;
|
|
}
|
|
else
|
|
{
|
|
invoke_method = "invoke_method_noreply";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
body << tab << tab << invoke_method << "(call);" << endl;
|
|
|
|
|
|
if (args_out.size() > 0)
|
|
{
|
|
body << tab << tab << "::DBus::MessageIter ri = ret.reader();" << endl
|
|
<< endl;
|
|
}
|
|
|
|
// generate 'out' value as return if only one existing
|
|
if (args_out.size() == 1)
|
|
{
|
|
string arg_object = args_out.front()->get("object");
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << arg_object << " _argout;" << endl;
|
|
}
|
|
|
|
body << tab << tab << signature_to_type(args_out.front()->get("type")) << " argout;" << endl;
|
|
|
|
body << tab << tab << "ri >> argout;" << endl;
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << "_argout << argout;" << endl;
|
|
body << tab << tab << "return _argout;" << endl;
|
|
}
|
|
else
|
|
{
|
|
body << tab << tab << "return argout;" << endl;
|
|
}
|
|
}
|
|
else if (args_out.size() > 1)
|
|
{
|
|
// generate multible 'out' value
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i)
|
|
{
|
|
Xml::Node &arg = **ao;
|
|
|
|
string arg_name = arg.get("name");
|
|
string arg_object = arg.get("object");
|
|
|
|
if (!arg_name.length())
|
|
{
|
|
arg_name = "argout" + i;
|
|
}
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << signature_to_type(arg.get("type")) << "_" << arg_name << ";" << endl;
|
|
}
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << "ri >> " << "_" << arg_name << ";" << endl;
|
|
}
|
|
else
|
|
{
|
|
body << tab << tab << "ri >> " << arg_name << ";" << endl;
|
|
}
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << arg_name << " << " << "_" << arg_name << ";" << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
body << tab << "}" << endl
|
|
<< endl;
|
|
}
|
|
|
|
// write public block header for signals
|
|
body << endl
|
|
<< "public:" << endl
|
|
<< endl
|
|
<< tab << "/* signal handlers for this interface" << endl
|
|
<< tab << " */" << endl;
|
|
|
|
// this loop generates all signals
|
|
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
|
|
{
|
|
Xml::Node &signal = **si;
|
|
Xml::Nodes args = signal["arg"];
|
|
|
|
body << tab << "virtual void " << signal.get("name") << "(";
|
|
|
|
// this loop generates all argument for a signal
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
|
|
string arg_object = arg.get("object");
|
|
|
|
// generate basic signature only if no object name available...
|
|
if (!arg_object.length())
|
|
{
|
|
body << "const " << signature_to_type(arg.get("type")) << "& ";
|
|
}
|
|
// ...or generate object style if available
|
|
else
|
|
{
|
|
body << "const " << arg_object << "& ";
|
|
|
|
// store a object name to later generate header includes
|
|
include_vector.push_back (arg_object);
|
|
}
|
|
|
|
string arg_name = arg.get("name");
|
|
if (arg_name.length())
|
|
body << arg_name;
|
|
else
|
|
body << "argin" << i;
|
|
|
|
if ((ai+1 != args.end()))
|
|
body << ", ";
|
|
}
|
|
body << ") = 0;" << endl;
|
|
}
|
|
|
|
// write private block header for unmarshalers
|
|
body << endl
|
|
<< "private:" << endl
|
|
<< endl
|
|
<< tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl
|
|
<< tab << " */" << endl;
|
|
|
|
// generate all the unmarshalers
|
|
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
|
|
{
|
|
Xml::Node &signal = **si;
|
|
Xml::Nodes args = signal["arg"];
|
|
|
|
body << tab << "void " << stub_name(signal.get("name")) << "(const ::DBus::SignalMessage &sig)" << endl
|
|
<< tab << "{" << endl;
|
|
|
|
if (args.size() > 0)
|
|
{
|
|
body << tab << tab << "::DBus::MessageIter ri = sig.reader();" << endl
|
|
<< endl;
|
|
}
|
|
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
body << tab << tab << signature_to_type(arg.get("type")) << " " ;
|
|
|
|
string arg_name = arg.get("name");
|
|
|
|
string arg_object = arg.get("object");
|
|
|
|
// use a default if no arg name given
|
|
if (!arg_name.length())
|
|
{
|
|
arg_name = "arg";
|
|
}
|
|
|
|
body << arg_name << ";" << endl;
|
|
body << tab << tab << "ri >> " << arg_name << ";" << endl;
|
|
|
|
// if a object type is used create a local variable and insert values with '<<' operation
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << arg_object << " _" << arg_name << ";" << endl;
|
|
body << tab << tab << "_" << arg_name << " << " << arg_name << ";" << endl;
|
|
}
|
|
}
|
|
|
|
body << tab << tab << signal.get("name") << "(";
|
|
|
|
// generate all arguments for the call to the virtual function
|
|
unsigned int j = 0;
|
|
for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++j)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
|
|
string arg_name = arg.get("name");
|
|
string arg_object = arg.get("object");
|
|
|
|
if (!arg_name.length())
|
|
{
|
|
arg_name = "arg" + j;
|
|
}
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << "_" << arg_name;
|
|
}
|
|
else
|
|
{
|
|
body << arg_name;
|
|
}
|
|
|
|
if (ai+1 != args.end())
|
|
body << ", ";
|
|
}
|
|
|
|
body << ");" << endl;
|
|
|
|
body << tab << "}" << endl;
|
|
}
|
|
|
|
|
|
body << "};" << endl
|
|
<< endl;
|
|
|
|
for (unsigned int i = 0; i < nspaces; ++i)
|
|
{
|
|
body << "} ";
|
|
}
|
|
body << endl;
|
|
}
|
|
|
|
body << "#endif //" << cond_comp << endl;
|
|
|
|
cerr << "writing " << filename << endl;
|
|
|
|
// remove all duplicates in the header include vector
|
|
vector<string>::const_iterator vec_end_it = unique (include_vector.begin (), include_vector.end ());
|
|
|
|
for (vector<string>::const_iterator vec_it = include_vector.begin ();
|
|
vec_it != vec_end_it;
|
|
++vec_it)
|
|
{
|
|
const string &include = *vec_it;
|
|
|
|
head << "#include " << "\"" << include << ".h" << "\"" << endl;
|
|
}
|
|
head << endl;
|
|
|
|
ofstream file(filename);
|
|
if (file.bad())
|
|
{
|
|
cerr << "unable to write file " << filename << endl;
|
|
exit(-1);
|
|
}
|
|
|
|
file << head.str ();
|
|
file << body.str ();
|
|
|
|
file.close();
|
|
}
|
|
|
|
/*! Generate adaptor code for a XML introspection
|
|
*/
|
|
void generate_adaptor(Xml::Document &doc, const char *filename)
|
|
{
|
|
ostringstream body;
|
|
ostringstream head;
|
|
vector <string> include_vector;
|
|
|
|
head << header;
|
|
string filestring = filename;
|
|
underscorize(filestring);
|
|
|
|
string cond_comp = "__dbusxx__" + filestring + "__ADAPTOR_MARSHAL_H";
|
|
|
|
head << "#ifndef " << cond_comp << endl
|
|
<< "#define " << cond_comp << endl;
|
|
|
|
head << dbus_includes;
|
|
|
|
Xml::Node &root = *(doc.root);
|
|
Xml::Nodes interfaces = root["interface"];
|
|
|
|
// iterate over all interface definitions
|
|
for (Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i)
|
|
{
|
|
Xml::Node &iface = **i;
|
|
Xml::Nodes methods = iface["method"];
|
|
Xml::Nodes signals = iface["signal"];
|
|
Xml::Nodes properties = iface["property"];
|
|
Xml::Nodes ms;
|
|
ms.insert(ms.end(), methods.begin(), methods.end());
|
|
ms.insert(ms.end(), signals.begin(), signals.end());
|
|
|
|
// gets the name of a interface: <interface name="XYZ">
|
|
string ifacename = iface.get("name");
|
|
|
|
// these interface names are skipped. Not sure why...
|
|
if (ifacename == "org.freedesktop.DBus.Introspectable"
|
|
||ifacename == "org.freedesktop.DBus.Properties")
|
|
{
|
|
cerr << "skipping interface " << ifacename << endl;
|
|
continue;
|
|
}
|
|
|
|
istringstream ss(ifacename);
|
|
string nspace;
|
|
unsigned int nspaces = 0;
|
|
|
|
// prints all the namespaces defined with <interface name="X.Y.Z">
|
|
while (ss.str().find('.', ss.tellg()) != string::npos)
|
|
{
|
|
getline(ss, nspace, '.');
|
|
|
|
body << "namespace " << nspace << " {" << endl;
|
|
|
|
++nspaces;
|
|
}
|
|
body << endl;
|
|
|
|
string ifaceclass;
|
|
|
|
getline(ss, ifaceclass);
|
|
|
|
// a "_adaptor" is added to class name to distinguish between proxy and adaptor
|
|
ifaceclass += "_adaptor";
|
|
|
|
cerr << "generating code for interface " << ifacename << "..." << endl;
|
|
|
|
// the code from class definiton up to opening of the constructor is generated...
|
|
body << "class " << ifaceclass << endl
|
|
<< ": public ::DBus::InterfaceAdaptor" << endl
|
|
<< "{" << endl
|
|
<< "public:" << endl
|
|
<< endl
|
|
<< tab << ifaceclass << "()" << endl
|
|
<< tab << ": ::DBus::InterfaceAdaptor(\"" << ifacename << "\")" << endl
|
|
<< tab << "{" << endl;
|
|
|
|
// generates code to bind the properties
|
|
for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi)
|
|
{
|
|
Xml::Node &property = **pi;
|
|
|
|
body << tab << tab << "bind_property("
|
|
<< property.get("name") << ", "
|
|
<< "\"" << property.get("type") << "\", "
|
|
<< (property.get("access").find("read") != string::npos
|
|
? "true"
|
|
: "false")
|
|
<< ", "
|
|
<< (property.get("access").find("write") != string::npos
|
|
? "true"
|
|
: "false")
|
|
<< ");" << endl;
|
|
}
|
|
|
|
// generate code to register all methods
|
|
for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi)
|
|
{
|
|
Xml::Node &method = **mi;
|
|
|
|
body << tab << tab << "register_method("
|
|
<< ifaceclass << ", " << method.get("name") << ", "<< stub_name(method.get("name"))
|
|
<< ");" << endl;
|
|
}
|
|
|
|
body << tab << "}" << endl
|
|
<< endl;
|
|
|
|
body << tab << "::DBus::IntrospectedInterface *const introspect() const " << endl
|
|
<< tab << "{" << endl;
|
|
|
|
// generate the introspect arguments
|
|
for (Xml::Nodes::iterator mi = ms.begin(); mi != ms.end(); ++mi)
|
|
{
|
|
Xml::Node &method = **mi;
|
|
Xml::Nodes args = method["arg"];
|
|
|
|
body << tab << tab << "static ::DBus::IntrospectedArgument " << method.get("name") << "_args[] = " << endl
|
|
<< tab << tab << "{" << endl;
|
|
|
|
for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
|
|
body << tab << tab << tab << "{ ";
|
|
|
|
if (arg.get("name").length())
|
|
{
|
|
body << "\"" << arg.get("name") << "\", ";
|
|
}
|
|
else
|
|
{
|
|
body << "0, ";
|
|
}
|
|
body << "\"" << arg.get("type") << "\", "
|
|
<< (arg.get("direction") == "in" ? "true" : "false")
|
|
<< " }," << endl;
|
|
}
|
|
body << tab << tab << tab << "{ 0, 0, 0 }" << endl
|
|
<< tab << tab << "};" << endl;
|
|
}
|
|
|
|
body << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_methods[] = " << endl
|
|
<< tab << tab << "{" << endl;
|
|
|
|
// generate the introspect methods
|
|
for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi)
|
|
{
|
|
Xml::Node &method = **mi;
|
|
|
|
body << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl;
|
|
}
|
|
|
|
body << tab << tab << tab << "{ 0, 0 }" << endl
|
|
<< tab << tab << "};" << endl;
|
|
|
|
body << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_signals[] = " << endl
|
|
<< tab << tab << "{" << endl;
|
|
|
|
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
|
|
{
|
|
Xml::Node &method = **si;
|
|
|
|
body << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl;
|
|
}
|
|
|
|
body << tab << tab << tab << "{ 0, 0 }" << endl
|
|
<< tab << tab << "};" << endl;
|
|
|
|
body << tab << tab << "static ::DBus::IntrospectedProperty " << ifaceclass << "_properties[] = " << endl
|
|
<< tab << tab << "{" << endl;
|
|
|
|
for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi)
|
|
{
|
|
Xml::Node &property = **pi;
|
|
|
|
body << tab << tab << tab << "{ "
|
|
<< "\"" << property.get("name") << "\", "
|
|
<< "\"" << property.get("type") << "\", "
|
|
<< (property.get("access").find("read") != string::npos
|
|
? "true"
|
|
: "false")
|
|
<< ", "
|
|
<< (property.get("access").find("write") != string::npos
|
|
? "true"
|
|
: "false")
|
|
<< " }," << endl;
|
|
}
|
|
|
|
|
|
body << tab << tab << tab << "{ 0, 0, 0, 0 }" << endl
|
|
<< tab << tab << "};" << endl;
|
|
|
|
// generate the Introspected interface
|
|
body << tab << tab << "static ::DBus::IntrospectedInterface " << ifaceclass << "_interface = " << endl
|
|
<< tab << tab << "{" << endl
|
|
<< tab << tab << tab << "\"" << ifacename << "\"," << endl
|
|
<< tab << tab << tab << ifaceclass << "_methods," << endl
|
|
<< tab << tab << tab << ifaceclass << "_signals," << endl
|
|
<< tab << tab << tab << ifaceclass << "_properties" << endl
|
|
<< tab << tab << "};" << endl
|
|
<< tab << tab << "return &" << ifaceclass << "_interface;" << endl
|
|
<< tab << "}" << endl
|
|
<< endl;
|
|
|
|
body << "public:" << endl
|
|
<< endl
|
|
<< tab << "/* properties exposed by this interface, use" << endl
|
|
<< tab << " * property() and property(value) to get and set a particular property" << endl
|
|
<< tab << " */" << endl;
|
|
|
|
// generate the properties code
|
|
for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi)
|
|
{
|
|
Xml::Node &property = **pi;
|
|
string name = property.get("name");
|
|
string type = property.get("type");
|
|
string type_name = signature_to_type(type);
|
|
|
|
body << tab << "::DBus::PropertyAdaptor< " << type_name << " > " << name << ";" << endl;
|
|
}
|
|
|
|
body << endl;
|
|
|
|
body << "public:" << endl
|
|
<< endl
|
|
<< tab << "/* methods exported by this interface," << endl
|
|
<< tab << " * you will have to implement them in your ObjectAdaptor" << endl
|
|
<< tab << " */" << endl;
|
|
|
|
// generate the methods code
|
|
for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi)
|
|
{
|
|
Xml::Node &method = **mi;
|
|
Xml::Nodes args = method["arg"];
|
|
Xml::Nodes args_in = args.select("direction","in");
|
|
Xml::Nodes args_out = args.select("direction","out");
|
|
string arg_object;
|
|
|
|
if (args_out.size() > 0)
|
|
{
|
|
arg_object = args_out.front()->get("object");
|
|
}
|
|
|
|
body << tab << "virtual ";
|
|
|
|
// return type is 'void' if none or multible return values
|
|
if (args_out.size() == 0 || args_out.size() > 1)
|
|
{
|
|
body << "void ";
|
|
}
|
|
else if (args_out.size() == 1)
|
|
{
|
|
// generate basic or object return type
|
|
if (arg_object.length())
|
|
{
|
|
body << arg_object << " ";
|
|
}
|
|
else
|
|
{
|
|
body << signature_to_type(args_out.front()->get("type")) << " ";
|
|
}
|
|
}
|
|
|
|
// generate the method name
|
|
body << method.get("name") << "(";
|
|
|
|
|
|
// generate the methods 'in' variables
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
string arg_object = arg.get("object");
|
|
|
|
// generate basic signature only if no object name available...
|
|
if (!arg_object.length())
|
|
{
|
|
body << "const " << signature_to_type(arg.get("type")) << "& ";
|
|
}
|
|
// ...or generate object style if available
|
|
else
|
|
{
|
|
body << "const " << arg_object << "& ";
|
|
|
|
// store a object name to later generate header includes
|
|
include_vector.push_back (arg_object);
|
|
}
|
|
|
|
string arg_name = arg.get("name");
|
|
if (arg_name.length())
|
|
body << arg_name;
|
|
|
|
if ((i+1 != args_in.size() || args_out.size() > 1))
|
|
body << ", ";
|
|
}
|
|
|
|
// generate the method 'out' variables if multibe 'out' values exist
|
|
if (args_out.size() > 1)
|
|
{
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i)
|
|
{
|
|
Xml::Node &arg = **ao;
|
|
string arg_object = arg.get("object");
|
|
|
|
// generate basic signature only if no object name available...
|
|
if (!arg_object.length())
|
|
{
|
|
body << "const " << signature_to_type(arg.get("type")) << "& ";
|
|
}
|
|
// ...or generate object style if available
|
|
else
|
|
{
|
|
body << "const " << arg_object << "& ";
|
|
|
|
// store a object name to later generate header includes
|
|
include_vector.push_back (arg_object);
|
|
}
|
|
|
|
string arg_name = arg.get("name");
|
|
if (arg_name.length())
|
|
body << " " << arg_name;
|
|
|
|
if (i+1 != args_out.size())
|
|
body << ", ";
|
|
}
|
|
}
|
|
body << ") = 0;" << endl;
|
|
}
|
|
|
|
body << endl
|
|
<< "public:" << endl
|
|
<< endl
|
|
<< tab << "/* signal emitters for this interface" << endl
|
|
<< tab << " */" << endl;
|
|
|
|
// generate the signals code
|
|
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
|
|
{
|
|
Xml::Node &signal = **si;
|
|
Xml::Nodes args = signal["arg"];
|
|
|
|
body << tab << "void " << signal.get("name") << "(";
|
|
|
|
// generate the signal arguments
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i)
|
|
{
|
|
Xml::Node &arg = **a;
|
|
string arg_object = arg.get("object");
|
|
|
|
// generate basic signature only if no object name available...
|
|
if (!arg_object.length())
|
|
{
|
|
body << "const " << signature_to_type(arg.get("type")) << "& arg" << i+1;
|
|
}
|
|
// ...or generate object style if available
|
|
else
|
|
{
|
|
body << "const " << arg_object << "& arg" << i+1;
|
|
|
|
// store a object name to later generate header includes
|
|
include_vector.push_back (arg_object);
|
|
}
|
|
|
|
if (i+1 != args.size())
|
|
body << ", ";
|
|
}
|
|
|
|
body << ")" << endl
|
|
<< tab << "{" << endl
|
|
<< tab << tab << "::DBus::SignalMessage sig(\"" << signal.get("name") <<"\");" << endl;
|
|
|
|
|
|
if (args.size() > 0)
|
|
{
|
|
body << tab << tab << "::DBus::MessageIter wi = sig.writer();" << endl;
|
|
|
|
unsigned int i = 0;
|
|
for (Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i)
|
|
{
|
|
Xml::Node &arg = **a;
|
|
string arg_object = arg.get("object");
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << signature_to_type(arg.get("type")) << " _arg" << i+1 << ";" << endl;
|
|
body << tab << tab << "_arg" << i+1 << " << " << "arg" << i+1 << ";" << endl;
|
|
|
|
body << tab << tab << "wi << _arg" << i+1 << ";" << endl;
|
|
}
|
|
else
|
|
{
|
|
body << tab << tab << "wi << arg" << i+1 << ";" << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
// emit the signal in method body
|
|
body << tab << tab << "emit_signal(sig);" << endl
|
|
<< tab << "}" << endl;
|
|
}
|
|
|
|
body << endl
|
|
<< "private:" << endl
|
|
<< endl
|
|
<< tab << "/* unmarshalers (to unpack the DBus message before calling the actual interface method)" << endl
|
|
<< tab << " */" << endl;
|
|
|
|
// generate the unmarshalers
|
|
for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi)
|
|
{
|
|
Xml::Node &method = **mi;
|
|
Xml::Nodes args = method["arg"];
|
|
Xml::Nodes args_in = args.select("direction","in");
|
|
Xml::Nodes args_out = args.select("direction","out");
|
|
|
|
body << tab << "::DBus::Message " << stub_name(method.get("name")) << "(const ::DBus::CallMessage &call)" << endl
|
|
<< tab << "{" << endl
|
|
<< tab << tab << "::DBus::MessageIter ri = call.reader();" << endl
|
|
<< endl;
|
|
|
|
// generate the 'in' variables
|
|
unsigned int i = 1;
|
|
for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
string arg_object = arg.get("object");
|
|
|
|
body << tab << tab << signature_to_type(arg.get("type")) << " argin" << i << ";" << endl;
|
|
body << tab << tab << " ri >> argin" << i << ";" << endl;
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << arg_object << " _argin" << i << ";" << endl;
|
|
}
|
|
}
|
|
|
|
// generate out variables
|
|
if (args_out.size() == 0)
|
|
{
|
|
body << tab << tab;
|
|
}
|
|
// if only one out argument exists
|
|
// TODO: is this needed? Should be same as else condition...
|
|
/*else if (args_out.size() == 1)
|
|
{
|
|
body << tab << tab << signature_to_type(args_out.front()->get("type")) << " argout1 = ";
|
|
}*/
|
|
else
|
|
{
|
|
unsigned int i = 1;
|
|
for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i)
|
|
{
|
|
Xml::Node &arg = **ao;
|
|
string arg_object = arg.get("object");
|
|
|
|
body << tab << tab << signature_to_type(arg.get("type")) << " argout" << i << ";" << endl;
|
|
|
|
// generate object types
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << arg_object << " _argout" << i << ";" << endl;
|
|
}
|
|
}
|
|
//body << tab << tab;
|
|
}
|
|
|
|
// generate in '<<' operation
|
|
i = 0;
|
|
for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
string arg_object = arg.get("object");
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << "_argin" << i+1 << " << " << "argin" << i+1 << ";" << endl;
|
|
}
|
|
}
|
|
|
|
body << tab << tab << method.get("name") << "(";
|
|
|
|
// generate call stub parameters
|
|
i = 0;
|
|
for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i)
|
|
{
|
|
Xml::Node &arg = **ai;
|
|
string arg_object = arg.get("object");
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << "_argin" << i+1;
|
|
}
|
|
else
|
|
{
|
|
body << "argin" << i+1;
|
|
}
|
|
|
|
if ((i+1 != args_in.size() || args_out.size() > 1))
|
|
body << ", ";
|
|
}
|
|
|
|
if (args_out.size() > 1)
|
|
{
|
|
i = 0;
|
|
for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i)
|
|
{
|
|
Xml::Node &arg = **ao;
|
|
string arg_object = arg.get("object");
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << "_argout" << i+1;
|
|
}
|
|
else
|
|
{
|
|
body << "argout" << i+1;
|
|
}
|
|
|
|
if (i+1 != args_out.size())
|
|
body << ", ";
|
|
}
|
|
}
|
|
|
|
body << ");" << endl;
|
|
|
|
body << tab << tab << "::DBus::ReturnMessage reply(call);" << endl;
|
|
|
|
if (args_out.size() > 0)
|
|
{
|
|
body << tab << tab << "::DBus::MessageIter wi = reply.writer();" << endl;
|
|
|
|
// generate out '<<' operation
|
|
i = 0;
|
|
for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i)
|
|
{
|
|
Xml::Node &arg = **ao;
|
|
string arg_object = arg.get("object");
|
|
|
|
if (arg_object.length())
|
|
{
|
|
body << tab << tab << "argout" << i+1 << " << " << "_argout" << i+1 << ";" << endl;
|
|
}
|
|
}
|
|
|
|
for (unsigned int i = 0; i < args_out.size(); ++i)
|
|
{
|
|
body << tab << tab << "wi << argout" << i+1 << ";" << endl;
|
|
}
|
|
}
|
|
|
|
body << tab << tab << "return reply;" << endl;
|
|
|
|
body << tab << "}" << endl;
|
|
}
|
|
|
|
body << "};" << endl
|
|
<< endl;
|
|
|
|
for (unsigned int i = 0; i < nspaces; ++i)
|
|
{
|
|
body << "} ";
|
|
}
|
|
body << endl;
|
|
}
|
|
|
|
body << "#endif //" << cond_comp << endl;
|
|
|
|
// remove all duplicates in the header include vector
|
|
vector<string>::const_iterator vec_end_it = unique (include_vector.begin (), include_vector.end ());
|
|
|
|
for (vector<string>::const_iterator vec_it = include_vector.begin ();
|
|
vec_it != vec_end_it;
|
|
++vec_it)
|
|
{
|
|
const string &include = *vec_it;
|
|
|
|
head << "#include " << "\"" << include << ".h" << "\"" << endl;
|
|
}
|
|
head << endl;
|
|
|
|
ofstream file(filename);
|
|
if (file.bad())
|
|
{
|
|
cerr << "unable to write file " << filename << endl;
|
|
exit(-1);
|
|
}
|
|
|
|
file << head.str ();
|
|
file << body.str ();
|
|
|
|
file.close();
|
|
}
|
|
|
|
int main(int argc, char ** argv)
|
|
{
|
|
if (argc < 2)
|
|
{
|
|
usage(argv[0]);
|
|
}
|
|
|
|
bool proxy_mode, adaptor_mode;
|
|
char *proxy, *adaptor;
|
|
|
|
proxy_mode = false;
|
|
proxy = 0;
|
|
|
|
adaptor_mode = false;
|
|
adaptor = 0;
|
|
|
|
for (int a = 1; a < argc; ++a)
|
|
{
|
|
if (!strncmp(argv[a], "--proxy=", 8))
|
|
{
|
|
proxy_mode = true;
|
|
proxy = argv[a] +8;
|
|
}
|
|
else
|
|
if (!strncmp(argv[a], "--adaptor=", 10))
|
|
{
|
|
adaptor_mode = true;
|
|
adaptor = argv[a] +10;
|
|
}
|
|
}
|
|
|
|
if (!proxy_mode && !adaptor_mode) usage(argv[0]);
|
|
|
|
ifstream xmlfile(argv[1]);
|
|
|
|
if (xmlfile.bad())
|
|
{
|
|
cerr << "unable to open file " << argv[1] << endl;
|
|
return -1;
|
|
}
|
|
|
|
Xml::Document doc;
|
|
|
|
try
|
|
{
|
|
xmlfile >> doc;
|
|
//cout << doc.to_xml();
|
|
}
|
|
catch(Xml::Error &e)
|
|
{
|
|
cerr << "error parsing " << argv[1] << ": " << e.what() << endl;
|
|
return -1;
|
|
}
|
|
|
|
if (!doc.root)
|
|
{
|
|
cerr << "empty document" << endl;
|
|
return -1;
|
|
}
|
|
|
|
if (proxy_mode) generate_proxy(doc, proxy);
|
|
if (adaptor_mode) generate_adaptor(doc, adaptor);
|
|
|
|
return 0;
|
|
}
|