/* * * D-Bus++ - C++ bindings for D-Bus * * Copyright (C) 2005-2007 Paolo Durante * * * 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 #include #include #include #include #include #include #include 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 \n\ \n\ "; typedef map TypeCache; void usage(const char *argv0) { cerr << endl << "Usage: " << argv0 << " [ --proxy= ] [ --adaptor= ]" << 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; } void generate_proxy(Xml::Document &doc, const char *filename) { cerr << "writing " << filename << endl; ofstream file(filename); if (file.bad()) { cerr << "unable to write file " << filename << endl; exit(-1); } file << header; string filestring = filename; underscorize(filestring); string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H"; file << "#ifndef " << cond_comp << endl; file << "#define " << cond_comp << endl; file << dbus_includes; Xml::Node &root = *(doc.root); Xml::Nodes interfaces = root["interface"]; 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()); string ifacename = iface.get("name"); 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; while (ss.str().find('.', ss.tellg()) != string::npos) { getline(ss, nspace, '.'); file << "namespace " << nspace << " {" << endl; ++nspaces; } file << endl; string ifaceclass; getline(ss, ifaceclass); cerr << "generating code for interface " << ifacename << "..." << endl; file << "class " << ifaceclass << endl << " : public ::DBus::InterfaceProxy" << endl << "{" << endl << "public:" << endl << endl << tab << ifaceclass << "()" << endl << tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << endl << tab << "{" << endl; for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) { Xml::Node &signal = **si; string marshname = "_" + signal.get("name") + "_stub"; file << tab << tab << "connect_signal(" << ifaceclass << ", " << signal.get("name") << ", " << stub_name(signal.get("name")) << ");" << endl; } file << tab << "}" << endl << endl; /// write properties file << "public:" << endl << endl << tab << "/* properties exported by this interface */" << endl; 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") { file << tab << tab << "const " << signature_to_type (property.get("type")) << " " << prop_name << "() {" << endl; file << tab << tab << tab << "::DBus::CallMessage call ;\n "; file << tab << tab << tab << "call.member(\"Get\"); call.interface(\"org.freedesktop.DBus.Properties\");" << endl; file << tab << tab << tab << "::DBus::MessageIter wi = call.writer(); " << endl; file << tab << tab << tab << "const DBus::String interface_name = \"" << ifacename << "\";" << endl; file << tab << tab << tab << "const DBus::String property_name = \"" << prop_name << "\";" << endl; file << tab << tab << tab << "wi << interface_name;" << endl; file << tab << tab << tab << "wi << property_name;" << endl; file << tab << tab << tab << "::DBus::Message ret = this->invoke_method (call);" << endl; file << tab << tab << tab << "::DBus::MessageIter ri = ret.reader ();" << endl; file << tab << tab << tab << "::DBus::Variant argout; " << endl; file << tab << tab << tab << "ri >> argout;" << endl; file << tab << tab << tab << "return argout;" << endl; file << tab << tab << "};" << endl; } if (property_access == "write" || property_access == "readwrite") { file << tab << tab << "void " << prop_name << "( const "<< signature_to_type (property.get("type")) << " & input" << ") {" << endl; file << tab << tab << tab << "::DBus::CallMessage call ;\n "; file << tab << tab << tab <<"call.member(\"Set\"); call.interface( \"org.freedesktop.DBus.Properties\");"<< endl; file << tab << tab << tab <<"::DBus::MessageIter wi = call.writer(); " << endl; file << tab << tab << tab <<"DBus::Variant value;" << endl; file << tab << tab << tab <<"::DBus::MessageIter vi = value.writer ();" << endl; file << tab << tab << tab <<"vi << input;" << endl; file << tab << tab << tab <<"const DBus::String interface_name = \"" << ifacename << "\";" << endl; file << tab << tab << tab <<"const DBus::String property_name = \"" << prop_name << "\";"<< endl; file << tab << tab << tab <<"wi << interface_name;" << endl; file << tab << tab << tab <<"wi << property_name;" << endl; file << tab << tab << tab <<"wi << value;" << endl; file << tab << tab << tab <<"::DBus::Message ret = this->invoke_method (call);" << endl; file << tab << tab << "};" << endl; } } file << "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; 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"); if (args_out.size() == 0 || args_out.size() > 1) { file << tab << "void "; } else if (args_out.size() == 1) { file << tab << signature_to_type(args_out.front()->get("type")) << " "; } file << method.get("name") << "("; unsigned int i = 0; for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) { Xml::Node &arg = **ai; file << "const " << signature_to_type(arg.get("type")) << "& "; string arg_name = arg.get("name"); if (arg_name.length()) file << arg_name; else file << "argin" << i; if ((i+1 != args_in.size() || args_out.size() > 1)) file << ", "; } 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; file << signature_to_type(arg.get("type")) << "&"; string arg_name = arg.get("name"); if (arg_name.length()) file << " " << arg_name; else file << " argout" << i; if (i+1 != args_out.size()) file << ", "; } } file << ")" << endl; file << tab << "{" << endl << tab << tab << "::DBus::CallMessage call;" << endl; if (args_in.size() > 0) { file << tab << tab << "::DBus::MessageIter wi = call.writer();" << endl << endl; } 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"); if (arg_name.length()) file << tab << tab << "wi << " << arg_name << ";" << endl; else file << tab << tab << "wi << argin" << j << ";" << endl; } file << tab << tab << "call.member(\"" << method.get("name") << "\");" << endl << tab << tab << "::DBus::Message ret = invoke_method(call);" << endl; if (args_out.size() > 0) { file << tab << tab << "::DBus::MessageIter ri = ret.reader();" << endl << endl; } if (args_out.size() == 1) { file << tab << tab << signature_to_type(args_out.front()->get("type")) << " argout;" << endl; file << tab << tab << "ri >> argout;" << endl; file << tab << tab << "return argout;" << endl; } else 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_name = arg.get("name"); if (arg_name.length()) file << tab << tab << "ri >> " << arg.get("name") << ";" << endl; else file << tab << tab << "ri >> argout" << i << ";" << endl; } } file << tab << "}" << endl << endl; } file << endl << "public:" << endl << endl << tab << "/* signal handlers for this interface" << endl << tab << " */" << endl; for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) { Xml::Node &signal = **si; Xml::Nodes args = signal["arg"]; file << tab << "virtual void " << signal.get("name") << "("; unsigned int i = 0; for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) { Xml::Node &arg = **ai; file << "const " << signature_to_type(arg.get("type")) << "& "; string arg_name = arg.get("name"); if (arg_name.length()) file << arg_name; else file << "argin" << i; if ((ai+1 != args.end())) file << ", "; } file << ") = 0;" << endl; } file << endl << "private:" << endl << endl << tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl << tab << " */" << endl; for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) { Xml::Node &signal = **si; Xml::Nodes args = signal["arg"]; file << tab << "void " << stub_name(signal.get("name")) << "(const ::DBus::SignalMessage &sig)" << endl << tab << "{" << endl; if (args.size() > 0) { file << 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; file << tab << tab << signature_to_type(arg.get("type")) << " " ; string arg_name = arg.get("name"); if (arg_name.length()) file << arg_name << ";" << " ri >> " << arg_name << ";" << endl; else file << "arg" << i << ";" << " ri >> " << "arg" << i << ";" << endl; } file << tab << tab << signal.get("name") << "("; 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"); if (arg_name.length()) file << arg_name; else file << "arg" << j; if (ai+1 != args.end()) file << ", "; } file << ");" << endl; file << tab << "}" << endl; } file << "};" << endl << endl; for (unsigned int i = 0; i < nspaces; ++i) { file << "} "; } file << endl; } file << "#endif//" << cond_comp << endl; file.close(); } void generate_adaptor(Xml::Document &doc, const char *filename) { cerr << "writing " << filename << endl; ofstream file(filename); if (file.bad()) { cerr << "unable to write file " << filename << endl; exit(-1); } file << header; string filestring = filename; underscorize(filestring); string cond_comp = "__dbusxx__" + filestring + "__ADAPTOR_MARSHAL_H"; file << "#ifndef " << cond_comp << endl << "#define " << cond_comp << endl; file << dbus_includes; Xml::Node &root = *(doc.root); Xml::Nodes interfaces = root["interface"]; 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()); string ifacename = iface.get("name"); 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; while (ss.str().find('.', ss.tellg()) != string::npos) { getline(ss, nspace, '.'); file << "namespace " << nspace << " {" << endl; ++nspaces; } file << endl; string ifaceclass; getline(ss, ifaceclass); cerr << "generating code for interface " << ifacename << "..." << endl; file << "class " << ifaceclass << endl << ": public ::DBus::InterfaceAdaptor" << endl << "{" << endl << "public:" << endl << endl << tab << ifaceclass << "()" << endl << tab << ": ::DBus::InterfaceAdaptor(\"" << ifacename << "\")" << endl << tab << "{" << endl; for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) { Xml::Node &property = **pi; file << 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; } for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) { Xml::Node &method = **mi; file << tab << tab << "register_method(" << ifaceclass << ", " << method.get("name") << ", "<< stub_name(method.get("name")) << ");" << endl; } file << tab << "}" << endl << endl; file << tab << "::DBus::IntrospectedInterface *const introspect() const " << endl << tab << "{" << endl; for (Xml::Nodes::iterator mi = ms.begin(); mi != ms.end(); ++mi) { Xml::Node &method = **mi; Xml::Nodes args = method["arg"]; file << 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; file << tab << tab << tab << "{ "; if (arg.get("name").length()) { file << "\"" << arg.get("name") << "\", "; } else { file << "0, "; } file << "\"" << arg.get("type") << "\", " << (arg.get("direction") == "in" ? "true" : "false") << " }," << endl; } file << tab << tab << tab << "{ 0, 0, 0 }" << endl << tab << tab << "};" << endl; } file << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_methods[] = " << endl << tab << tab << "{" << endl; for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) { Xml::Node &method = **mi; file << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; } file << tab << tab << tab << "{ 0, 0 }" << endl << tab << tab << "};" << endl; file << 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; file << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; } file << tab << tab << tab << "{ 0, 0 }" << endl << tab << tab << "};" << endl; file << 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; file << 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; } file << tab << tab << tab << "{ 0, 0, 0, 0 }" << endl << tab << tab << "};" << endl; file << 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; file << "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; 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); file << tab << "::DBus::PropertyAdaptor< " << type_name << " > " << name << ";" << endl; } file << endl; file << "public:" << endl << endl << tab << "/* methods exported by this interface," << endl << tab << " * you will have to implement them in your ObjectAdaptor" << endl << tab << " */" << endl; 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"); file << tab << "virtual "; if (args_out.size() == 0 || args_out.size() > 1) { file << "void "; } else if (args_out.size() == 1) { file << signature_to_type(args_out.front()->get("type")) << " "; } file << method.get("name") << "("; unsigned int i = 0; for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) { Xml::Node &arg = **ai; file << "const " << signature_to_type(arg.get("type")) << "& "; string arg_name = arg.get("name"); if (arg_name.length()) file << arg_name; if ((i+1 != args_in.size() || args_out.size() > 1)) file << ", "; } 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; file << signature_to_type(arg.get("type")) << "&"; string arg_name = arg.get("name"); if (arg_name.length()) file << " " << arg_name; if (i+1 != args_out.size()) file << ", "; } } file << ") = 0;" << endl; } file << endl << "public:" << endl << endl << tab << "/* signal emitters for this interface" << endl << tab << " */" << endl; for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) { Xml::Node &signal = **si; Xml::Nodes args = signal["arg"]; file << tab << "void " << signal.get("name") << "("; unsigned int i = 0; for (Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i) { Xml::Node &arg = **a; file << "const " << signature_to_type(arg.get("type")) << "& arg" << i+1; if (i+1 != args.size()) file << ", "; } file << ")" << endl << tab << "{" << endl << tab << tab << "::DBus::SignalMessage sig(\"" << signal.get("name") <<"\");" << endl;; if (args.size() > 0) { file << tab << tab << "::DBus::MessageIter wi = sig.writer();" << endl; for (unsigned int i = 0; i < args.size(); ++i) { file << tab << tab << "wi << arg" << i+1 << ";" << endl; } } file << tab << tab << "emit_signal(sig);" << endl << tab << "}" << endl; } file << endl << "private:" << endl << endl << tab << "/* unmarshalers (to unpack the DBus message before calling the actual interface method)" << endl << tab << " */" << endl; 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"); file << tab << "::DBus::Message " << stub_name(method.get("name")) << "(const ::DBus::CallMessage &call)" << endl << tab << "{" << endl << tab << tab << "::DBus::MessageIter ri = call.reader();" << endl << endl; unsigned int i = 1; for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) { Xml::Node &arg = **ai; file << tab << tab << signature_to_type(arg.get("type")) << " argin" << i << ";" << " ri >> argin" << i << ";" << endl; } if (args_out.size() == 0) { file << tab << tab; } else if (args_out.size() == 1) { file << 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; file << tab << tab << signature_to_type(arg.get("type")) << " argout" << i << ";" << endl; } file << tab << tab; } file << method.get("name") << "("; for (unsigned int i = 0; i < args_in.size(); ++i) { file << "argin" << i+1; if ((i+1 != args_in.size() || args_out.size() > 1)) file << ", "; } if (args_out.size() > 1) for (unsigned int i = 0; i < args_out.size(); ++i) { file << "argout" << i+1; if (i+1 != args_out.size()) file << ", "; } file << ");" << endl; file << tab << tab << "::DBus::ReturnMessage reply(call);" << endl; if (args_out.size() > 0) { file << tab << tab << "::DBus::MessageIter wi = reply.writer();" << endl; for (unsigned int i = 0; i < args_out.size(); ++i) { file << tab << tab << "wi << argout" << i+1 << ";" << endl; } } file << tab << tab << "return reply;" << endl; file << tab << "}" << endl; } file << "};" << endl << endl; for (unsigned int i = 0; i < nspaces; ++i) { file << "} "; } file << endl; } file << "#endif//" << cond_comp << endl; 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; }