00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <tqdom.h>
00024 #include <tqfile.h>
00025 #include <tqtextstream.h>
00026 #include <tqstring.h>
00027 #include <tqstringlist.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 TQString& t, const TQString& n, const TQString&fn, bool h )
00056 : type( t ), name( n ), fullName( fn ), hidden( h ) {}
00057 TQString type;
00058 TQString name;
00059 TQString fullName;
00060 bool hidden;
00061 };
00062
00063
00064
00065
00066
00067 void generateSkel( const TQString& idl, const TQString& filename, TQDomElement de )
00068 {
00069 TQFile skel( filename );
00070 if ( !skel.open( IO_WriteOnly ) )
00071 tqFatal("Could not write to %s", filename.local8Bit().data() );
00072
00073 TQTextStream 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 TQDomElement 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 TQDomElement n = e.firstChild().toElement();
00093 Q_ASSERT( n.tagName() == "NAME" );
00094 TQString className = n.firstChild().toText().data();
00095
00096 TQString DCOPParent;
00097 TQDomElement 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
00104 TQValueList<Function> functions;
00105 s = n.nextSibling().toElement();
00106 for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00107 if ( s.tagName() != "FUNC" )
00108 continue;
00109 TQDomElement r = s.firstChild().toElement();
00110 Q_ASSERT( r.tagName() == "TYPE" );
00111 TQString funcType = r.firstChild().toText().data();
00112 r = r.nextSibling().toElement();
00113 Q_ASSERT ( r.tagName() == "NAME" );
00114 TQString funcName = r.firstChild().toText().data();
00115 TQStringList argtypes;
00116 TQStringList argnames;
00117 r = r.nextSibling().toElement();
00118 for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00119 Q_ASSERT( r.tagName() == "ARG" );
00120 TQDomElement 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( TQString::null );
00129 }
00130 }
00131 funcName += '(';
00132 TQString fullFuncName = funcName;
00133 bool first = true;
00134 TQStringList::Iterator ittype = argtypes.begin();
00135 TQStringList::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
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 <tqasciidict.h>" << endl;
00172 }
00173
00174 TQString classNameFull = className;
00175
00176 int namespace_count = 0;
00177 TQString 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( TQValueList<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( TQValueList<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
00214 str << "bool " << className;
00215 str << "::process(const TQCString &fun, const TQByteArray &data, TQCString& replyType, TQByteArray &replyData)" << endl;
00216 str << "{" << endl;
00217 if ( useHashing ) {
00218 str << " static TQAsciiDict<int>* fdict = 0;" << endl;
00219
00220 str << " if ( !fdict ) {" << endl;
00221 str << "\tfdict = new TQAsciiDict<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;
00231 bool firstFunc = true;
00232 for( ; !s.isNull(); s = s.nextSibling().toElement() ) {
00233 if ( s.tagName() != "FUNC" )
00234 continue;
00235 TQDomElement r = s.firstChild().toElement();
00236 Q_ASSERT( r.tagName() == "TYPE" );
00237 TQString funcType = r.firstChild().toText().data();
00238 if ( funcType == "ASYNC" )
00239 funcType = "void";
00240 r = r.nextSibling().toElement();
00241 Q_ASSERT ( r.tagName() == "NAME" );
00242 TQString funcName = r.firstChild().toText().data();
00243 TQStringList args;
00244 TQStringList argtypes;
00245 r = r.nextSibling().toElement();
00246 for( ; !r.isNull(); r = r.nextSibling().toElement() ) {
00247 Q_ASSERT( r.tagName() == "ARG" );
00248 TQDomElement a = r.firstChild().toElement();
00249 Q_ASSERT( a.tagName() == "TYPE" );
00250 argtypes.append( a.firstChild().toText().data() );
00251 args.append( TQString("arg" ) + TQString::number( args.count() ) );
00252 }
00253 TQString plainFuncName = funcName;
00254 funcName += '(';
00255 bool first = true;
00256 for( TQStringList::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 TQStringList::Iterator ittypes = argtypes.begin();
00275 TQStringList::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 << "\tTQDataStream 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;
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 << "\tTQDataStream _replyStream( replyData, IO_WriteOnly );" << endl;
00292 str << "\t_replyStream << " << plainFuncName << '(';
00293 }
00294
00295 first = true;
00296 for ( TQStringList::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
00311 if ( fcount > 0 ) {
00312 if ( useHashing ) {
00313 str << " default: " << endl;
00314 } else {
00315 str << " else {" << endl;
00316 }
00317 }
00318
00319
00320 if (!DCOPParent.isEmpty()) {
00321 str << "\treturn " << DCOPParent << "::process( fun, data, replyType, replyData );" << endl;
00322 } else {
00323 str << "\treturn false;" << endl;
00324 }
00325
00326
00327
00328
00329 if ( fcount > 0 ) {
00330 str << " }" << endl;
00331 str << " return true;" << endl;
00332 }
00333
00334
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 << "\tTQCString 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
00372 for(s = e.firstChild().toElement(); !s.isNull(); s = s.nextSibling().toElement() ) {
00373 if (s.tagName() != "SIGNAL")
00374 continue;
00375 TQDomElement r = s.firstChild().toElement();
00376 TQString result = writeType( str, r );
00377
00378 r = r.nextSibling().toElement();
00379 Q_ASSERT ( r.tagName() == "NAME" );
00380 TQString funcName = r.firstChild().toText().data();
00381 str << className << "::" << funcName << "(";
00382
00383 TQStringList args;
00384 TQStringList 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 TQDomElement a = r.firstChild().toElement();
00395 TQString type = writeType( str, a );
00396 argtypes.append( type );
00397 args.append( TQString("arg" ) + TQString::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( TQStringList::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 tqFatal("Error in DCOP signal %s::%s: DCOP signals can not return values.", className.latin1(), funcName.latin1());
00422
00423 str << " TQByteArray data;" << endl;
00424 if ( !args.isEmpty() ) {
00425 str << " TQDataStream arg( data, IO_WriteOnly );" << endl;
00426 for( TQStringList::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