00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
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;
00170
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
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;
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
00298 if ( fcount > 0 ) {
00299 if ( useHashing ) {
00300 str << " default: " << endl;
00301 } else {
00302 str << " else {" << endl;
00303 }
00304 }
00305
00306
00307 if (!DCOPParent.isEmpty()) {
00308 str << "\treturn " << DCOPParent << "::process( fun, data, replyType, replyData );" << endl;
00309 } else {
00310 str << "\treturn FALSE;" << endl;
00311 }
00312
00313
00314
00315
00316 if ( fcount > 0 ) {
00317 str << " }" << endl;
00318 str << " return TRUE;" << endl;
00319 }
00320
00321
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
00355
00356
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 }
00435 }
00436
00437 for(;
00438 namespace_count > 0;
00439 --namespace_count )
00440 str << "} // namespace" << endl;
00441 str << endl;
00442
00443 }
00444 }
00445
00446 skel.close();
00447 }