skel.cpp Source File (dcop Library)

| # dcop Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | 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
    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 }

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