• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

dcop

skel.cpp

Go to the documentation of this file.
00001 /*****************************************************************
00002 Copyright (c) 1999 Torben Weis <weis@kde.org>
00003 Copyright (c) 2000 Matthias Ettrich <ettrich@kde.org>
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00018 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021 
00022 ******************************************************************/
00023 #include <qdom.h>
00024 #include <qfile.h>
00025 #include <qtextstream.h>
00026 #include <qstring.h>
00027 #include <qstringlist.h>
00028 
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <unistd.h>
00033 #include "main.h"
00034 #include "type.h"
00035 
00036 static int const primes[] =
00037 {
00038     2,  3,  5,  7, 11, 13, 17, 19, 23, 29,
00039     31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
00040     73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
00041     127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
00042     179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
00043     233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
00044     283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
00045     353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
00046     419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
00047     467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
00048     547, 557, 563, 569, 571, 577, 587, 593, 599, 601,0
00049 };
00050 
00051 
00052 struct Function
00053 {
00054     Function(){}
00055     Function( const QString& t, const QString& n, const QString&fn, bool h ) 
00056     : type( t ), name( n ), fullName( fn ), hidden( h ) {}
00057     QString type;
00058     QString name;
00059     QString fullName;
00060     bool hidden;
00061 };
00062 
00063 
00064 /*
00065  * Writes the skeleton
00066  */
00067 void generateSkel( const QString& idl, const QString& filename, QDomElement de )
00068 {
00069     QFile skel( filename );
00070     if ( !skel.open( IO_WriteOnly ) )
00071     qFatal("Could not write to %s", filename.local8Bit().data() );
00072 
00073     QTextStream str( &skel );
00074 
00075     str << "/****************************************************************************" << endl;
00076     str << "**" << endl;
00077     str << "** DCOP Skeleton generated by dcopidl2cpp from " << idl << endl;
00078     str << "**" << endl;
00079     str << "** WARNING! All changes made in this file will be lost!" << endl;
00080     str << "**" << endl;
00081     str << "*****************************************************************************/" << endl;
00082     str << endl;
00083 
00084     QDomElement e = de.firstChild().toElement();
00085     if ( e.tagName() == "SOURCE" ) {
00086     str << "#include \"" << e.firstChild().toText().data() << "\"" << endl << endl;
00087     }
00088 
00089     for( ; !e.isNull(); e = e.nextSibling().toElement() ) {
00090     if ( e.tagName() != "CLASS" )
00091         continue;
00092     QDomElement n = e.firstChild().toElement();
00093     Q_ASSERT( n.tagName() == "NAME" );
00094     QString className = n.firstChild().toText().data();
00095     // find dcop parent ( rightmost super class )
00096     QString DCOPParent;
00097     QDomElement s = n.nextSibling().toElement();
00098     for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00099         if ( s.tagName() == "SUPER" )
00100         DCOPParent = s.firstChild().toText().data();
00101     }
00102     
00103     // get function table
00104     QValueList<Function> functions;
00105     s = n.nextSibling().toElement();
00106     for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00107         if ( s.tagName() != "FUNC" )
00108         continue;
00109         QDomElement r = s.firstChild().toElement();
00110         Q_ASSERT( r.tagName() == "TYPE" );
00111         QString funcType = r.firstChild().toText().data();
00112         r = r.nextSibling().toElement();
00113         Q_ASSERT ( r.tagName() == "NAME" );
00114         QString funcName = r.firstChild().toText().data();
00115         QStringList argtypes;
00116         QStringList argnames;
00117         r = r.nextSibling().toElement();
00118         for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00119         Q_ASSERT( r.tagName() == "ARG" );
00120         QDomElement a = r.firstChild().toElement();
00121         Q_ASSERT( a.tagName() == "TYPE" );
00122         argtypes.append( a.firstChild().toText().data() );
00123         a = a.nextSibling().toElement();
00124         if ( !a.isNull() ) {
00125             Q_ASSERT( a.tagName() == "NAME" );
00126             argnames.append( a.firstChild().toText().data() );
00127         } else {
00128             argnames.append( QString::null );
00129         }
00130         }
00131         funcName += '(';
00132         QString fullFuncName = funcName;
00133         bool first = true;
00134         QStringList::Iterator ittype = argtypes.begin();
00135         QStringList::Iterator itname = argnames.begin();
00136         while ( ittype != argtypes.end() && itname != argnames.end() ) {
00137         if ( !first ) {
00138             funcName += ',';
00139             fullFuncName += ',';
00140         }
00141         first = false;
00142         funcName += *ittype;
00143         fullFuncName += *ittype;
00144         if ( ! (*itname).isEmpty() ) {
00145             fullFuncName += ' ';
00146             fullFuncName += *itname;
00147         }
00148         ++ittype;
00149         ++itname;
00150         }
00151         funcName += ')';
00152         fullFuncName += ')';
00153         bool hidden = (s.attribute("hidden") == "yes");
00154         functions.append( Function( funcType, funcName, fullFuncName, hidden ) );
00155     }
00156 
00157     // create static tables
00158     
00159     int fhash = functions.count() + 1;
00160     for ( int i = 0; primes[i]; i++ ) {
00161         if ( primes[i] >  static_cast<int>(functions.count()) ) {
00162         fhash = primes[i];
00163         break;
00164         }
00165     }
00166     
00167     str << "#include <kdatastream.h>" << endl;
00168 
00169     bool useHashing = functions.count() > 7;
00170     if ( useHashing ) {
00171         str << "#include <qasciidict.h>" << endl;
00172     }
00173 
00174     QString classNameFull = className; // class name with possible namespaces prepended
00175                        // namespaces will be removed from className now
00176     int namespace_count = 0;
00177     QString namespace_tmp = className;
00178     str << endl;
00179     for(;;) {
00180         int pos = namespace_tmp.find( "::" );
00181         if( pos < 0 ) {
00182         className = namespace_tmp;
00183         break;
00184         }
00185         str << "namespace " << namespace_tmp.left( pos ) << " {" << endl;
00186         ++namespace_count;
00187         namespace_tmp = namespace_tmp.mid( pos + 2 );
00188     }
00189 
00190     str << endl;
00191 
00192     if ( useHashing ) {
00193         str << "static const int " << className << "_fhash = " << fhash << ";" << endl;
00194     }
00195     str << "static const char* const " << className << "_ftable[" << functions.count() + 1 << "][3] = {" << endl;
00196     for( QValueList<Function>::Iterator it = functions.begin(); it != functions.end(); ++it ){
00197         str << "    { \"" << (*it).type << "\", \"" << (*it).name << "\", \"" << (*it).fullName << "\" }," << endl;
00198     }
00199     str << "    { 0, 0, 0 }" << endl;
00200     str << "};" << endl;
00201 
00202     if (functions.count() > 0) {
00203         str << "static const int " << className << "_ftable_hiddens[" << functions.count() << "] = {" << endl;
00204         for( QValueList<Function>::Iterator it = functions.begin(); it != functions.end(); ++it ){
00205         str << "    " << !!(*it).hidden << "," << endl;
00206         }
00207         str << "};" << endl;
00208     }
00209     
00210     str << endl;
00211     
00212     
00213     // Write dispatcher
00214     str << "bool " << className;
00215     str << "::process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)" << endl;
00216     str << "{" << endl;
00217     if ( useHashing ) {
00218         str << "    static QAsciiDict<int>* fdict = 0;" << endl;
00219     
00220         str << "    if ( !fdict ) {" << endl;
00221         str << "\tfdict = new QAsciiDict<int>( " << className << "_fhash, true, false );" << endl;
00222         str << "\tfor ( int i = 0; " << className << "_ftable[i][1]; i++ )" << endl;
00223         str << "\t    fdict->insert( " << className << "_ftable[i][1],  new int( i ) );" << endl;
00224         str << "    }" << endl;
00225     
00226         str << "    int* fp = fdict->find( fun );" << endl;
00227         str << "    switch ( fp?*fp:-1) {" << endl;
00228     }
00229     s = n.nextSibling().toElement();
00230     int fcount = 0; // counter of written functions
00231     bool firstFunc = true;
00232     for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00233         if ( s.tagName() != "FUNC" )
00234         continue;
00235         QDomElement r = s.firstChild().toElement();
00236         Q_ASSERT( r.tagName() == "TYPE" );
00237         QString funcType = r.firstChild().toText().data();
00238         if ( funcType == "ASYNC" )
00239         funcType = "void";
00240         r = r.nextSibling().toElement();
00241         Q_ASSERT ( r.tagName() == "NAME" );
00242         QString funcName = r.firstChild().toText().data();
00243         QStringList args;
00244         QStringList argtypes;
00245         r = r.nextSibling().toElement();
00246         for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00247         Q_ASSERT( r.tagName() == "ARG" );
00248         QDomElement a = r.firstChild().toElement();
00249         Q_ASSERT( a.tagName() == "TYPE" );
00250         argtypes.append( a.firstChild().toText().data() );
00251         args.append( QString("arg" ) + QString::number( args.count() ) );
00252         }
00253         QString plainFuncName = funcName;
00254         funcName += '(';
00255         bool first = true;
00256         for( QStringList::Iterator argtypes_count = argtypes.begin(); argtypes_count != argtypes.end(); ++argtypes_count ){
00257         if ( !first )
00258             funcName += ',';
00259         first = false;
00260         funcName += *argtypes_count;
00261         }
00262         funcName += ')';
00263         
00264         if ( useHashing ) {
00265         str << "    case " << fcount << ": { // " << funcType << " " << funcName << endl;
00266         } else {
00267         if ( firstFunc )
00268             str << "    if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl;
00269         else
00270             str << " else if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl;
00271         firstFunc = false;
00272         }
00273         if ( !args.isEmpty() ) {
00274         QStringList::Iterator ittypes = argtypes.begin();
00275         QStringList::Iterator args_count;
00276         for( args_count = args.begin(); args_count != args.end(); ++args_count ){
00277             str << '\t'<< *ittypes << " " << *args_count << ";" <<  endl;
00278             ++ittypes;
00279         }
00280         str << "\tQDataStream arg( data, IO_ReadOnly );" << endl;
00281         for( args_count = args.begin(); args_count != args.end(); ++args_count ){
00282             str << "\tif (arg.atEnd()) return false;" << endl; // Basic error checking
00283             str << "\targ >> " << *args_count << ";" << endl;
00284         }
00285         }
00286 
00287         str << "\treplyType = " << className << "_ftable[" << fcount++ << "][0]; " << endl;
00288         if ( funcType == "void" ) {
00289         str << '\t' << plainFuncName << '(';
00290         } else {
00291         str << "\tQDataStream _replyStream( replyData, IO_WriteOnly );"  << endl;
00292         str << "\t_replyStream << " << plainFuncName << '(';
00293         }
00294 
00295         first = true;
00296         for ( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
00297         if ( !first )
00298             str << ", ";
00299         first = false;
00300         str << *args_count;
00301         }
00302         str << " );" << endl;
00303         if (useHashing ) {
00304         str << "    } break;" << endl;
00305         } else {
00306         str << "    }";
00307         }
00308     }
00309 
00310     // only open an 'else' clause if there were one or more functions
00311     if ( fcount > 0 ) {
00312         if ( useHashing ) {
00313         str << "    default: " << endl;
00314         } else {
00315         str << " else {" << endl;
00316         }
00317     }
00318     
00319     // if no DCOP function was called, delegate the request to the parent
00320     if (!DCOPParent.isEmpty()) {
00321         str << "\treturn " << DCOPParent << "::process( fun, data, replyType, replyData );" << endl;
00322     } else {
00323         str << "\treturn false;" << endl;
00324     }
00325 
00326     // only close the 'else' clause and add the default 'return true'
00327     // (signifying a DCOP method was found and called) if there were
00328     // one or more functions.
00329     if ( fcount > 0 ) {
00330         str << "    }" << endl;
00331         str << "    return true;" << endl;
00332     }
00333 
00334     // close the 'process' function
00335     str << "}" << endl << endl;
00336     
00337     str << "QCStringList " << className;
00338     str << "::interfaces()" << endl;
00339     str << "{" << endl;
00340     if (!DCOPParent.isEmpty()) {
00341         str << "    QCStringList ifaces = " << DCOPParent << "::interfaces();" << endl;
00342     } else {
00343         str << "    QCStringList ifaces;" << endl;
00344     }
00345     str << "    ifaces += \"" << classNameFull << "\";" << endl;
00346     str << "    return ifaces;" << endl;
00347     str << "}" << endl << endl;
00348     
00349     
00350     str << "QCStringList " << className;
00351     str << "::functions()" << endl;
00352     str << "{" << endl;
00353     if (!DCOPParent.isEmpty()) {
00354         str << "    QCStringList funcs = " << DCOPParent << "::functions();" << endl;
00355     } else {
00356         str << "    QCStringList funcs;" << endl;
00357     }
00358     str << "    for ( int i = 0; " << className << "_ftable[i][2]; i++ ) {" << endl;
00359         if (functions.count() > 0) {
00360         str << "\tif (" << className << "_ftable_hiddens[i])" << endl;
00361         str << "\t    continue;" << endl;
00362         }
00363     str << "\tQCString func = " << className << "_ftable[i][0];" << endl;
00364     str << "\tfunc += ' ';" << endl;
00365     str << "\tfunc += " << className << "_ftable[i][2];" << endl;
00366     str << "\tfuncs << func;" << endl;
00367     str << "    }" << endl;
00368     str << "    return funcs;" << endl;
00369     str << "}" << endl << endl;
00370     
00371     // Add signal stubs
00372     for(s = e.firstChild().toElement(); !s.isNull(); s = s.nextSibling().toElement() ) {
00373         if (s.tagName() != "SIGNAL")
00374         continue;
00375         QDomElement r = s.firstChild().toElement();
00376         QString result = writeType( str, r );
00377 
00378         r = r.nextSibling().toElement();
00379         Q_ASSERT ( r.tagName() == "NAME" );
00380         QString funcName = r.firstChild().toText().data();
00381         str << className << "::" << funcName << "(";
00382 
00383         QStringList args;
00384         QStringList argtypes;
00385         bool first = true;
00386         r = r.nextSibling().toElement();
00387         for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00388         if ( !first )
00389             str << ", ";
00390         else
00391             str << " ";
00392         first = false;
00393         Q_ASSERT( r.tagName() == "ARG" );
00394         QDomElement a = r.firstChild().toElement();
00395         QString type = writeType( str, a );
00396         argtypes.append( type );
00397         args.append( QString("arg" ) + QString::number( args.count() ) ) ;
00398         str << args.last();
00399         }
00400         if ( !first )
00401         str << " ";
00402         str << ")";
00403 
00404         if ( s.hasAttribute("qual") )
00405         str << " " << s.attribute("qual");
00406         str << endl;
00407     
00408         str << "{" << endl ;
00409 
00410         funcName += "(";
00411         first = true;
00412         for( QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it ){
00413         if ( !first )
00414             funcName += ",";
00415         first = false;
00416         funcName += *it;
00417         }
00418         funcName += ")";
00419     
00420         if ( result != "void" )
00421            qFatal("Error in DCOP signal %s::%s: DCOP signals can not return values.", className.latin1(), funcName.latin1());
00422     
00423         str << "    QByteArray data;" << endl;
00424         if ( !args.isEmpty() ) {
00425         str << "    QDataStream arg( data, IO_WriteOnly );" << endl;
00426         for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
00427             str << "    arg << " << *args_count << ";" << endl;
00428         }
00429         }
00430 
00431         str << "    emitDCOPSignal( \"" << funcName << "\", data );" << endl;
00432 
00433         str << "}" << endl << endl;
00434         
00435     }
00436 
00437     for(; namespace_count > 0; --namespace_count )
00438         str << "} // namespace" << endl;
00439     str << endl;
00440     }
00441     
00442     skel.close();
00443 }
00444 
00445 // :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN>

dcop

Skip menu "dcop"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal