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 #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 created 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 << "\targ >> " << *args_count << ";" << endl; 00283 } 00284 } 00285 00286 str << "\treplyType = " << className << "_ftable[" << fcount++ << "][0]; " << endl; 00287 if ( funcType == "void" ) { 00288 str << '\t' << plainFuncName << '('; 00289 } else { 00290 str << "\tQDataStream _replyStream( replyData, IO_WriteOnly );" << endl; 00291 str << "\t_replyStream << " << plainFuncName << '('; 00292 } 00293 00294 first = true; 00295 for ( QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count ){ 00296 if ( !first ) 00297 str << ", "; 00298 first = false; 00299 str << *args_count; 00300 } 00301 str << " );" << endl; 00302 if (useHashing ) { 00303 str << " } break;" << endl; 00304 } else { 00305 str << " }"; 00306 } 00307 } 00308 00309 // only open an 'else' clause if there were one or more functions 00310 if ( fcount > 0 ) { 00311 if ( useHashing ) { 00312 str << " default: " << endl; 00313 } else { 00314 str << " else {" << endl; 00315 } 00316 } 00317 00318 // if no DCOP function was called, delegate the request to the parent 00319 if (!DCOPParent.isEmpty()) { 00320 str << "\treturn " << DCOPParent << "::process( fun, data, replyType, replyData );" << endl; 00321 } else { 00322 str << "\treturn false;" << endl; 00323 } 00324 00325 // only close the 'else' clause and add the default 'return true' 00326 // (signifying a DCOP method was found and called) if there were 00327 // one or more functions. 00328 if ( fcount > 0 ) { 00329 str << " }" << endl; 00330 str << " return true;" << endl; 00331 } 00332 00333 // close the 'process' function 00334 str << "}" << endl << endl; 00335 00336 str << "QCStringList " << className; 00337 str << "::interfaces()" << endl; 00338 str << "{" << endl; 00339 if (!DCOPParent.isEmpty()) { 00340 str << " QCStringList ifaces = " << DCOPParent << "::interfaces();" << endl; 00341 } else { 00342 str << " QCStringList ifaces;" << endl; 00343 } 00344 str << " ifaces += \"" << classNameFull << "\";" << endl; 00345 str << " return ifaces;" << endl; 00346 str << "}" << endl << endl; 00347 00348 00349 str << "QCStringList " << className; 00350 str << "::functions()" << endl; 00351 str << "{" << endl; 00352 if (!DCOPParent.isEmpty()) { 00353 str << " QCStringList funcs = " << DCOPParent << "::functions();" << endl; 00354 } else { 00355 str << " QCStringList funcs;" << endl; 00356 } 00357 str << " for ( int i = 0; " << className << "_ftable[i][2]; i++ ) {" << endl; 00358 if (functions.count() > 0) { 00359 str << "\tif (" << className << "_ftable_hiddens[i])" << endl; 00360 str << "\t continue;" << endl; 00361 } 00362 str << "\tQCString func = " << className << "_ftable[i][0];" << endl; 00363 str << "\tfunc += ' ';" << endl; 00364 str << "\tfunc += " << className << "_ftable[i][2];" << endl; 00365 str << "\tfuncs << func;" << endl; 00366 str << " }" << endl; 00367 str << " return funcs;" << endl; 00368 str << "}" << endl << endl; 00369 00370 // Add signal stubs 00371 for(s = e.firstChild().toElement(); !s.isNull(); s = s.nextSibling().toElement() ) { 00372 if (s.tagName() != "SIGNAL") 00373 continue; 00374 QDomElement r = s.firstChild().toElement(); 00375 QString result = writeType( str, r ); 00376 00377 r = r.nextSibling().toElement(); 00378 Q_ASSERT ( r.tagName() == "NAME" ); 00379 QString funcName = r.firstChild().toText().data(); 00380 str << className << "::" << funcName << "("; 00381 00382 QStringList args; 00383 QStringList argtypes; 00384 bool first = true; 00385 r = r.nextSibling().toElement(); 00386 for( ; !r.isNull(); r = r.nextSibling().toElement() ) { 00387 if ( !first ) 00388 str << ", "; 00389 else 00390 str << " "; 00391 first = false; 00392 Q_ASSERT( r.tagName() == "ARG" ); 00393 QDomElement a = r.firstChild().toElement(); 00394 QString type = writeType( str, a ); 00395 argtypes.append( type ); 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 } 00435 00436 for(; namespace_count > 0; --namespace_count ) 00437 str << "} // namespace" << endl; 00438 str << endl; 00439 } 00440 00441 skel.close(); 00442 } 00443 00444 // :set expandtab!<RETURN>:set ts=8<RETURN>:set sts=4<RETURN>:set sw=4<RETURN>
KDE Logo
This file is part of the documentation for dcop Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:21:26 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003