Mercurial > projects > dbus-d
view dbus-d/dsrc/org/freedesktop/dbus/tool/CreateInterface.d @ 4:427c0332a111
work on DBusTesting
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 21 Oct 2007 14:49:02 +0200 |
parents | a5576806d36d |
children | 7c2c75740370 |
line wrap: on
line source
/* * 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.dbus.d.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>"); }