diff dbus-d/dsrc/org/freedesktop/dbus/tool/CreateInterface.d @ 0:a5576806d36d

recreate repository without any libs for lightweight repository
author Frank Benoit <benoit@tionex.de>
date Sat, 20 Oct 2007 18:07:18 +0200
parents
children 427c0332a111
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbus-d/dsrc/org/freedesktop/dbus/tool/CreateInterface.d	Sat Oct 20 18:07:18 2007 +0200
@@ -0,0 +1,1006 @@
+/*
+ * Copyright (C) 2007  Frank Benoit
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+module org.freedesktop.dbus.tool.CreateInterface;
+
+import tango.io.Stdout;
+import tango.io.Print;
+import tango.text.convert.Integer : toUtf8;
+import tango.text.Util : layout, split, join, replace;
+import tango.net.Uri; // make dsss and linker happy :(
+import tango.core.Exception : TracedException;
+
+import org.freedesktop.dbus.tool.XmlSupport;
+
+class TerminateException : TracedException {
+    int code;
+    this( int code ){
+        super( null );
+        this.code = code;
+    }
+}
+const char[] ID_NODE = "node";
+const char[] ID_INTF = "interface";
+const char[] ID_METH = "method";
+const char[] ID_SIGN = "signal";
+const char[] ID_PROP = "property";
+const char[] ID_ANNO = "annotation";
+const char[] ID_ARGU = "arg";
+const char[] ID_DIRECTION     = "direction";
+const char[] ID_DIRECTION_IN  = "in";
+const char[] ID_DIRECTION_OUT = "out";
+const char[] ID_TYPE          = "type";
+const char[] ANNO_RETURNS     = "org.dsource.tiolink.Returns";
+IntfTree intfTree;
+
+//-----------------------------------------
+
+private void createStdInterfaces() {
+    DefInterface intf;
+    DefMethod meth;
+    DefArgument argu;
+
+    intfTree.add( intf = new DefInterface( "org.freedesktop.DBus.Peer" ));
+    {
+        intf.addMethod( meth = new DefMethod( "Ping" ));
+        meth.complete();
+
+        intf.addMethod( meth = new DefMethod( "GetMachineId" ));
+        meth.addArgument( argu = new DefArgument( "machine_uuid", "s", DefArgument.EDir.DIR_OUT));
+        meth.addAnnotation( ANNO_RETURNS, "machine_uuid" );
+        meth.complete();
+    }
+
+    intfTree.add( intf = new DefInterface( "org.freedesktop.DBus.Introspectable" ));
+    {
+        intf.addMethod( meth = new DefMethod( "Introspect" ));
+        meth.addArgument( argu = new DefArgument( "xml_data", "s", DefArgument.EDir.DIR_OUT));
+        meth.addAnnotation( ANNO_RETURNS, "xml_data" );
+        meth.complete();
+    }
+
+    intfTree.add( intf = new DefInterface( "org.freedesktop.DBus.Properties" ));
+    {
+        intf.addMethod( meth = new DefMethod( "Get" ));
+        meth.addArgument( argu = new DefArgument( "intf_name", "s", DefArgument.EDir.DIR_IN ));
+        meth.addArgument( argu = new DefArgument( "prop_name", "s", DefArgument.EDir.DIR_IN ));
+        meth.addArgument( argu = new DefArgument( "prop"     , "v", DefArgument.EDir.DIR_OUT));
+        meth.addAnnotation( ANNO_RETURNS, "prop" );
+        meth.complete();
+
+        intf.addMethod( meth = new DefMethod( "Set" ));
+        meth.addArgument( argu = new DefArgument( "intf_name", "s", DefArgument.EDir.DIR_IN ));
+        meth.addArgument( argu = new DefArgument( "prop_name", "s", DefArgument.EDir.DIR_IN ));
+        meth.addArgument( argu = new DefArgument( "prop"     , "v", DefArgument.EDir.DIR_IN ));
+        meth.complete();
+
+        intf.addMethod( meth = new DefMethod( "GetAll" ));
+        meth.addArgument( argu = new DefArgument( "intf_name", "s"    , DefArgument.EDir.DIR_IN ));
+        meth.addArgument( argu = new DefArgument( "allprops" , "a{sv}", DefArgument.EDir.DIR_OUT));
+        meth.addAnnotation( ANNO_RETURNS, "allprops" );
+        meth.complete();
+    }
+}
+
+
+alias char[] DBusObjPath;
+alias void function() DBusHandler;
+
+struct DBusVariant{
+    byte type;
+    union{
+        byte v_byte;
+        bool v_bool;
+    }
+}
+
+
+
+class IntfTree{
+    class Node{
+        char[]       mName;
+        DefInterface mValue;
+        Node[]       mChilds;
+    }
+
+    Node mRoot;
+    char[][] allInterfaces;
+
+    public this(){
+        mRoot = new Node();
+    }
+
+    public void add( DefInterface intf ){
+        allInterfaces ~= intf.mName;
+        char[][] parts = split( intf.mName, "." );
+
+        Node findNode( char[][] names ){
+            if( names.length == 0 ){
+                return mRoot;
+            }
+            Node par = findNode( names[ 0 .. $-1 ] );
+            foreach( child; par.mChilds ){
+                if( child.mName == names[ $-1 ] ){
+                    return child;
+                }
+            }
+            auto child = new Node;
+            child.mName = names[ $-1 ].dup;
+            par.mChilds ~= child;
+            return child;
+        }
+
+        Node node = findNode( parts );
+        node.mValue = intf;
+    }
+
+    public DefInterface getInterface( char[] intfName ){
+        char[][] parts = split( intfName, "." );
+
+        Node findNode( char[][] names ){
+            if( names.length == 0 ){
+                return mRoot;
+            }
+            Node par = findNode( names[ 0 .. $-1 ] );
+            foreach( child; par.mChilds ){
+                if( child.mName == names[ $-1 ] ){
+                    return child;
+                }
+            }
+            return null;
+        }
+        Node node = findNode( parts );
+        if( node is null ){
+            return null;
+        }
+        return node.mValue;
+    }
+
+    public char[][] getChildNames( char[] parentName ){
+        char[][] parts = split( parentName, "." );
+
+        Node findNode( char[][] names ){
+            if( names.length == 0 ){
+                return mRoot;
+            }
+            Node par = findNode( names[ 0 .. $-1 ] );
+            foreach( child; par.mChilds ){
+                if( child.mName == names[ $-1 ] ){
+                    return child;
+                }
+            }
+            return null;
+        }
+        Node node = findNode( parts );
+        if( node is null ){
+            return null;
+        }
+        char[][] res;
+        foreach( idx, child; node.mChilds ){
+            char[] txt;
+            if( parentName.length > 0 ){
+                res ~= parentName ~ '.' ~ child.mName;
+            }
+            else{
+                res ~= child.mName;
+            }
+        }
+        return res;
+    }
+}
+
+class DefInterface{
+    char[]      mName;
+
+    DefMethod[]   mMethods;
+    DefSignal[]   mSignals;
+    DefProperty[] mProperties;
+    char[][ char[] ] mAnnotations;
+
+    public this( char[] aName ){
+        mName = aName.dup;
+    }
+
+    public void addMethod( DefMethod meth ){
+        mMethods ~= meth;
+    }
+
+    public void addSignal( DefSignal sign ){
+        mSignals ~= sign;
+    }
+
+    public void addProperty( DefProperty prop ){
+        mProperties ~= prop;
+    }
+
+    public void addAnnotation( char[] name, char[] value ){
+        mAnnotations[ name.dup ] = value.dup;
+    }
+}
+
+class DefSignal : ArgumentContainer {
+
+    char[]         mName;
+    DefArgument[]  mArguments;
+    char[][ char[] ] mAnnotations;
+    public this( char[] aName ){
+        mName = aName.dup;
+    }
+
+    public void addArgument( DefArgument aArg ){
+        mArguments ~= aArg;
+    }
+    public void addAnnotation( char[] name, char[] value ){
+        mAnnotations[ name.dup ] = value.dup;
+    }
+}
+
+class DefProperty {
+
+    char[]         mName;
+    public this( char[] aName ){
+        mName = aName.dup;
+    }
+
+}
+
+class DefMethod : ArgumentContainer {
+    char[]         mName;
+    DefArgument[]  mArguments;
+    char[][ char[] ] mAnnotations;
+
+    DefArgument    mDRetArgument;
+    DefArgument[]  mDArguments;
+
+    public this( char[] aName ){
+        mName = aName.dup;
+    }
+    public void addArgument( DefArgument aArg ){
+        mArguments ~= aArg;
+    }
+    public void addAnnotation( char[] name, char[] value ){
+        mAnnotations[ name.dup ] = value.dup;
+    }
+
+    public void complete(){
+        char[]* retArgName = ANNO_RETURNS in mAnnotations;
+        if( retArgName !is null ){
+            int idx = 0;
+            bool found = false;
+            foreach( arg; mArguments ){
+                if( *retArgName == arg.mName && arg.mDirection == DefArgument.EDir.DIR_OUT ){
+                    if( found ){
+                        error( "there are two or more out arguements in the same method" );
+                    }
+                    found = true;
+                    mDRetArgument = arg;
+                }
+                else{
+                    mDArguments ~= arg;
+                }
+            }
+        }
+        else{
+            mDRetArgument = null;
+            mDArguments = mArguments;
+        }
+    }
+
+
+}
+
+interface ArgumentContainer{
+    public void addArgument( DefArgument aPar );
+}
+
+class DefArgument{
+
+    enum EDir{
+        DIR_IN, DIR_OUT
+    }
+
+    EDir    mDirection;
+    char[]  mName;
+    char[]  mType;
+
+    public this( char[] aName, char[] aType, EDir aDir ){
+        mName = aName.dup;
+        mType = aType.dup;
+        mDirection = aDir;
+    }
+
+    char[] toDType(){
+        char[] rem;
+        char[] res = signatureToDType( mType, rem );
+        if( rem.length > 0 ){
+            error( "not a complete type %0 %1", mType, rem );
+        }
+        return res;
+    }
+
+    private char[] signatureToDType( char[] sigText, out char[] remainingSigText ){
+
+        remainingSigText = null;
+        if( sigText.length == 0 ){
+            return null;
+        }
+
+        remainingSigText = sigText[ 1.. $ ];
+
+        switch( sigText[0] ){
+        case 'y': return "byte";
+        case 'b': return "bool";
+        case 'n': return "short";
+        case 'q': return "ushort";
+        case 'i': return "int";
+        case 'u': return "uint";
+        case 'x': return "long";
+        case 't': return "ulong";
+        case 'd': return "double";
+        case 's': return "char[]";
+        case 'o': return "DBusObject";
+        case 'g': return "DBusSignature";
+        case 'v': return "DBusVariant";
+        default:
+            break;
+        }
+        if( sigText[0] == 'a' ){
+            if( sigText.length > 1 && sigText[ 1 ] == '{' ){
+                char[] rem;
+                char[] tkey = signatureToDType( sigText[2..$], rem );
+                char[] rem2;
+                char[] tval = signatureToDType( rem, rem2 );
+                char[] res = tval ~ "[ "~ tkey ~" ]";
+                if( rem2.length == 0 || rem2[0] != '}' ){
+                    error( "no valid closing bracket for dict Entry" );
+                }
+                remainingSigText = rem2[ 1 .. $ ];
+                return res;
+            }
+            else{
+                return signatureToDType( sigText[1..$], remainingSigText ) ~ "[]";
+            }
+        }
+        else if( sigText[0] == '(' ){
+            char[][] flds;
+            char[] rem = sigText[ 1 .. $ ];
+            do{
+                char[] rem2;
+                flds ~= signatureToDType( rem, rem2 );
+                rem = rem2;
+            }
+            while( rem.length > 0 && rem[ 0 ] != ')' );
+            remainingSigText = ( rem.length > 0  ) ? rem[ 1 .. $ ] : null;
+            return "Struct!( " ~ join( flds, ", " ) ~ " )";
+        }
+        error( "unknown type "~sigText );
+        assert(false);
+    }
+
+
+}
+
+
+
+
+
+// array Attt_ AttAtt_i_     alles bis zum abschließenden _
+// map   Mtt       zwei typen nach M
+
+// BYTE    121        (ASCII 'y') 8-bit unsigned integer
+// BOOLEAN  98        (ASCII 'b')  Boolean value, 0 is FALSE and 1 is TRUE. Everything else is invalid.
+// INT16   110        (ASCII 'n') 16-bit signed integer
+// UINT16  113        (ASCII 'q') 16-bit unsigned integer
+// INT32   105        (ASCII 'i') 32-bit signed integer
+// UINT32  117        (ASCII 'u') 32-bit unsigned integer
+// INT64   120        (ASCII 'x') 64-bit signed integer
+// UINT64  116        (ASCII 't') 64-bit unsigned integer
+// DOUBLE  100        (ASCII 'd') IEEE 754 double
+// STRING  115        (ASCII 's') UTF-8 string (must be valid UTF-8). Must be nul terminated and contain no other nul bytes.
+// OBJECT_PATH 111    (ASCII 'o') Name of an object instance
+// SIGNATURE   103    (ASCII 'g') A type signature
+// ARRAY    97        (ASCII 'a')  Array
+// STRUCT    114      (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')') Struct
+// VARIANT   118      (ASCII 'v')     Variant type (the type of the value is part of the value itself)
+// DICT_ENTRY 101     (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}')   Entry in a dict or map (array of key-value pairs)
+//            
+
+
+void parseNode( Element el ){
+
+    el.checkAllowedChilds( ID_INTF, ID_NODE );
+
+    foreach( intf; el.getChilds( ID_INTF )){
+        auto defIntf = parseInterface( intf );
+        intfTree.add( defIntf );
+    }
+    foreach( node; el.getChilds( ID_NODE )){
+        parseNode( node );
+    }     
+}
+
+void unknownElement( char[][] msg ... ){
+    char[200] buf;
+    Stderr( layout( buf, msg ) ).newline;
+}
+
+DefInterface parseInterface( Element intf ){
+
+    char[] elname = intf.getAttribute( "name" );
+    auto defIntf = new DefInterface( elname );
+
+    foreach( child; intf.getChilds() ){
+        switch( child.getName() ){
+        case ID_METH:
+            defIntf.addMethod( parseMethod( child ));
+            break;
+        case ID_SIGN:
+            defIntf.addSignal( parseSignal( child ));
+            break;
+        case ID_PROP:
+            defIntf.addProperty( parseProperty( child ));
+            break;
+        case ID_ANNO:
+            char[] name = child.getAttribute( "name" );
+            char[] value = child.getAttribute( "value" );
+            defIntf.addAnnotation( name, value );
+            break;
+        default:
+            unknownElement( "Warning: found unknown nodetype %0 in interface", child.getName() );
+            break;
+        }
+    }
+    return defIntf;
+}
+
+DefMethod parseMethod( Element meth ){
+
+    char[] methName = meth.getAttribute( "name" );
+    auto defMeth = new DefMethod( methName );
+
+    foreach( child; meth.getChilds() ){
+        switch( child.getName() ){
+        case ID_ARGU:
+            defMeth.addArgument( parseArgument( child, true ));
+            break;
+        case ID_ANNO:
+            char[] name = child.getAttribute( "name" );
+            char[] value = child.getAttribute( "value" );
+            defMeth.addAnnotation( name, value );
+            break;
+        default:
+            unknownElement( "Warning: found unknown nodetype %0 in interface", child.getName() );
+            break;
+        }
+    }
+    defMeth.complete();
+    return defMeth;
+}
+
+DefSignal parseSignal( Element sign ){
+    char[] name = sign.getAttribute( "name" );
+    auto defSign = new DefSignal( name );
+    foreach( child; sign.getChilds() ){
+        switch( child.getName() ){
+        case ID_ARGU:
+            defSign.addArgument( parseArgument( child, false ));
+            break;
+        case ID_ANNO:
+            char[] annoName = child.getAttribute( "name" );
+            char[] annoValue = child.getAttribute( "value" );
+            defSign.addAnnotation( annoName, annoValue );
+            break;
+        default:
+            unknownElement( "Warning: found unknown nodetype %0 in interface", child.getName() );
+            break;
+        }
+    }
+    return defSign;
+}
+DefProperty parseProperty( Element prop ){
+    char[] name = prop.getAttribute( "name" );
+    auto res = new DefProperty( name );
+    return res;
+}
+
+
+DefArgument parseArgument( Element arg, bool dirDefIn ){
+    char[] name = arg.getAttribute( "name" );
+    DefArgument.EDir dir = dirDefIn ? DefArgument.EDir.DIR_IN : DefArgument.EDir.DIR_OUT;
+    if( arg.hasAttribute( ID_DIRECTION )){
+        char[] dirtxt = arg.getAttribute( ID_DIRECTION );
+        switch( dirtxt ){
+        case ID_DIRECTION_OUT:
+            dir = DefArgument.EDir.DIR_OUT;
+            break;
+        case ID_DIRECTION_IN:
+            dir = DefArgument.EDir.DIR_IN;
+            break;
+        default:
+            unknownElement( "Warning: direction attribute has unknown value %0", dirtxt );
+            break;
+        }
+    }
+    char[] typetxt = arg.getAttribute( ID_TYPE );
+    auto res = new DefArgument( name, typetxt, dir );
+    return res;
+}
+
+char[] getIndent( int indent ){
+    static char[] spaces = "                                                                                   ";
+    int count = indent*4;
+    assert( count >= 0 );
+    assert( count < spaces.length );
+    return spaces[0..count];
+}
+
+//char[][ char[] ] introspection = [ `sdklf`:`ldkfj`];
+
+void writeIntrospectionData( Print!(char) p ){
+    char[200] buf;
+    char[] getArgIntrospectionData( DefArgument arg ){
+        char[] res = `    <arg `;
+        res ~= layout( buf, ` name=\"%0\"`, arg.mName ).dup;
+        res ~= layout( buf, ` type=\"%0\"`, arg.mType ).dup;
+        res ~= layout( buf, ` direction=\"%0\"`, arg.mDirection == DefArgument.EDir.DIR_IN ? ID_DIRECTION_IN : ID_DIRECTION_OUT ).dup;
+        res ~= ` />\\n`;
+        return res;
+    }
+    char[] getAnnotationIntrospectionData( char[] name, char[] value, int indent ){
+        return layout( buf, `%2<annotation name=\"%0\" value=\"%1\" />\\n`, name, value, getIndent( indent ) ).dup;
+    }
+    char[][] getMethodIntrospectionData( DefMethod meth ){
+        char[][] res;
+        res ~= layout( buf, `  <method name=\"%0\">\\n`, meth.mName ).dup;
+        foreach( key, value ; meth.mAnnotations ){
+            res ~= getAnnotationIntrospectionData( key, value, 2 );
+        }
+        foreach( argu ; meth.mArguments ){
+            res ~= getArgIntrospectionData( argu );
+        }
+        res ~= `  </method>\\n`.dup;
+        return res;
+    }
+    char[][] getIntrospectionData( DefInterface intf ){
+        char[][] res;
+        res ~= layout( buf, `<interface name=\"%0\">\\n`, intf.mName ).dup;
+        foreach( meth; intf.mMethods ){
+            res ~= getMethodIntrospectionData( meth );
+        }
+        res ~= `</interface>\\n`.dup;
+        return res;
+    }
+    p.formatln( "private void init_introspectionData(){{" );
+    foreach( intfIdx, intf; intfTree.allInterfaces ){
+        p.formatln( "    registerIntrospectionData(" );
+        p.formatln( "        DBusInterface.{}.classinfo,", intf );
+        char[][] data = getIntrospectionData( intfTree.getInterface( intf ) );
+        foreach( idx, line; data ){
+            if( idx < data.length-1 ){
+                p.formatln( "            \"{}\"", line );
+            }
+            else{
+                p.formatln( "            \"{}\");", line, (intfIdx<intfTree.allInterfaces.length-1)?",":"" );
+            }
+        }
+    }
+    p.formatln( "}" );
+}
+
+void error( char[][] msg... ){
+    char[200] buf;
+    throw new TracedException( layout( buf, msg ));
+}
+
+void writeInterfaceMethod( Print!(char) p, DefMethod meth, int indent ){
+    DefArgument retArg = meth.mDRetArgument;
+    DefArgument[] args = meth.mDArguments;
+    char[] retType = ( retArg is null ) ? "void" : retArg.toDType();
+    char[] argList;
+    foreach( idx, arg; args ){
+        if( idx > 0 ){
+            argList ~= ",";
+        }
+        argList ~= " ";
+        argList ~= (arg.mDirection == DefArgument.EDir.DIR_OUT) ? "out" : "in";
+        argList ~= " ";
+        argList ~= arg.toDType();
+        argList ~= " ";
+        argList ~= ( arg.mName.length == 0 ) ? "arg_" ~ toUtf8(idx) : arg.mName;
+    }
+    if( argList.length > 0 ){
+        argList ~= " ";
+    }
+    p.formatln( "{}public {} {}({});", getIndent(indent), retType, meth.mName, argList );
+}
+
+void writeInterfaceSignal( Print!(char) p, DefSignal sign, int indent ){
+    char[] argList;
+    foreach( idx, arg; sign.mArguments ){
+        if( idx > 0 ){
+            argList ~= ",";
+        }
+        argList ~= " ";
+        argList ~= arg.toDType();
+    }
+    if( argList.length > 0 ){
+        argList ~= " ";
+    }
+    p.formatln( "{}public tango.core.Signal.Signal!({})* {}();", getIndent(indent), argList, sign.mName );
+}
+
+void writeInterface( Print!(char) p, char[] name, int indent ){
+    p.formatln( "{}// {}", getIndent(indent), name );
+    char[] nodeName = split( name, "." )[ $-1 ];
+    p.formatln( "{}public interface {} {{", getIndent(indent), nodeName );
+    DefInterface intf = intfTree.getInterface( name );
+    if( intf !is null ){
+        foreach( meth; intf.mMethods ){
+            writeInterfaceMethod( p, meth, indent+1 );
+        }
+        foreach( sign; intf.mSignals ){
+            writeInterfaceSignal( p, sign, indent+1 );
+        }
+    }
+    foreach( child; intfTree.getChildNames( name ) ){
+        writeInterface( p, child, indent +1 );
+    }
+    p.formatln( "{}}", getIndent(indent) );
+}
+
+void writeHeader( Print!(char) p, char[] modName ){
+    static char[] HEADER =
+        "/**\n"
+        " * Generated with TioLink\n"
+        " * TioLink was written by Frank Benoit <benoit@tionex.de>\n"
+        " * http://www.dsource.org/projects/tiolink\n"
+        " *\n"
+        " * File type: D programming language source code\n"
+        " */\n";
+    p(HEADER);
+    p.formatln( "module {};", modName );
+    p.newline;
+    p.formatln( "public import org.freedesktop.dbus.Struct;" );
+    p.formatln( "public import org.freedesktop.dbus.Variant;" );
+    p.newline;
+    p.formatln( "import tango.core.Signal;" );
+    p.formatln( "import org.freedesktop.dbus.DBus;" );
+    p.formatln( "import org.freedesktop.dbus.c.Connection : DBusConnection;" );
+    p.formatln( "import org.freedesktop.dbus.c.Message : DBusMessage;" );
+    p.formatln( "import org.freedesktop.dbus.c.Shared : DBusHandlerResult;" );
+    p.newline;
+    p.newline;
+}
+
+void writeInterfaces( Print!(char) p ){
+
+    p.formatln( "// DBus interfaces" );
+    p.formatln( "public interface DBusInterface {{" );
+    foreach( child; intfTree.getChildNames( "" ) ){
+        writeInterface( p, child, 1 );
+    }
+    p.formatln( "}" );
+    p.newline;
+    p.newline;
+
+}
+
+void writePeerMethod( Print!(char) p, DefMethod mth, int indent ){
+    DefArgument retArg = mth.mDRetArgument;
+    DefArgument[] args = mth.mDArguments;
+    char[] retType = ( retArg is null ) ? "void" : retArg.toDType();
+    char[] argList;
+    foreach( idx, arg; args ){
+        if( idx > 0 ){
+            argList ~= ",";
+        }
+        argList ~= " ";
+        argList ~= (arg.mDirection == DefArgument.EDir.DIR_OUT) ? "out" : "in";
+        argList ~= " ";
+        argList ~= arg.toDType();
+        argList ~= " ";
+        argList ~= ( arg.mName.length == 0 ) ? "arg_" ~ toUtf8(idx) : arg.mName;
+    }
+    if( argList.length > 0 ){
+        argList ~= " ";
+    }
+    p.formatln( "{}public {} {}({}){{", getIndent(indent), retType, mth.mName, argList );
+    p.formatln( "{}}", getIndent(indent) );
+}
+
+void writePeerSignal( Print!(char) p, DefSignal sig, int indent ){
+}
+
+void writePeerImpl( Print!(char) p, char[] name, int indent ){
+    p.formatln( "{}// {}", getIndent(indent), name );
+    char[] nodeName = split( name, "." )[ $-1 ];
+    p.formatln( "{}public class {} : DBusPeerObject, DBusInterface.{} {{", getIndent(indent), nodeName, name );
+    DefInterface intf = intfTree.getInterface( name );
+    if( intf !is null ){
+        foreach( meth; intf.mMethods ){
+            writePeerMethod( p, meth, indent+1 );
+        }
+        foreach( sign; intf.mSignals ){
+            writePeerSignal( p, sign, indent+1 );
+        }
+    }
+    foreach( child; intfTree.getChildNames( name ) ){
+        writePeerImpl( p, child, indent +1 );
+    }
+    p.formatln( "{}}", getIndent(indent) );
+}
+void writePeerImpls( Print!(char) p ){
+
+    p.formatln( "// Peer implementations" );
+    p.formatln( "public interface DBusPeers {{" );
+    foreach( child; intfTree.getChildNames( "" ) ){
+        writePeerImpl( p, child, 1 );
+    }
+    p.formatln( "}" );
+    p.newline;
+    p.newline;
+
+}
+
+void writeDBusObject( Print!(char) p ){
+    p.formatln( "// DBusObject" );
+    p.formatln( "public class DBusObject : DBusObjectImpl, DBusInterface.org.freedesktop.DBus.Introspectable {{" );
+    p.formatln( "    this(){{" );
+    p.formatln( "        super();" );
+    p.formatln( "    }" );
+    p.formatln( "    public char[] Introspect(){{" );
+    p.formatln( "        return super.Introspect();" );
+    p.formatln( "    }" );
+    p.formatln( "}" );
+    p.newline;
+    p.newline;
+}
+void writeDBusPeerObject( Print!(char) p ){
+    p.formatln( "// DBusPeerObject" );
+    p.formatln( "public class DBusPeerObject {{" );
+    p.formatln( "}" );
+    p.newline;
+    p.newline;
+}
+class TextList {
+    
+    private char[] separator;
+    private char[] sb;
+    private char[] prefix;
+    private char[] postfix;
+    private bool completed = false;
+
+    public this( char[] separator ){
+        this.separator = separator;
+        this.prefix = "";
+        this.postfix = "";
+    }
+    public this( char[] prefix, char[] separator, char[] postfix ){
+        this.prefix = prefix;
+        this.separator = separator;
+        this.postfix = postfix;
+    }
+    
+    public static TextList createParameterList(){
+        return new TextList( " ", ", ", " " );
+    }
+
+    public void add( char[] value ){
+        if( sb.length == 0 ){
+            sb ~= prefix;
+        }
+        else{
+            sb ~= separator;
+        }
+        sb ~= value;
+    }
+    public char[] toUtf8(){
+        if( !completed ){
+            if( sb.length > 0 ){
+                sb ~= postfix;
+            }
+            completed = true;
+        }
+        return sb;
+    }
+}
+
+void writeHandlerInterfaceMethod( Print!(char) p, DefMethod mth ){
+    char[] sig = mth.mName ~ "|";
+    foreach( arg; mth.mArguments ){
+        if( arg.mDirection == DefArgument.EDir.DIR_IN ){
+            sig ~= arg.mType;
+        }
+    }
+
+    DefArgument retArg = mth.mDRetArgument;
+    DefArgument[] args = mth.mDArguments;
+
+    p.formatln("        case \"{}\":", sig );
+    p.formatln("            {{" );
+    TextList callParams = TextList.createParameterList();
+    TextList callTypes = TextList.createParameterList();
+    TextList callInTypes = TextList.createParameterList();
+    TextList callOutTypes = TextList.createParameterList();
+    int idxi, idxo;
+    char[] retAssign = "";
+    char[] retVar = "";
+    bool hasOutputs = false;
+    bool hasInputs = false;
+    foreach( idx, arg; mth.mArguments ){
+        callTypes.add( arg.toDType());
+        if( arg.mDirection == DefArgument.EDir.DIR_IN ){
+            hasInputs = true;
+            callInTypes.add( arg.toDType());
+            callParams.add( "pi.t["~toUtf8(idxi)~"]" );
+            idxi++;
+        }
+        else{
+            hasOutputs = true;
+            callOutTypes.add( arg.toDType());
+
+            char[] outArg = "po.t["~toUtf8(idxo)~"]";
+            idxo++;
+            if( arg is mth.mDRetArgument ){
+                retVar = outArg;
+                retAssign = retVar~" = ";
+            }
+            else{
+                callParams.add( outArg );
+            }
+        }
+    }
+    if( hasInputs ){
+        p.formatln("                Struct!({0}) pi = getCallValues!({0})( message );", callInTypes.toUtf8() );
+    }
+    if( hasOutputs ){
+        p.formatln("                Struct!({0}) po;" , callOutTypes.toUtf8() );
+    }
+    p.formatln("                {}o.{}({});", retAssign, mth.mName, callParams.toUtf8() );
+    if( hasOutputs ){
+        p.formatln("                sendReplyData!({})( conn, message, po );", callOutTypes.toUtf8() );
+    }
+    else{
+        p.formatln("                sendReply( conn, message );" );
+    }
+    p.formatln("            }" );
+    p.formatln("            break;" );
+
+
+}
+void writeHandlerInterfaceSignal( Print!(char) p, DefSignal sig ){
+    char[] signature = sig.mName ~ ">";
+    foreach( arg; sig.mArguments ){
+        signature ~= arg.mType;
+    }
+
+    DefArgument[] args = sig.mArguments;
+
+    p.formatln("        case \"{}\":", signature );
+    p.formatln("            {{" );
+    TextList callParams = TextList.createParameterList();
+    TextList callInTypes = TextList.createParameterList();
+    int idxi;
+    char[] retAssign = "";
+    char[] retVar = "";
+    bool hasInputs = false;
+    foreach( idx, arg; sig.mArguments ){
+        hasInputs = true;
+        callInTypes.add( arg.toDType());
+        callParams.add( "pi.t["~toUtf8(idxi)~"]" );
+        idxi++;
+    }
+    if( hasInputs ){
+        p.formatln("                Struct!({0}) pi = getCallValues!({0})( message );", callInTypes.toUtf8() );
+    }
+    p.formatln("                o.{}().opCall({});", sig.mName, callParams.toUtf8() );
+    p.formatln("            }" );
+    p.formatln("            break;" );
+
+
+}
+void writeHandlerInterface( Print!(char) p, DefInterface intf ){
+    p.formatln("private DBusHandlerResult intfHandler__{}( "
+        "DBusConnection* conn, DBusMessage* message, void* user_data ){{",
+        replace( intf.mName.dup, '.', '_') );
+    p.formatln("    DBusInterface.{} o = cast(DBusInterface.{0})cast(Object)user_data;", intf.mName );
+    p.formatln("    if( o is null || !checkIntf( \"{}\", message) )", intf.mName );
+    p.formatln("        return DBusHandlerResult.DBUS_HANDLER_RESULT_NOT_YET_HANDLED;" );
+    p.formatln("");
+    p.formatln("    try{{");
+    p.formatln("        char[METHOD_SIG_MAXLENGTH] buf;");
+    p.formatln("        switch( methodSignature( message, buf ) ){{");
+    foreach( DefMethod mth ; intf.mMethods ){
+        writeHandlerInterfaceMethod( p, mth );
+    }
+    foreach( DefSignal sig ; intf.mSignals ){
+        writeHandlerInterfaceSignal( p, sig );
+    }
+    p.formatln("        default:" );
+    p.formatln("            return DBusHandlerResult.DBUS_HANDLER_RESULT_NOT_YET_HANDLED;");
+    p.formatln("        }");
+    p.formatln("    }");
+    p.formatln("    catch( Exception e ){{");
+    p.formatln("        sendException( conn, message, e );" );
+    p.formatln("    }");
+    p.formatln("    return DBusHandlerResult.DBUS_HANDLER_RESULT_HANDLED;");
+    p.formatln("}");
+    p.newline;
+}
+void writeHandlers( Print!(char) p ){
+
+
+    foreach( intfIdx, intf; intfTree.allInterfaces ){
+        writeHandlerInterface( p, intfTree.getInterface( intf ));
+    }
+
+    p.formatln( "private void init_handlers(){{" );
+    foreach( intfIdx, intf; intfTree.allInterfaces ){
+        p.formatln( "    registerHandler(" );
+        p.formatln( "        DBusInterface.{}.classinfo,", intf );
+        p.formatln( "            & intfHandler__{} );", replace( intf.dup, '.', '_' ));
+    }
+    p.formatln( "}" );
+    p.newline;
+
+}
+void writeStaticInit( Print!(char) p ){
+    p.formatln( "static this(){{" );
+    p.formatln( "    init_introspectionData();" );
+    p.formatln( "    init_handlers();" );
+    p.formatln( "}" );
+    p.newline;
+}
+
+int main(char[][] args) {
+    try{
+        if( args.length != 3 ){
+            printSyntax();
+            throw new TerminateException(1);
+        }
+        char[] introxml = args[1];
+        char[] modname  = args[2];
+        intfTree = new IntfTree();
+        auto root = parse( introxml );
+        createStdInterfaces();
+        parseNode( root );
+        Print!(char) output = Stdout;
+        writeHeader( output, modname );
+        writeInterfaces( output );
+        //writePeerImpls( output );
+        writeDBusObject( output );
+        //writeDBusPeerObject( output );
+        writeIntrospectionData( output );
+        writeHandlers( output );
+        writeStaticInit( output );
+    }
+    catch( TerminateException e ){
+        return e.code;
+    }
+    return(0);
+}
+
+
+void printSyntax() {
+    Stdout.formatln("dbus-createinterface <introspectionsdata.xml> <modulename>");
+}
+
+
+