diff options
Diffstat (limited to 'dcop/dcopidl2cpp')
-rw-r--r-- | dcop/dcopidl2cpp/Makefile.am | 20 | ||||
-rw-r--r-- | dcop/dcopidl2cpp/dcopidl_test.h | 109 | ||||
-rw-r--r-- | dcop/dcopidl2cpp/main.cpp | 128 | ||||
-rw-r--r-- | dcop/dcopidl2cpp/main.h | 40 | ||||
-rw-r--r-- | dcop/dcopidl2cpp/skel.cpp | 445 | ||||
-rw-r--r-- | dcop/dcopidl2cpp/stub.cpp | 216 | ||||
-rw-r--r-- | dcop/dcopidl2cpp/stubimpl.cpp | 277 | ||||
-rw-r--r-- | dcop/dcopidl2cpp/type.h | 22 |
8 files changed, 1257 insertions, 0 deletions
diff --git a/dcop/dcopidl2cpp/Makefile.am b/dcop/dcopidl2cpp/Makefile.am new file mode 100644 index 000000000..9b9a6b599 --- /dev/null +++ b/dcop/dcopidl2cpp/Makefile.am @@ -0,0 +1,20 @@ + +INCLUDES = $(all_includes) +AM_LDFLAGS = $(all_libraries) + +####### Files + +bin_PROGRAMS = dcopidl2cpp + +dcopidl2cpp_SOURCES = main.cpp skel.cpp stub.cpp stubimpl.cpp +noinst_HEADERS = main.h + +dcopidl2cpp_LDADD = $(LIB_QT) +dcopidl2cpp_LDFLAGS = $(KDE_RPATH) $(AM_LDFLAGS) + +dcopidl_output.kidl: ../dcopidl/dcopidl $(srcdir)/dcopidl_test.h + ../dcopidl/dcopidl $(srcdir)/dcopidl_test.h > dcopidl_output.kidl + +check-local: dcopidl_output.kidl + ./dcopidl2cpp dcopidl_output.kidl + $(MD5SUM) dcopidl_output_* diff --git a/dcop/dcopidl2cpp/dcopidl_test.h b/dcop/dcopidl2cpp/dcopidl_test.h new file mode 100644 index 000000000..a6c625abe --- /dev/null +++ b/dcop/dcopidl2cpp/dcopidl_test.h @@ -0,0 +1,109 @@ +#include <klistview.h> +#include "main.h" + +#ifndef TEST_H +#define TEST_H + +// still todo: +// stub: +// - includes to super relationship, a bit much to test, needs multiple files? + +class KDEUI_EXPORT DefaultTest : public QObject, virtual public DCOPObject +{ + Q_OBJECT + K_DCOP +public: + DefaultTest(); + void nonDcopFunction( QString filename, QString url, QString text, QString address, QString icon ); +k_dcop: + void noArgsTest(); + void argsTest( QString filename, QString url ); + void unNamedArgsTest( QString, QString ); + + void constTest( QString, QString ) const; + QStringList writeTypeTest( const QString &, QPtrList<int> ); + + void voidReturnType( QString filename, QString url, QString text, QString address, QString icon ); + QString nonVoidReturnType( QString filename, QString text, QString address ); + int intReturnType( QString filename, QString text, QString address ); + bool boolReturnType( QString filename, QString text, QString address ); + + ASYNC asyncTest( QString filename, QString text, QString address ); +}; + +namespace TestNamespace { + class NamespaceTest + { + K_DCOP + public: + NamespaceTest(); + k_dcop: + void function1( QString filename, QString url, QString text, QString address, QString icon ); + }; +} + +class NoSuper +{ + K_DCOP +public: + NoSuper(); +k_dcop: + void function1( QString filename, QString url, QString text, QString address, QString icon ); +}; + +class NonDCOPObject : public MyDCOPObjectBase +{ + K_DCOP +public: + NonDCOPObject(); +k_dcop: + void function1( QString filename, QString url, QString text, QString address, QString icon ); +}; + +class NoFunctions : public DCOPObject +{ + K_DCOP +public: + NonDCOPObject(); + void nonDcopFunction( QString filename, QString url, QString text, QString address, QString icon ); +}; + +class NonHashingTest : public QObject, virtual public DCOPObject +{ + Q_OBJECT + K_DCOP +public: + NonHashingTest(); +k_dcop: + void function1( QString ); +}; + +class HashingTest : public QObject, virtual public DCOPObject +{ + Q_OBJECT + K_DCOP +public: + HashingTest(); +k_dcop: + void function1( QString ); + void function2( QString, QString ); + void function3( QString, QString, QString ); + void function4( QString, QString, QString, QString ); + void function5( QString, QString, QString, QString, QString ); + void function6( QString, QString, QString, QString, QString, QString ); + void function7( QString, QString, QString, QString, QString, QString, QString ); + void function8( QString, QString, QString, QString, QString, QString, QString, QString ); +}; + +class SignalTest : virtual public DCOPObject +{ + K_DCOP +public: + SignalTest(QCString objId = "KBookmarkNotifier") : DCOPObject(objId) {} +k_dcop_signals: + void signal1( QString filename, QString url, QString text, QString address, QString icon ); + void signal2( QString filename, QString text, QString address ); + void signal3( QString filename, QString url ); +}; + +#endif // end diff --git a/dcop/dcopidl2cpp/main.cpp b/dcop/dcopidl2cpp/main.cpp new file mode 100644 index 000000000..32d128c30 --- /dev/null +++ b/dcop/dcopidl2cpp/main.cpp @@ -0,0 +1,128 @@ +/***************************************************************** +Copyright (c) 1999 Torben Weis <weis@kde.org> +Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ +#include <qdom.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qstring.h> + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include "main.h" + + + +void usage() +{ + fprintf( stderr, "Usage: dcopidl2cpp [ --no-skel | --no-stub ] [--c++-suffix <suffix>] file\n" ); +} + +int main( int argc, char** argv ) +{ + + if ( *qVersion() == '1' ) { + fprintf( stderr, "dcopidl2cpp appears to be linked to Qt 1 instead of Qt >= 2 ! Aborting.\n" ); + exit(1); + } + if ( argc < 2 ) { + usage(); + return 1; + } + int argpos = 1; + bool generate_skel = true; + bool generate_stub = true; + + QString suffix = "cpp"; + + while (argc > 2) { + + if ( strcmp( argv[argpos], "--no-skel" ) == 0 ) + { + generate_skel = false; + for (int i = argpos; i < argc - 1; i++) argv[i] = argv[i+1]; + argc--; + } + else if ( strcmp( argv[argpos], "--no-stub" ) == 0 ) + { + generate_stub = false; + for (int i = argpos; i < argc - 1; i++) argv[i] = argv[i+1]; + argc--; + } + else if ( strcmp( argv[argpos], "--no-signals" ) == 0 ) + { + // Obsolete: Signal stubs are now always generated. + // Leave this command line argument intact, so old Makefiles won't break. + for (int i = argpos; i < argc - 1; i++) argv[i] = argv[i+1]; + argc--; + } + else if ( strcmp( argv[argpos], "--c++-suffix" ) == 0) + { + if (argc - 1 < argpos) { + usage(); + exit(1); + } + suffix = argv[argpos+1]; + for (int i = argpos; i < argc - 2; i++) argv[i] = argv[i+2]; + argc -= 2; + } else { + usage(); + exit(1); + } + } + + QFile in( QFile::decodeName(argv[argpos]) ); + if ( !in.open( IO_ReadOnly ) ) + qFatal("Could not read %s", argv[argpos] ); + + QDomDocument doc; + doc.setContent( &in ); + + QDomElement de = doc.documentElement(); + Q_ASSERT( de.tagName() == "DCOP-IDL" ); + + QString base( argv[argpos] ); + QString idl = base; + + int pos = base.findRev( '.' ); + if ( pos != -1 ) + base = base.left( pos ); + + pos = idl.findRev('/'); + if ( pos != -1 ) + idl = idl.mid( pos+1 ); + + if ( generate_skel ) + generateSkel( idl, base + "_skel." + suffix, de ); + + if ( generate_stub ) { + QString header = base; + generateStub( idl, header + "_stub.h", de ); + pos = header.findRev('/'); + if ( pos != -1 ) + header = header.mid( pos+1 ); + generateStubImpl( idl, header + "_stub.h", base+".h", base + "_stub." + suffix, de); + } + + return 0; +} diff --git a/dcop/dcopidl2cpp/main.h b/dcop/dcopidl2cpp/main.h new file mode 100644 index 000000000..a0ecdb250 --- /dev/null +++ b/dcop/dcopidl2cpp/main.h @@ -0,0 +1,40 @@ +/***************************************************************** +Copyright (c) 1999 Torben Weis <weis@kde.org> +Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ +#include <qdom.h> +#include <qstring.h> + +/** + * Writes the skeleton + */ +void generateSkel( const QString& idl, const QString& filename, QDomElement de ); + +/** + * Writes the stubs header + */ +void generateStub( const QString& idl, const QString& filename, QDomElement de); + +/** + * Writes the stub implementation + */ +void generateStubImpl( const QString& idl, const QString& header, const QString& headerBase, const QString& filename, QDomElement de); + diff --git a/dcop/dcopidl2cpp/skel.cpp b/dcop/dcopidl2cpp/skel.cpp new file mode 100644 index 000000000..fe79aec92 --- /dev/null +++ b/dcop/dcopidl2cpp/skel.cpp @@ -0,0 +1,445 @@ +/***************************************************************** +Copyright (c) 1999 Torben Weis <weis@kde.org> +Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ +#include <qdom.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qstring.h> +#include <qstringlist.h> + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include "main.h" +#include "type.h" + +static int const primes[] = +{ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, + 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, + 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, + 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, + 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, + 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, + 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, + 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,0 +}; + + +struct Function +{ + Function(){} + Function( const QString& t, const QString& n, const QString&fn, bool h ) + : type( t ), name( n ), fullName( fn ), hidden( h ) {} + QString type; + QString name; + QString fullName; + bool hidden; +}; + + +/* + * Writes the skeleton + */ +void generateSkel( const QString& idl, const QString& filename, QDomElement de ) +{ + QFile skel( filename ); + if ( !skel.open( IO_WriteOnly ) ) + qFatal("Could not write to %s", filename.local8Bit().data() ); + + QTextStream str( &skel ); + + str << "/****************************************************************************" << endl; + str << "**" << endl; + str << "** DCOP Skeleton generated by dcopidl2cpp from " << idl << endl; + str << "**" << endl; + str << "** WARNING! All changes made in this file will be lost!" << endl; + str << "**" << endl; + str << "*****************************************************************************/" << endl; + str << endl; + + QDomElement e = de.firstChild().toElement(); + if ( e.tagName() == "SOURCE" ) { + str << "#include \"" << e.firstChild().toText().data() << "\"" << endl << endl; + } + + for( ; !e.isNull(); e = e.nextSibling().toElement() ) { + if ( e.tagName() != "CLASS" ) + continue; + QDomElement n = e.firstChild().toElement(); + Q_ASSERT( n.tagName() == "NAME" ); + QString className = n.firstChild().toText().data(); + // find dcop parent ( rightmost super class ) + QString DCOPParent; + QDomElement s = n.nextSibling().toElement(); + for( ; !s.isNull(); s = s.nextSibling().toElement() ) { + if ( s.tagName() == "SUPER" ) + DCOPParent = s.firstChild().toText().data(); + } + + // get function table + QValueList<Function> functions; + s = n.nextSibling().toElement(); + for( ; !s.isNull(); s = s.nextSibling().toElement() ) { + if ( s.tagName() != "FUNC" ) + continue; + QDomElement r = s.firstChild().toElement(); + Q_ASSERT( r.tagName() == "TYPE" ); + QString funcType = r.firstChild().toText().data(); + r = r.nextSibling().toElement(); + Q_ASSERT ( r.tagName() == "NAME" ); + QString funcName = r.firstChild().toText().data(); + QStringList argtypes; + QStringList argnames; + r = r.nextSibling().toElement(); + for( ; !r.isNull(); r = r.nextSibling().toElement() ) { + Q_ASSERT( r.tagName() == "ARG" ); + QDomElement a = r.firstChild().toElement(); + Q_ASSERT( a.tagName() == "TYPE" ); + argtypes.append( a.firstChild().toText().data() ); + a = a.nextSibling().toElement(); + if ( !a.isNull() ) { + Q_ASSERT( a.tagName() == "NAME" ); + argnames.append( a.firstChild().toText().data() ); + } else { + argnames.append( QString::null ); + } + } + funcName += '('; + QString fullFuncName = funcName; + bool first = true; + QStringList::Iterator ittype = argtypes.begin(); + QStringList::Iterator itname = argnames.begin(); + while ( ittype != argtypes.end() && itname != argnames.end() ) { + if ( !first ) { + funcName += ','; + fullFuncName += ','; + } + first = false; + funcName += *ittype; + fullFuncName += *ittype; + if ( ! (*itname).isEmpty() ) { + fullFuncName += ' '; + fullFuncName += *itname; + } + ++ittype; + ++itname; + } + funcName += ')'; + fullFuncName += ')'; + bool hidden = (s.attribute("hidden") == "yes"); + functions.append( Function( funcType, funcName, fullFuncName, hidden ) ); + } + + // create static tables + + int fhash = functions.count() + 1; + for ( int i = 0; primes[i]; i++ ) { + if ( primes[i] > static_cast<int>(functions.count()) ) { + fhash = primes[i]; + break; + } + } + + str << "#include <kdatastream.h>" << endl; + + bool useHashing = functions.count() > 7; + if ( useHashing ) { + str << "#include <qasciidict.h>" << endl; + } + + QString classNameFull = className; // class name with possible namespaces prepended + // namespaces will be removed from className now + int namespace_count = 0; + QString namespace_tmp = className; + str << endl; + for(;;) { + int pos = namespace_tmp.find( "::" ); + if( pos < 0 ) { + className = namespace_tmp; + break; + } + str << "namespace " << namespace_tmp.left( pos ) << " {" << endl; + ++namespace_count; + namespace_tmp = namespace_tmp.mid( pos + 2 ); + } + + str << endl; + + if ( useHashing ) { + str << "static const int " << className << "_fhash = " << fhash << ";" << endl; + } + str << "static const char* const " << className << "_ftable[" << functions.count() + 1 << "][3] = {" << endl; + for( QValueList<Function>::Iterator it = functions.begin(); it != functions.end(); ++it ){ + str << " { \"" << (*it).type << "\", \"" << (*it).name << "\", \"" << (*it).fullName << "\" }," << endl; + } + str << " { 0, 0, 0 }" << endl; + str << "};" << endl; + + if (functions.count() > 0) { + str << "static const int " << className << "_ftable_hiddens[" << functions.count() << "] = {" << endl; + for( QValueList<Function>::Iterator it = functions.begin(); it != functions.end(); ++it ){ + str << " " << !!(*it).hidden << "," << endl; + } + str << "};" << endl; + } + + str << endl; + + + // Write dispatcher + str << "bool " << className; + str << "::process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)" << endl; + str << "{" << endl; + if ( useHashing ) { + str << " static QAsciiDict<int>* fdict = 0;" << endl; + + str << " if ( !fdict ) {" << endl; + str << "\tfdict = new QAsciiDict<int>( " << className << "_fhash, true, false );" << endl; + str << "\tfor ( int i = 0; " << className << "_ftable[i][1]; i++ )" << endl; + str << "\t fdict->insert( " << className << "_ftable[i][1], new int( i ) );" << endl; + str << " }" << endl; + + str << " int* fp = fdict->find( fun );" << endl; + str << " switch ( fp?*fp:-1) {" << endl; + } + s = n.nextSibling().toElement(); + int fcount = 0; // counter of written functions + bool firstFunc = true; + for( ; !s.isNull(); s = s.nextSibling().toElement() ) { + if ( s.tagName() != "FUNC" ) + continue; + QDomElement r = s.firstChild().toElement(); + Q_ASSERT( r.tagName() == "TYPE" ); + QString funcType = r.firstChild().toText().data(); + if ( funcType == "ASYNC" ) + funcType = "void"; + r = r.nextSibling().toElement(); + Q_ASSERT ( r.tagName() == "NAME" ); + QString funcName = r.firstChild().toText().data(); + QStringList args; + QStringList argtypes; + r = r.nextSibling().toElement(); + for( ; !r.isNull(); r = r.nextSibling().toElement() ) { + Q_ASSERT( r.tagName() == "ARG" ); + QDomElement a = r.firstChild().toElement(); + Q_ASSERT( a.tagName() == "TYPE" ); + argtypes.append( a.firstChild().toText().data() ); + args.append( QString("arg" ) + QString::number( args.count() ) ); + } + QString plainFuncName = funcName; + funcName += '('; + bool first = true; + for( QStringList::Iterator argtypes_count = argtypes.begin(); argtypes_count != argtypes.end(); ++argtypes_count ){ + if ( !first ) + funcName += ','; + first = false; + funcName += *argtypes_count; + } + funcName += ')'; + + if ( useHashing ) { + str << " case " << fcount << ": { // " << funcType << " " << funcName << endl; + } else { + if ( firstFunc ) + str << " if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl; + else + str << " else if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl; + firstFunc = false; + } + if ( !args.isEmpty() ) { + QStringList::Iterator ittypes = argtypes.begin(); + QStringList::Iterator args_count; + for( args_count = args.begin(); args_count != args.end(); ++args_count ){ + str << '\t'<< *ittypes << " " << *args_count << ";" << endl; + ++ittypes; + } + str << "\tQDataStream arg( data, IO_ReadOnly );" << endl; + for( args_count = args.begin(); args_count != args.end(); ++args_count ){ + str << "\tif (arg.atEnd()) return false;" << endl; // Basic error checking + str << "\targ >> " << *args_count << ";" << endl; + } + } + + str << "\treplyType = " << className << "_ftable[" << fcount++ << "][0]; " << endl; + if ( funcType == "void" ) { + str << '\t' << plainFuncName << '('; + } else { + str << "\tQDataStream _replyStream( replyData, IO_WriteOnly );" << endl; + str << "\t_replyStream << " << plainFuncName << '('; + } + + first = true; + for ( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){ + if ( !first ) + str << ", "; + first = false; + str << *args_count; + } + str << " );" << endl; + if (useHashing ) { + str << " } break;" << endl; + } else { + str << " }"; + } + } + + // only open an 'else' clause if there were one or more functions + if ( fcount > 0 ) { + if ( useHashing ) { + str << " default: " << endl; + } else { + str << " else {" << endl; + } + } + + // if no DCOP function was called, delegate the request to the parent + if (!DCOPParent.isEmpty()) { + str << "\treturn " << DCOPParent << "::process( fun, data, replyType, replyData );" << endl; + } else { + str << "\treturn false;" << endl; + } + + // only close the 'else' clause and add the default 'return true' + // (signifying a DCOP method was found and called) if there were + // one or more functions. + if ( fcount > 0 ) { + str << " }" << endl; + str << " return true;" << endl; + } + + // close the 'process' function + str << "}" << endl << endl; + + str << "QCStringList " << className; + str << "::interfaces()" << endl; + str << "{" << endl; + if (!DCOPParent.isEmpty()) { + str << " QCStringList ifaces = " << DCOPParent << "::interfaces();" << endl; + } else { + str << " QCStringList ifaces;" << endl; + } + str << " ifaces += \"" << classNameFull << "\";" << endl; + str << " return ifaces;" << endl; + str << "}" << endl << endl; + + + str << "QCStringList " << className; + str << "::functions()" << endl; + str << "{" << endl; + if (!DCOPParent.isEmpty()) { + str << " QCStringList funcs = " << DCOPParent << "::functions();" << endl; + } else { + str << " QCStringList funcs;" << endl; + } + str << " for ( int i = 0; " << className << "_ftable[i][2]; i++ ) {" << endl; + if (functions.count() > 0) { + str << "\tif (" << className << "_ftable_hiddens[i])" << endl; + str << "\t continue;" << endl; + } + str << "\tQCString func = " << className << "_ftable[i][0];" << endl; + str << "\tfunc += ' ';" << endl; + str << "\tfunc += " << className << "_ftable[i][2];" << endl; + str << "\tfuncs << func;" << endl; + str << " }" << endl; + str << " return funcs;" << endl; + str << "}" << endl << endl; + + // Add signal stubs + for(s = e.firstChild().toElement(); !s.isNull(); s = s.nextSibling().toElement() ) { + if (s.tagName() != "SIGNAL") + continue; + QDomElement r = s.firstChild().toElement(); + QString result = writeType( str, r ); + + r = r.nextSibling().toElement(); + Q_ASSERT ( r.tagName() == "NAME" ); + QString funcName = r.firstChild().toText().data(); + str << className << "::" << funcName << "("; + + QStringList args; + QStringList argtypes; + bool first = true; + r = r.nextSibling().toElement(); + for( ; !r.isNull(); r = r.nextSibling().toElement() ) { + if ( !first ) + str << ", "; + else + str << " "; + first = false; + Q_ASSERT( r.tagName() == "ARG" ); + QDomElement a = r.firstChild().toElement(); + QString type = writeType( str, a ); + argtypes.append( type ); + args.append( QString("arg" ) + QString::number( args.count() ) ) ; + str << args.last(); + } + if ( !first ) + str << " "; + str << ")"; + + if ( s.hasAttribute("qual") ) + str << " " << s.attribute("qual"); + str << endl; + + str << "{" << endl ; + + funcName += "("; + first = true; + for( QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it ){ + if ( !first ) + funcName += ","; + first = false; + funcName += *it; + } + funcName += ")"; + + if ( result != "void" ) + qFatal("Error in DCOP signal %s::%s: DCOP signals can not return values.", className.latin1(), funcName.latin1()); + + str << " QByteArray data;" << endl; + if ( !args.isEmpty() ) { + str << " QDataStream arg( data, IO_WriteOnly );" << endl; + for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){ + str << " arg << " << *args_count << ";" << endl; + } + } + + str << " emitDCOPSignal( \"" << funcName << "\", data );" << endl; + + str << "}" << endl << endl; + + } + + for(; namespace_count > 0; --namespace_count ) + str << "} // namespace" << endl; + str << endl; + } + + skel.close(); +} + +// :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN> diff --git a/dcop/dcopidl2cpp/stub.cpp b/dcop/dcopidl2cpp/stub.cpp new file mode 100644 index 000000000..4060ae88f --- /dev/null +++ b/dcop/dcopidl2cpp/stub.cpp @@ -0,0 +1,216 @@ +/***************************************************************** +Copyright (c) 1999 Torben Weis <weis@kde.org> +Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ +#include <qdom.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qstring.h> +#include <qstringlist.h> + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include "main.h" +#include "type.h" + +/* + * Writes the stubs header + */ +void generateStub( const QString& idl, const QString& filename, QDomElement de) +{ + QFile stub( filename ); + if ( !stub.open( IO_WriteOnly ) ) + qFatal("Could not write to %s", filename.local8Bit().data() ); + + QTextStream str( &stub ); + + str << "/****************************************************************************" << endl; + str << "**" << endl; + str << "** DCOP Stub Definition created by dcopidl2cpp from " << idl << endl; + str << "**" << endl; + str << "** WARNING! All changes made in this file will be lost!" << endl; + str << "**" << endl; + str << "*****************************************************************************/" << endl; + str << endl; + + QString ifdefstring = idl.upper(); + int pos = idl.findRev( '.' ); + if ( pos != -1 ) + ifdefstring = ifdefstring.left( pos ); + + QString ifdefsuffix = "_STUB__"; + str << "#ifndef __" << ifdefstring << ifdefsuffix << endl; + str << "#define __" << ifdefstring << ifdefsuffix << endl << endl; + + str << "#include <dcopstub.h>" << endl; + + QStringList includeslist, all_includes; + QDomElement e = de.firstChild().toElement(); + for( ; !e.isNull(); e = e.nextSibling().toElement() ) { + if ( e.tagName() == "INCLUDE" ) { + // dcopidl lists the includes in reversed order because of the used yacc/bison gramatic + // so let's reverse it back, as the order may be important + includeslist.prepend( e.firstChild().toText().data()); + continue; + } + if( !includeslist.empty()) { + for( QStringList::ConstIterator it = includeslist.begin(); + it != includeslist.end(); + ++it ) { + str << "#include <" << ( *it ) << ">" << endl; + all_includes.append( *it ); + } + includeslist.clear(); + } + if ( e.tagName() != "CLASS" ) + continue; + + str << endl; + + QDomElement n = e.firstChild().toElement(); + Q_ASSERT( n.tagName() == "NAME" ); + QString className = n.firstChild().toText().data() + ( "_stub" ); + + //add link scope, if available + n = n.nextSibling().toElement(); + QString linkScope; + if (n.tagName()=="LINK_SCOPE") { + linkScope = n.firstChild().toText().data() + " "; + n = n.nextSibling().toElement(); + } + + // find dcop parent ( rightmost super class ) + QString DCOPParent; + for( ; !n.isNull(); n = n.nextSibling().toElement() ) { + if ( n.tagName() == "SUPER" ) + DCOPParent = n.firstChild().toText().data(); + } + + if( DCOPParent != "DCOPObject" ) { // we need to include the .h file for the base stub + if( all_includes.contains( DCOPParent + ".h" )) + str << "#include <" << DCOPParent << "_stub.h>" << endl; + else if( all_includes.contains( DCOPParent.lower() + ".h" )) + str << "#include <" << DCOPParent.lower() << "_stub.h>" << endl; + else {// damn ... let's assume it's the last include + QString stub_h = all_includes.last(); + unsigned int pos = stub_h.find( ".h" ); + if( pos > 0 ) { + stub_h = stub_h.remove( pos, 100000 ); + str << "#include <" << stub_h << "_stub.h>" << endl; + } + else + str << "#include <" << stub_h << ">" << endl; + } + } + + QString classNameFull = className; // class name with possible namespaces prepended + // namespaces will be removed from className now + int namespace_count = 0; + QString namespace_tmp = className; + for(;;) { + int pos = namespace_tmp.find( "::" ); + if( pos < 0 ) { + className = namespace_tmp; + break; + } + str << "namespace " << namespace_tmp.left( pos ) << " {" << endl; + ++namespace_count; + namespace_tmp = namespace_tmp.mid( pos + 2 ); + } + + str << endl; + + // Stub class definition + str << "class " << linkScope << className; + + // Parent : inherited interface stub or dcopstub + if ( !DCOPParent.isEmpty() && DCOPParent != "DCOPObject" ) { + str << " : "; + str << "virtual public " << DCOPParent << "_stub"; + } else { + str << " : virtual public DCOPStub"; + } + + str << endl; + str << "{" << endl; + str << "public:" << endl; + + // Constructors + str << " " << className << "( const QCString& app, const QCString& id );" << endl; + str << " " << className << "( DCOPClient* client, const QCString& app, const QCString& id );" << endl; + str << " explicit " << className << "( const DCOPRef& ref );" << endl; + + n = e.firstChild().toElement(); + for( ; !n.isNull(); n = n.nextSibling().toElement() ) { + if (n.tagName() != "FUNC") + continue; + QDomElement r = n.firstChild().toElement(); + str << " virtual "; // KDE4 - I really don't think these need to be virtual + writeType( str, r ); + + r = r.nextSibling().toElement(); + Q_ASSERT ( r.tagName() == "NAME" ); + str << r.firstChild().toText().data() << "("; + + bool first = true; + r = r.nextSibling().toElement(); + for( ; !r.isNull(); r = r.nextSibling().toElement() ) { + if ( !first ) + str << ", "; + else + str << " "; + first = false; + Q_ASSERT( r.tagName() == "ARG" ); + QDomElement a = r.firstChild().toElement(); + writeType( str, a ); + a = a.nextSibling().toElement(); + if ( a.tagName() == "NAME" ) + str << a.firstChild().toText().data(); + } + if ( !first ) + str << " "; + str << ")"; + + //const methods stubs can't compile, they need to call setStatus(). + //if ( n.hasAttribute("qual") ) + // str << " " << n.attribute("qual"); + str << ";" << endl; + } + + // needed for inherited stubs + str << "protected:" << endl; + str << " " << className << "() : DCOPStub( never_use ) {}" << endl; + + str << "};" << endl; + str << endl; + + for(; namespace_count > 0; --namespace_count ) + str << "} // namespace" << endl; + str << endl; + } + + str << "#endif" << endl; + stub.close(); +} + +// :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN> diff --git a/dcop/dcopidl2cpp/stubimpl.cpp b/dcop/dcopidl2cpp/stubimpl.cpp new file mode 100644 index 000000000..22c11527b --- /dev/null +++ b/dcop/dcopidl2cpp/stubimpl.cpp @@ -0,0 +1,277 @@ +/***************************************************************** +Copyright (c) 1999 Torben Weis <weis@kde.org> +Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ +#include <qdom.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qstring.h> +#include <qstringlist.h> + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include "main.h" +#include "type.h" + +static bool isIntType( const QString& t ) +{ + return ((t == "int") + || (t == "signed int") + || (t == "unsigned int") + || (t == "uint") + || (t == "unsigned") + || (t == "signed short int") + || (t == "signed short") + || (t == "short int") + || (t == "short") + || (t == "unsigned short int") + || (t == "unsigned short") + || (t == "ushort") + || (t == "long int") + || (t == "signed long int") + || (t == "long") + || (t == "signed long") + || (t == "unsigned long int") + || (t == "unsigned long") + || (t == "ulong") + || (t == "char") + || (t == "signed char") + || (t == "unsigned char")); +} + +/* + * Writes the stub implementation + */ +void generateStubImpl( const QString& idl, const QString& header, const QString& /*headerBase*/, const QString& filename, QDomElement de ) +{ + QFile impl( filename ); + if ( !impl.open( IO_WriteOnly ) ) + qFatal("Could not write to %s", filename.latin1() ); + + QTextStream str( &impl ); + + str << "/****************************************************************************" << endl; + str << "**" << endl; + str << "** DCOP Stub Implementation created by dcopidl2cpp from " << idl << endl; + str << "**" << endl; + str << "** WARNING! All changes made in this file will be lost!" << endl; + str << "**" << endl; + str << "*****************************************************************************/" << endl; + str << endl; + + str << "#include \"" << header << "\"" << endl; + str << "#include <dcopclient.h>" << endl << endl; + str << "#include <kdatastream.h>" << endl; + + QDomElement e = de.firstChild().toElement(); + for( ; !e.isNull(); e = e.nextSibling().toElement() ) { + if ( e.tagName() != "CLASS" ) + continue; + QDomElement n = e.firstChild().toElement(); + Q_ASSERT( n.tagName() == "NAME" ); + QString classNameBase = n.firstChild().toText().data(); + QString className_stub = classNameBase + "_stub"; + + QString classNameFull = className_stub; // class name with possible namespaces prepended + // namespaces will be removed from className now + int namespace_count = 0; + QString namespace_tmp = className_stub; + str << endl; + for(;;) { + int pos = namespace_tmp.find( "::" ); + if( pos < 0 ) { + className_stub = namespace_tmp; + break; + } + str << "namespace " << namespace_tmp.left( pos ) << " {" << endl; + ++namespace_count; + namespace_tmp = namespace_tmp.mid( pos + 2 ); + } + + str << endl; + + // Write constructors + str << className_stub << "::" << className_stub << "( const QCString& app, const QCString& obj )" << endl; + str << " : "; + + // Always explicitly call DCOPStub constructor, because it's virtual base class. + // Calling other ones doesn't matter, as they don't do anything important. + str << "DCOPStub( app, obj )" << endl; + + str << "{" << endl; + str << "}" << endl << endl; + + str << className_stub << "::" << className_stub << "( DCOPClient* client, const QCString& app, const QCString& obj )" << endl; + str << " : "; + + str << "DCOPStub( client, app, obj )" << endl; + + str << "{" << endl; + str << "}" << endl << endl; + + str << className_stub << "::" << className_stub << "( const DCOPRef& ref )" << endl; + str << " : "; + + str << "DCOPStub( ref )" << endl; + + str << "{" << endl; + str << "}" << endl << endl; + + // Write marshalling code + QDomElement s = e.firstChild().toElement(); + for( ; !s.isNull(); s = s.nextSibling().toElement() ) { + if (s.tagName() != "FUNC") + continue; + QDomElement r = s.firstChild().toElement(); + Q_ASSERT( r.tagName() == "TYPE" ); + QString result = r.firstChild().toText().data(); + bool async = result == "ASYNC"; + if ( async) { + result = "void"; + str << result << " "; + } else + result = writeType( str, r ); + + r = r.nextSibling().toElement(); + Q_ASSERT ( r.tagName() == "NAME" ); + QString funcName = r.firstChild().toText().data(); + str << className_stub << "::" << funcName << "("; + + QStringList args; + QStringList argtypes; + bool first = true; + r = r.nextSibling().toElement(); + for( ; !r.isNull(); r = r.nextSibling().toElement() ) { + if ( !first ) + str << ", "; + else + str << " "; + first = false; + Q_ASSERT( r.tagName() == "ARG" ); + QDomElement a = r.firstChild().toElement(); + QString type = writeType( str, a ); + argtypes.append( type ); + args.append( QString("arg" ) + QString::number( args.count() ) ) ; + str << args.last(); + } + if ( !first ) + str << " "; + str << ")"; + + //const methods in a stub can't compile, they need to call setStatus() + //if ( s.hasAttribute("qual") ) + // str << " " << s.attribute("qual"); + str << endl; + + str << "{" << endl ; + + + funcName += "("; + first = true; + for( QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it ){ + if ( !first ) + funcName += ","; + first = false; + funcName += *it; + } + funcName += ")"; + + if ( async ) { + + str << " if ( !dcopClient() ) {"<< endl; + str << "\tsetStatus( CallFailed );" << endl; + str << "\treturn;" << endl; + str << " }" << endl; + + str << " QByteArray data;" << endl; + if ( !args.isEmpty() ) { + str << " QDataStream arg( data, IO_WriteOnly );" << endl; + for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){ + str << " arg << " << *args_count << ";" << endl; + } + } + + str << " dcopClient()->send( app(), obj(), \"" << funcName << "\", data );" << endl; + str << " setStatus( CallSucceeded );" << endl; + + } else { + + if ( result != "void" ) { + str << " " << result << " result"; + if (isIntType( result )) + str << " = 0"; + else if (result == "float" || result == "double") + str << " = 0.0"; + else if ( result == "bool" ) + str << " = false"; + + str << ";" << endl; + } + + str << " if ( !dcopClient() ) {"<< endl; + str << "\tsetStatus( CallFailed );" << endl; + if ( result != "void" ) + str << "\treturn result;" << endl; + else + str << "\treturn;" << endl; + str << " }" << endl; + + str << " QByteArray data, replyData;" << endl; + str << " QCString replyType;" << endl; + + if ( !args.isEmpty() ) { + str << " QDataStream arg( data, IO_WriteOnly );" << endl; + for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){ + str << " arg << " << *args_count << ";" << endl; + } + } + str << " if ( dcopClient()->call( app(), obj(), \"" << funcName << "\","; + str << " data, replyType, replyData ) ) {" << endl; + if ( result != "void" ) { + str << "\tif ( replyType == \"" << result << "\" ) {" << endl; + str << "\t QDataStream _reply_stream( replyData, IO_ReadOnly );" << endl; + str << "\t _reply_stream >> result;" << endl; + str << "\t setStatus( CallSucceeded );" << endl; + str << "\t} else {" << endl; + str << "\t callFailed();" << endl; + str << "\t}" << endl; + } else { + str << "\tsetStatus( CallSucceeded );" << endl; + } + str << " } else { " << endl; + str << "\tcallFailed();" << endl; + str << " }" << endl; + if ( result != "void" ) + str << " return result;" << endl; + } + str << "}" << endl << endl; + } + + for(; namespace_count > 0; --namespace_count ) + str << "} // namespace" << endl; + str << endl; + } + impl.close(); +} + +// :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN> diff --git a/dcop/dcopidl2cpp/type.h b/dcop/dcopidl2cpp/type.h new file mode 100644 index 000000000..baaacacfb --- /dev/null +++ b/dcop/dcopidl2cpp/type.h @@ -0,0 +1,22 @@ +#ifndef TYPE_H +#define TYPE_H + +#include <qtextstream.h> +#include <qdom.h> + +static QString writeType( QTextStream& str, const QDomElement& r ) +{ + Q_ASSERT( r.tagName() == "TYPE" ); + if ( r.hasAttribute( "qleft" ) ) + str << r.attribute("qleft") << " "; + QString t = r.firstChild().toText().data(); + t = t.replace( ">>", "> >" ); + str << t; + if ( r.hasAttribute( "qright" ) ) + str << r.attribute("qright") << " "; + else + str << " "; + return t; +} + +#endif |