dcop Library: skel.cpp Source File (dcop Library)

| # dcop Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# skel.cpp

    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>

This file is part of the documentation for dcop Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:16:55 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003