dcop Library API Documentation

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 
00035 static int const primes[] =
00036 {
00037     2,  3,  5,  7, 11, 13, 17, 19, 23, 29,
00038     31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
00039     73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
00040     127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
00041     179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
00042     233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
00043     283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
00044     353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
00045     419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
00046     467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
00047     547, 557, 563, 569, 571, 577, 587, 593, 599, 601,0
00048 };
00049 
00050 
00051 struct Function
00052 {
00053     Function(){};
00054     Function( const QString& t, const QString& n, const QString&fn ) : type( t ), name( n ), fullName( fn ){}
00055     QString type;
00056     QString name;
00057     QString fullName;
00058 };
00059 
00060 
00064 void generateSkel( const QString& idl, const QString& filename, QDomElement de )
00065 {
00066     QFile skel( filename );
00067     if ( !skel.open( IO_WriteOnly ) )
00068         qFatal("Could not write to %s", filename.local8Bit().data() );
00069 
00070     QTextStream str( &skel );
00071 
00072     str << "/****************************************************************************" << endl;
00073     str << "**" << endl;
00074     str << "** DCOP Skeleton created by dcopidl2cpp from " << idl << endl;
00075     str << "**" << endl;
00076     str << "** WARNING! All changes made in this file will be lost!" << endl;
00077     str << "**" << endl;
00078     str << "*****************************************************************************/" << endl;
00079     str << endl;
00080 
00081     QDomElement e = de.firstChild().toElement();
00082     if ( e.tagName() == "SOURCE" ) {
00083         str << "#include \"" << e.firstChild().toText().data() << "\"" << endl << endl;
00084     }
00085 
00086     for( ; !e.isNull(); e = e.nextSibling().toElement() ) {
00087         if ( e.tagName() == "CLASS" ) {
00088             QDomElement n = e.firstChild().toElement();
00089             Q_ASSERT( n.tagName() == "NAME" );
00090             QString className = n.firstChild().toText().data();
00091             // find dcop parent ( rightmost super class )
00092             QString DCOPParent;
00093             QDomElement s = n.nextSibling().toElement();
00094             for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00095                 if ( s.tagName() == "SUPER" )
00096                     DCOPParent = s.firstChild().toText().data();
00097             }
00098         
00099             // get function table
00100             QValueList<Function> functions;
00101             s = n.nextSibling().toElement();
00102             for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00103                 if ( s.tagName() == "FUNC" ) {
00104                     QDomElement r = s.firstChild().toElement();
00105                     Q_ASSERT( r.tagName() == "TYPE" );
00106                     QString funcType = r.firstChild().toText().data();
00107                     r = r.nextSibling().toElement();
00108                     Q_ASSERT ( r.tagName() == "NAME" );
00109                     QString funcName = r.firstChild().toText().data();
00110                     QStringList argtypes;
00111                     QStringList argnames;
00112                     r = r.nextSibling().toElement();
00113                     for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00114                         Q_ASSERT( r.tagName() == "ARG" );
00115                         QDomElement a = r.firstChild().toElement();
00116                         Q_ASSERT( a.tagName() == "TYPE" );
00117                         argtypes.append( a.firstChild().toText().data() );
00118                         a = a.nextSibling().toElement();
00119                         if ( !a.isNull() ) {
00120                             Q_ASSERT( a.tagName() == "NAME" );
00121                             argnames.append( a.firstChild().toText().data() );
00122                         } else {
00123                             argnames.append( QString::null );
00124                         }
00125                     }
00126                     funcName += '(';
00127                     QString fullFuncName = funcName;
00128                     bool first = TRUE;
00129                     QStringList::Iterator ittype = argtypes.begin();
00130                     QStringList::Iterator itname = argnames.begin();
00131                     while ( ittype != argtypes.end() && itname != argnames.end() ) {
00132                         if ( !first ) {
00133                             funcName += ',';
00134                             fullFuncName += ',';
00135                         }
00136                         first = FALSE;
00137                         funcName += *ittype;
00138                         fullFuncName += *ittype;
00139                         if ( ! (*itname).isEmpty() ) {
00140                             fullFuncName += ' ';
00141                             fullFuncName += *itname;
00142                         }
00143                         ++ittype;
00144                         ++itname;
00145                     }
00146                     funcName += ')';
00147                     fullFuncName += ')';
00148                     functions.append( Function( funcType, funcName, fullFuncName ) );
00149                 }
00150             }
00151 
00152             // create static tables
00153         
00154             int fhash = functions.count() + 1;
00155             for ( int i = 0; primes[i]; i++ ) {
00156                 if ( primes[i] >  static_cast<int>(functions.count()) ) {
00157                     fhash = primes[i];
00158                     break;
00159                 }
00160             }
00161         
00162             str << "#include <kdatastream.h>" << endl;
00163 
00164             bool useHashing = functions.count() > 7;
00165             if ( useHashing ) {
00166                 str << "#include <qasciidict.h>" << endl;
00167             }
00168 
00169             QString classNameFull = className; // class name with possible namespaces prepended
00170                                                // namespaces will be removed from className now
00171             int namespace_count = 0;
00172             QString namespace_tmp = className;
00173             str << endl;
00174             for(;;) {
00175                 int pos = namespace_tmp.find( "::" );
00176                 if( pos < 0 )
00177                     {
00178                     className = namespace_tmp;
00179                     break;
00180                     }
00181                 str << "namespace " << namespace_tmp.left( pos ) << " {" << endl;
00182                 ++namespace_count;
00183                 namespace_tmp = namespace_tmp.mid( pos + 2 );
00184             }
00185 
00186             str << endl;
00187 
00188             if ( useHashing ) {
00189                 str << "static const int " << className << "_fhash = " << fhash << ";" << endl;
00190             }
00191             str << "static const char* const " << className << "_ftable[" << functions.count() + 1 << "][3] = {" << endl;
00192             for( QValueList<Function>::Iterator it = functions.begin(); it != functions.end(); ++it ){
00193                 str << "    { \"" << (*it).type << "\", \"" << (*it).name << "\", \"" << (*it).fullName << "\" }," << endl;
00194             }
00195             str << "    { 0, 0, 0 }" << endl;
00196             str << "};" << endl;
00197         
00198             str << endl;
00199         
00200         
00201             // Write dispatcher
00202             str << "bool " << className;
00203             str << "::process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)" << endl;
00204             str << "{" << endl;
00205             if ( useHashing ) {
00206                 str << "    static QAsciiDict<int>* fdict = 0;" << endl;
00207         
00208                 str << "    if ( !fdict ) {" << endl;
00209                 str << "\tfdict = new QAsciiDict<int>( " << className << "_fhash, TRUE, FALSE );" << endl;
00210                 str << "\tfor ( int i = 0; " << className << "_ftable[i][1]; i++ )" << endl;
00211                 str << "\t    fdict->insert( " << className << "_ftable[i][1],  new int( i ) );" << endl;
00212                 str << "    }" << endl;
00213         
00214                 str << "    int* fp = fdict->find( fun );" << endl;
00215                 str << "    switch ( fp?*fp:-1) {" << endl;
00216             }
00217             s = n.nextSibling().toElement();
00218             int fcount = 0; // counter of written functions
00219             bool firstFunc = TRUE;
00220             for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00221                 if ( s.tagName() == "FUNC" ) {
00222                     QDomElement r = s.firstChild().toElement();
00223                     Q_ASSERT( r.tagName() == "TYPE" );
00224                     QString funcType = r.firstChild().toText().data();
00225                     if ( funcType == "ASYNC" )
00226                         funcType = "void";
00227                     r = r.nextSibling().toElement();
00228                     Q_ASSERT ( r.tagName() == "NAME" );
00229                     QString funcName = r.firstChild().toText().data();
00230                     QStringList args;
00231                     QStringList argtypes;
00232                     r = r.nextSibling().toElement();
00233                     for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00234                         Q_ASSERT( r.tagName() == "ARG" );
00235                         QDomElement a = r.firstChild().toElement();
00236                         Q_ASSERT( a.tagName() == "TYPE" );
00237                         argtypes.append( a.firstChild().toText().data() );
00238                         args.append( QString("arg" ) + QString::number( args.count() ) );
00239                     }
00240                     QString plainFuncName = funcName;
00241                     funcName += '(';
00242                     bool first = TRUE;
00243                     for( QStringList::Iterator argtypes_count = argtypes.begin(); argtypes_count != argtypes.end(); ++argtypes_count ){
00244                         if ( !first )
00245                             funcName += ',';
00246                         first = FALSE;
00247                         funcName += *argtypes_count;
00248                     }
00249                     funcName += ')';
00250                         
00251                     if ( useHashing ) {
00252                         str << "    case " << fcount << ": { // " << funcType << " " << funcName << endl;
00253                     } else {
00254                         if ( firstFunc )
00255                             str << "    if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl;
00256                         else
00257                             str << " else if ( fun == " << className << "_ftable[" << fcount << "][1] ) { // " << funcType << " " << funcName << endl;
00258                         firstFunc = FALSE;
00259                     }
00260                     if ( !args.isEmpty() ) {
00261                         QStringList::Iterator ittypes = argtypes.begin();
00262                         QStringList::Iterator args_count;
00263                         for( args_count = args.begin(); args_count != args.end(); ++args_count ){
00264                             str << '\t'<< *ittypes << " " << *args_count << ";" <<  endl;
00265                             ++ittypes;
00266                         }
00267                         str << "\tQDataStream arg( data, IO_ReadOnly );" << endl;
00268                         for( args_count = args.begin(); args_count != args.end(); ++args_count ){
00269                             str << "\targ >> " << *args_count << ";" << endl;
00270                         }
00271                     }
00272 
00273                     str << "\treplyType = " << className << "_ftable[" << fcount++ << "][0]; " << endl;
00274                     if ( funcType == "void" ) {
00275                         str << '\t' << plainFuncName << '(';
00276                     } else {
00277                         str << "\tQDataStream _replyStream( replyData, IO_WriteOnly );"  << endl;
00278                         str << "\t_replyStream << " << plainFuncName << '(';
00279                     }
00280 
00281                     first = TRUE;
00282                     for ( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
00283                         if ( !first )
00284                             str << ", ";
00285                         first = FALSE;
00286                         str << *args_count;
00287                     }
00288                     str << " );" << endl;
00289                     if (useHashing ) {
00290                         str << "    } break;" << endl;
00291                     } else {
00292                         str << "    }";
00293                     }
00294                 }
00295             }
00296 
00297             // only open an 'else' clause if there were one or more functions
00298             if ( fcount > 0 ) {
00299                 if ( useHashing ) {
00300                     str << "    default: " << endl;
00301                 } else {
00302                     str << " else {" << endl;
00303                 }
00304             }
00305             
00306             // if no DCOP function was called, delegate the request to the parent
00307             if (!DCOPParent.isEmpty()) {
00308                 str << "\treturn " << DCOPParent << "::process( fun, data, replyType, replyData );" << endl;
00309             } else {
00310                 str << "\treturn FALSE;" << endl;
00311             }
00312 
00313             // only close the 'else' clause and add the default 'return TRUE'
00314             // (signifying a DCOP method was found and called) if there were
00315             // one or more functions.
00316             if ( fcount > 0 ) {
00317                 str << "    }" << endl;
00318                 str << "    return TRUE;" << endl;
00319             }
00320 
00321             // close the 'process' function
00322             str << "}" << endl << endl;
00323         
00324             str << "QCStringList " << className;
00325             str << "::interfaces()" << endl;
00326             str << "{" << endl;
00327             if (!DCOPParent.isEmpty()) {
00328                 str << "    QCStringList ifaces = " << DCOPParent << "::interfaces();" << endl;
00329             } else {
00330                 str << "    QCStringList ifaces;" << endl;
00331             }
00332             str << "    ifaces += \"" << classNameFull << "\";" << endl;
00333             str << "    return ifaces;" << endl;
00334             str << "}" << endl << endl;
00335             
00336             
00337             str << "QCStringList " << className;
00338             str << "::functions()" << endl;
00339             str << "{" << endl;
00340             if (!DCOPParent.isEmpty()) {
00341                 str << "    QCStringList funcs = " << DCOPParent << "::functions();" << endl;
00342             } else {
00343                 str << "    QCStringList funcs;" << endl;
00344             }
00345             str << "    for ( int i = 0; " << className << "_ftable[i][2]; i++ ) {" << endl;
00346             str << "\tQCString func = " << className << "_ftable[i][0];" << endl;
00347             str << "\tfunc += ' ';" << endl;
00348             str << "\tfunc += " << className << "_ftable[i][2];" << endl;
00349             str << "\tfuncs << func;" << endl;
00350             str << "    }" << endl;
00351             str << "    return funcs;" << endl;
00352             str << "}" << endl << endl;
00353             
00354             // Add signal stubs
00355 
00356             // Go over all children of the CLASS tag
00357             for(s = e.firstChild().toElement(); !s.isNull(); s = s.nextSibling().toElement() ) {
00358                 if (s.tagName() == "SIGNAL") {
00359                     QDomElement r = s.firstChild().toElement();
00360                     Q_ASSERT( r.tagName() == "TYPE" );
00361                     QString result = r.firstChild().toText().data();
00362                     if ( r.hasAttribute( "qleft" ) )
00363                         str << r.attribute("qleft") << " ";
00364                     str << result;
00365                     if ( r.hasAttribute( "qright" ) )
00366                         str << r.attribute("qright") << " ";
00367                     else
00368                         str << " ";
00369 
00370                     r = r.nextSibling().toElement();
00371                     Q_ASSERT ( r.tagName() == "NAME" );
00372                     QString funcName = r.firstChild().toText().data();
00373                     str << className << "::" << funcName << "(";
00374 
00375                     QStringList args;
00376                     QStringList argtypes;
00377                     bool first = TRUE;
00378                     r = r.nextSibling().toElement();
00379                     for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00380                         if ( !first )
00381                             str << ", ";
00382                         else
00383                             str << " ";
00384                         first = FALSE;
00385                         Q_ASSERT( r.tagName() == "ARG" );
00386                         QDomElement a = r.firstChild().toElement();
00387                         Q_ASSERT( a.tagName() == "TYPE" );
00388                         if ( a.hasAttribute( "qleft" ) )
00389                             str << a.attribute("qleft") << " ";
00390                         argtypes.append( a.firstChild().toText().data() );
00391                         str << argtypes.last();
00392                         if ( a.hasAttribute( "qright" ) )
00393                             str << a.attribute("qright") << " ";
00394                         else
00395                             str << " ";
00396                         args.append( QString("arg" ) + QString::number( args.count() ) ) ;
00397                         str << args.last();
00398                     }
00399                     if ( !first )
00400                         str << " ";
00401                     str << ")";
00402 
00403                     if ( s.hasAttribute("qual") )
00404                         str << " " << s.attribute("qual");
00405                     str << endl;
00406                 
00407                     str << "{" << endl ;
00408 
00409                     funcName += "(";
00410                     first = TRUE;
00411                     for( QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it ){
00412                         if ( !first )
00413                             funcName += ",";
00414                         first = FALSE;
00415                         funcName += *it;
00416                     }
00417                     funcName += ")";
00418                 
00419                     if ( result != "void" )
00420                        qFatal("Error in DCOP signal %s::%s: DCOP signals can not return values.", className.latin1(), funcName.latin1());
00421                 
00422                     str << "    QByteArray data;" << endl;
00423                     if ( !args.isEmpty() ) {
00424                         str << "    QDataStream arg( data, IO_WriteOnly );" << endl;
00425                         for( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){
00426                             str << "    arg << " << *args_count << ";" << endl;
00427                         }
00428                     }
00429 
00430                     str << "    emitDCOPSignal( \"" << funcName << "\", data );" << endl;
00431 
00432                     str << "}" << endl << endl;
00433                 
00434                 } // if SIGNAL tag
00435             } // for each class function 
00436 
00437             for(;
00438                  namespace_count > 0;
00439                  --namespace_count )
00440                 str << "} // namespace" << endl;
00441             str << endl;
00442 
00443         } // if CLASS tag
00444     } // for each CLASS-level tag
00445         
00446     skel.close();
00447 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:42:42 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001