TDE base libraries and programs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gen.cpp 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. /*
  2. * This file is part of the Trinity Desktop Environment
  3. *
  4. * Original file taken from the OpenSUSE tdebase builds
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. #include <tqfile.h>
  21. #include <tqstring.h>
  22. #include <tqvaluelist.h>
  23. #include <stdlib.h>
  24. // TODO includes, forwards
  25. /*
  26. FUNCTION <name>
  27. RETURN_TYPE <type>
  28. DELAYED_RETURN - use DCOP transaction in kded module, function will take some time to finish
  29. SKIP_QT - don't generate in qt file
  30. ONLY_QT - generate only in qt file
  31. ADD_APPINFO - generate wmclass arguments
  32. ARG <name>
  33. TYPE <type>
  34. ORIG_TYPE <type> - for example when the function accepts TQWidget*, but WId is really used
  35. ORIG_CONVERSION <conversion>
  36. IGNORE
  37. NEEDS_DEREF
  38. CONST_REF
  39. OUT_ARGUMENT
  40. CONVERSION <function>
  41. BACK_CONVERSION <function> - for out arguments
  42. CREATE <function> - doesn't exist in TQt, create in qtkde using function
  43. PARENT - the argument is a parent window to be used for windows
  44. ENDARG
  45. ENDFUNCTION
  46. */
  47. struct Arg
  48. {
  49. Arg() : ignore( false ), needs_deref( false ), const_ref( false ), out_argument( false ), parent( false ) {}
  50. TQString name;
  51. TQString type;
  52. TQString orig_type;
  53. TQString orig_conversion;
  54. bool ignore;
  55. bool needs_deref;
  56. bool const_ref;
  57. bool out_argument;
  58. TQString conversion;
  59. TQString back_conversion;
  60. TQString create;
  61. bool parent;
  62. };
  63. struct Function
  64. {
  65. Function() : delayed_return( false ), skip_qt( false ), only_qt( false ), add_appinfo( false ) {}
  66. TQString name;
  67. TQString return_type;
  68. bool delayed_return;
  69. bool skip_qt;
  70. bool only_qt;
  71. bool add_appinfo;
  72. TQValueList< Arg > args;
  73. void stripNonOutArguments();
  74. void stripCreatedArguments();
  75. };
  76. void Function::stripNonOutArguments()
  77. {
  78. TQValueList< Arg > new_args;
  79. for( TQValueList< Arg >::ConstIterator it = args.begin();
  80. it != args.end();
  81. ++it )
  82. {
  83. const Arg& arg = (*it);
  84. if( arg.out_argument )
  85. new_args.append( arg );
  86. }
  87. args = new_args;
  88. }
  89. void Function::stripCreatedArguments()
  90. {
  91. TQValueList< Arg > new_args;
  92. for( TQValueList< Arg >::ConstIterator it = args.begin();
  93. it != args.end();
  94. ++it )
  95. {
  96. const Arg& arg = (*it);
  97. if( arg.create.isEmpty())
  98. new_args.append( arg );
  99. }
  100. args = new_args;
  101. }
  102. TQValueList< Function > functions;
  103. TQFile* input_file = NULL;
  104. TQTextStream* input_stream = NULL;
  105. static TQString last_line;
  106. int last_lineno = 0;
  107. #define check( arg ) my_check( __FILE__, __LINE__, arg )
  108. #define error() my_error( __FILE__, __LINE__ )
  109. void my_error( const char* file, int line )
  110. {
  111. fprintf( stderr, "Error: %s: %d\n", file, line );
  112. fprintf( stderr, "Line %d: %s\n", last_lineno, last_line.utf8().data());
  113. abort();
  114. }
  115. void my_check( const char* file, int line, bool arg )
  116. {
  117. if( !arg )
  118. my_error( file, line );
  119. }
  120. void openInputFile( const TQString& filename )
  121. {
  122. check( input_file == NULL );
  123. input_file = new TQFile( filename );
  124. printf("[INFO] Reading bindings definitions from file %s\n", filename.ascii());
  125. if( !input_file->open( IO_ReadOnly ))
  126. error();
  127. input_stream = new TQTextStream( input_file );
  128. last_lineno = 0;
  129. }
  130. TQString getInputLine()
  131. {
  132. while( !input_stream->atEnd())
  133. {
  134. TQString line = input_stream->readLine().stripWhiteSpace();
  135. ++last_lineno;
  136. last_line = line;
  137. if( line.isEmpty() || line[ 0 ] == '#' )
  138. continue;
  139. return line;
  140. }
  141. return TQString();
  142. }
  143. void closeInputFile()
  144. {
  145. delete input_stream;
  146. delete input_file;
  147. input_stream = NULL;
  148. input_file = NULL;
  149. }
  150. void parseArg( Function& function, const TQString& details )
  151. {
  152. Arg arg;
  153. arg.name = details;
  154. TQString line = getInputLine();
  155. while( !line.isNull() )
  156. {
  157. if( line.startsWith( "ENDARG" ))
  158. {
  159. check( !arg.type.isEmpty());
  160. function.args.append( arg );
  161. return;
  162. }
  163. else if( line.startsWith( "TYPE" ))
  164. {
  165. check( arg.type.isEmpty());
  166. arg.type = line.mid( strlen( "TYPE" )).stripWhiteSpace();
  167. }
  168. else if( line.startsWith( "ORIG_TYPE" ))
  169. {
  170. check( arg.orig_type.isEmpty());
  171. arg.orig_type = line.mid( strlen( "ORIG_TYPE" )).stripWhiteSpace();
  172. }
  173. else if( line.startsWith( "ORIG_CONVERSION" ))
  174. {
  175. check( arg.orig_conversion.isEmpty());
  176. arg.orig_conversion = line.mid( strlen( "ORIG_CONVERSION" )).stripWhiteSpace();
  177. }
  178. else if( line.startsWith( "IGNORE" ))
  179. {
  180. check( !arg.out_argument );
  181. arg.ignore = true;
  182. }
  183. else if( line.startsWith( "NEEDS_DEREF" ))
  184. {
  185. check( !arg.const_ref );
  186. arg.needs_deref = true;
  187. }
  188. else if( line.startsWith( "CONST_REF" ))
  189. {
  190. check( !arg.needs_deref );
  191. check( !arg.out_argument );
  192. arg.const_ref = true;
  193. }
  194. else if( line.startsWith( "OUT_ARGUMENT" ))
  195. {
  196. check( !arg.ignore );
  197. check( !arg.const_ref );
  198. arg.out_argument = true;
  199. }
  200. else if( line.startsWith( "CONVERSION" ))
  201. {
  202. check( arg.conversion.isEmpty());
  203. arg.conversion = line.mid( strlen( "CONVERSION" )).stripWhiteSpace();
  204. }
  205. else if( line.startsWith( "BACK_CONVERSION" ))
  206. {
  207. check( arg.back_conversion.isEmpty());
  208. arg.back_conversion = line.mid( strlen( "BACK_CONVERSION" )).stripWhiteSpace();
  209. }
  210. else if( line.startsWith( "CREATE" ))
  211. {
  212. check( arg.create.isEmpty());
  213. arg.create = line.mid( strlen( "CREATE" )).stripWhiteSpace();
  214. }
  215. else if( line.startsWith( "PARENT" ))
  216. {
  217. arg.parent = true;
  218. }
  219. else
  220. error();
  221. line = getInputLine();
  222. }
  223. error();
  224. }
  225. void parseFunction( const TQString& details )
  226. {
  227. Function function;
  228. function.name = details;
  229. TQString line = getInputLine();
  230. while( !line.isNull() )
  231. {
  232. if( line.startsWith( "ENDFUNCTION" ))
  233. {
  234. if( function.add_appinfo )
  235. {
  236. Arg arg;
  237. arg.name = "wmclass1";
  238. arg.type = "TQCString";
  239. arg.const_ref = true;
  240. arg.create = "tqAppName";
  241. function.args.append( arg );
  242. arg.name = "wmclass2";
  243. arg.create = "tqAppClass";
  244. function.args.append( arg );
  245. }
  246. check( !function.return_type.isEmpty());
  247. functions.append( function );
  248. return;
  249. }
  250. else if( line.startsWith( "RETURN_TYPE" ))
  251. {
  252. check( function.return_type.isEmpty());
  253. function.return_type = line.mid( strlen( "RETURN_TYPE" )).stripWhiteSpace();
  254. }
  255. else if( line.startsWith( "DELAYED_RETURN" ))
  256. function.delayed_return = true;
  257. else if( line.startsWith( "SKIP_QT" ))
  258. function.skip_qt = true;
  259. else if( line.startsWith( "ONLY_QT" ))
  260. function.only_qt = true;
  261. else if( line.startsWith( "ADD_APPINFO" ))
  262. function.add_appinfo = true;
  263. else if( line.startsWith( "ARG" ))
  264. {
  265. parseArg( function, line.mid( strlen( "ARG" )).stripWhiteSpace());
  266. }
  267. else
  268. error();
  269. line = getInputLine();
  270. }
  271. error();
  272. }
  273. void parse(TQString filename)
  274. {
  275. openInputFile( filename );
  276. TQString line = getInputLine();
  277. while( !line.isNull() )
  278. {
  279. if( line.startsWith( "FUNCTION" ))
  280. {
  281. parseFunction( line.mid( strlen( "FUNCTION" )).stripWhiteSpace());
  282. }
  283. else
  284. error();
  285. line = getInputLine();
  286. }
  287. closeInputFile();
  288. }
  289. TQString makeIndent( int indent )
  290. {
  291. return indent > 0 ? TQString().fill( ' ', indent ) : "";
  292. }
  293. void generateFunction( TQTextStream& stream, const Function& function, const TQString name,
  294. int indent, bool staticf, bool orig_type, bool ignore_deref, int ignore_level )
  295. {
  296. TQString line;
  297. line += makeIndent( indent );
  298. if( staticf )
  299. line += "static ";
  300. line += function.return_type + " " + name + "(";
  301. bool need_comma = false;
  302. for( TQValueList< Arg >::ConstIterator it = function.args.begin();
  303. it != function.args.end();
  304. ++it )
  305. {
  306. const Arg& arg = (*it);
  307. if( ignore_level >= 2 && arg.ignore )
  308. continue;
  309. if( need_comma )
  310. {
  311. line += ",";
  312. if( line.length() > 80 )
  313. {
  314. stream << line << "\n";
  315. line = makeIndent( indent + 4 );
  316. }
  317. else
  318. line += " ";
  319. }
  320. else
  321. line += " ";
  322. need_comma = true;
  323. if( orig_type && !arg.orig_type.isEmpty())
  324. line += arg.orig_type;
  325. else
  326. {
  327. if( arg.const_ref )
  328. line += "const ";
  329. line += arg.type;
  330. if( !ignore_deref && arg.needs_deref )
  331. line += "*";
  332. if( arg.const_ref )
  333. line += "&";
  334. }
  335. if( ignore_level >= 1 && arg.ignore )
  336. line += " /*" + arg.name + "*/";
  337. else
  338. line += " " + arg.name;
  339. }
  340. line += " )";
  341. stream << line;
  342. }
  343. void generateTQtH()
  344. {
  345. TQFile file( "qtkdeintegration_x11_p.h.gen" );
  346. if( !file.open( IO_WriteOnly ))
  347. error();
  348. TQTextStream stream( &file );
  349. for( TQValueList< Function >::ConstIterator it = functions.begin();
  350. it != functions.end();
  351. ++it )
  352. {
  353. Function f = *it;
  354. if( f.skip_qt )
  355. continue;
  356. f.stripCreatedArguments();
  357. generateFunction( stream, f, f.name, 8,
  358. true /*static*/, true /*orig type*/, false /*ignore deref*/, 0 /*ignore level*/ );
  359. stream << ";\n";
  360. }
  361. }
  362. void generateTQtCpp()
  363. {
  364. TQFile file( "qtkdeintegration_x11.cpp.gen" );
  365. if( !file.open( IO_WriteOnly ))
  366. error();
  367. TQTextStream stream( &file );
  368. for( TQValueList< Function >::ConstIterator it = functions.begin();
  369. it != functions.end();
  370. ++it )
  371. {
  372. Function f = *it;
  373. if( f.only_qt )
  374. continue;
  375. f.stripCreatedArguments();
  376. generateFunction( stream, f, "(*qtkde_" + f.name + ")", 0,
  377. true /*static*/, false /*orig type*/, false /*ignore deref*/, 0 /*ignore level*/ );
  378. stream << ";\n";
  379. }
  380. stream <<
  381. "\n"
  382. "void TQKDEIntegration::initLibrary()\n"
  383. " {\n"
  384. " if( !inited )\n"
  385. " {\n"
  386. " enable = false;\n"
  387. " inited = true;\n"
  388. " TQString libpath = findLibrary();\n"
  389. " if( libpath.isEmpty())\n"
  390. " return;\n"
  391. " TQLibrary lib( libpath );\n"
  392. " if( !TQFile::exists( lib.library())) // avoid stupid TQt warning\n"
  393. " return;\n"
  394. " lib.setAutoUnload( false );\n";
  395. for( TQValueList< Function >::ConstIterator it = functions.begin();
  396. it != functions.end();
  397. ++it )
  398. {
  399. Function function = *it;
  400. if( function.only_qt )
  401. continue;
  402. stream << makeIndent( 8 ) + "qtkde_" + function.name + " = (\n";
  403. function.stripCreatedArguments();
  404. generateFunction( stream, function, "(*)", 12,
  405. false /*static*/, false /*orig type*/, false /*ignore deref*/, 0 /*ignore level*/ );
  406. stream << "\n" + makeIndent( 12 ) + ")\n";
  407. stream << makeIndent( 12 ) + "lib.resolve(\"" + (*it).name + "\");\n";
  408. stream << makeIndent( 8 ) + "if( qtkde_" + (*it).name + " == NULL )\n";
  409. stream << makeIndent( 12 ) + "return;\n";
  410. }
  411. stream <<
  412. " enable = qtkde_initializeIntegration();\n"
  413. " }\n"
  414. " }\n"
  415. "\n";
  416. for( TQValueList< Function >::ConstIterator it1 = functions.begin();
  417. it1 != functions.end();
  418. ++it1 )
  419. {
  420. Function function = *it1;
  421. if( function.skip_qt || function.only_qt )
  422. continue;
  423. function.stripCreatedArguments();
  424. generateFunction( stream, function, "QKDEIntegration::" + function.name, 0,
  425. false /*static*/, true /*orig type*/, false /*ignore deref*/, 0 /*ignore level*/ );
  426. stream << "\n";
  427. stream << makeIndent( 4 ) + "{\n";
  428. stream << makeIndent( 4 ) + "return qtkde_" + function.name + "(\n";
  429. stream << makeIndent( 8 );
  430. bool need_comma = false;
  431. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  432. it2 != function.args.end();
  433. ++it2 )
  434. {
  435. const Arg& arg = (*it2);
  436. if( need_comma )
  437. stream << ", ";
  438. need_comma = true;
  439. if( !arg.orig_conversion.isEmpty())
  440. {
  441. stream << arg.orig_conversion + "( " + arg.name + " )";
  442. }
  443. else
  444. stream << arg.name;
  445. }
  446. stream << " );\n";
  447. stream << makeIndent( 4 ) + "}\n";
  448. }
  449. }
  450. void generateTQt()
  451. {
  452. generateTQtH();
  453. generateTQtCpp();
  454. }
  455. void generateTQtKde()
  456. {
  457. TQFile file( "tqtkde_functions.cpp" );
  458. if( !file.open( IO_WriteOnly ))
  459. error();
  460. TQTextStream stream( &file );
  461. for( TQValueList< Function >::ConstIterator it1 = functions.begin();
  462. it1 != functions.end();
  463. ++it1 )
  464. {
  465. const Function& function = *it1;
  466. if( function.only_qt )
  467. continue;
  468. Function stripped_function = function;
  469. stripped_function.stripCreatedArguments();
  470. stream << "extern \"C\"\n";
  471. generateFunction( stream, stripped_function, stripped_function.name, 0,
  472. false /*static*/, false /*orig type*/, false /*ignore deref*/, 1 /*ignore level*/ );
  473. stream << "\n";
  474. stream <<
  475. " {\n"
  476. " if( tqt_xdisplay() != NULL )\n"
  477. " XSync( tqt_xdisplay(), False );\n";
  478. TQString parent_arg;
  479. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  480. it2 != function.args.end();
  481. ++it2 )
  482. {
  483. const Arg& arg = (*it2);
  484. if( arg.ignore )
  485. continue;
  486. if( arg.parent )
  487. {
  488. parent_arg = arg.name;
  489. break;
  490. }
  491. }
  492. if( !parent_arg.isEmpty())
  493. {
  494. stream << " if( " << parent_arg << " == 0 )\n";
  495. stream << " DCOPRef( \"kded\", \"MainApplication-Interface\" ).call( \"updateUserTimestamp\", tqt_x_time );\n";
  496. }
  497. stream <<
  498. " TQByteArray data, replyData;\n"
  499. " TQCString replyType;\n";
  500. if( !function.args.isEmpty())
  501. {
  502. stream << " TQDataStream datastream( data, IO_WriteOnly );\n";
  503. stream << " datastream";
  504. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  505. it2 != function.args.end();
  506. ++it2 )
  507. {
  508. const Arg& arg = (*it2);
  509. if( arg.ignore )
  510. continue;
  511. stream << " << ";
  512. if( !(arg.conversion).isNull() )
  513. stream << arg.conversion + "( ";
  514. if( !arg.create.isEmpty())
  515. stream << arg.create + "()";
  516. else
  517. {
  518. if( arg.needs_deref )
  519. stream << "( " << arg.name << " != NULL ? *" << arg.name << " : " << arg.type << "())";
  520. else
  521. stream << arg.name;
  522. }
  523. if( !(arg.conversion).isNull() )
  524. stream << " )";
  525. }
  526. stream << ";\n";
  527. }
  528. stream << " if( !dcopClient()->call( \"kded\", \"kdeintegration\",\"" + function.name + "(";
  529. bool need_comma = false;
  530. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  531. it2 != function.args.end();
  532. ++it2 )
  533. {
  534. const Arg& arg = (*it2);
  535. if( arg.ignore )
  536. continue;
  537. if( need_comma )
  538. stream << ",";
  539. need_comma = true;
  540. stream << arg.type;
  541. }
  542. stream << ")\", data, replyType, replyData, true ))\n";
  543. stream << " {\n";
  544. if( function.return_type != "void" )
  545. {
  546. stream << " " + function.return_type << " ret;\n";
  547. stream << " dcopTypeInit( ret ); // set to false/0/whatever\n";
  548. stream << " return ret;\n";
  549. }
  550. else
  551. stream << " return;\n";
  552. stream << " }\n";
  553. bool return_data = false;
  554. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  555. !return_data && it2 != function.args.end();
  556. ++it2 )
  557. {
  558. if( (*it2).out_argument )
  559. return_data = true;
  560. }
  561. if( return_data || function.return_type != "void" )
  562. stream << " TQDataStream replystream( replyData, IO_ReadOnly );\n";
  563. if( function.return_type != "void" )
  564. {
  565. stream << " " + function.return_type << " ret;\n";
  566. stream << " replystream >> ret;\n";
  567. }
  568. if( return_data )
  569. {
  570. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  571. it2 != function.args.end();
  572. ++it2 )
  573. {
  574. const Arg& arg = (*it2);
  575. if( arg.out_argument && arg.needs_deref )
  576. stream << " " << arg.type << " " << arg.name + "_dummy;\n";
  577. }
  578. stream << " replystream";
  579. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  580. it2 != function.args.end();
  581. ++it2 )
  582. {
  583. const Arg& arg = (*it2);
  584. if( arg.out_argument )
  585. {
  586. stream << " >> ";
  587. if( !(arg.back_conversion).isNull() )
  588. stream << arg.name + "_dummy";
  589. else
  590. {
  591. if( arg.needs_deref )
  592. stream << "( " << arg.name << " != NULL ? *" << arg.name << " : " << arg.name << "_dummy )";
  593. else
  594. stream << arg.name;
  595. }
  596. }
  597. }
  598. stream << ";\n";
  599. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  600. it2 != function.args.end();
  601. ++it2 )
  602. {
  603. const Arg& arg = (*it2);
  604. if( arg.out_argument && (!(arg.back_conversion).isNull()) )
  605. stream << " if( " << arg.name << " != NULL )\n"
  606. << makeIndent( 8 ) << "*" << arg.name << " = " << arg.back_conversion << "( " << arg.name + "_dummy );\n";
  607. }
  608. }
  609. if( function.return_type != "void" )
  610. stream << " return ret;\n";
  611. stream << " }\n";
  612. stream << "\n";
  613. }
  614. }
  615. void generateKdeDcop( TQTextStream& stream )
  616. {
  617. stream <<
  618. "bool Module::process(const TQCString &fun, const TQByteArray &data,\n"
  619. " TQCString &replyType, TQByteArray &replyData)\n"
  620. " {\n";
  621. for( TQValueList< Function >::ConstIterator it1 = functions.begin();
  622. it1 != functions.end();
  623. ++it1 )
  624. {
  625. const Function& function = *it1;
  626. if( function.only_qt )
  627. continue;
  628. stream << " if( fun == \"" + function.name + "(";
  629. bool need_comma = false;
  630. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  631. it2 != function.args.end();
  632. ++it2 )
  633. {
  634. const Arg& arg = (*it2);
  635. if( arg.ignore )
  636. continue;
  637. if( need_comma )
  638. stream << ",";
  639. need_comma = true;
  640. stream << arg.type;
  641. }
  642. stream << ")\" )\n";
  643. stream << " {\n";
  644. if( function.delayed_return )
  645. stream << " pre_" + function.name + "( data );\n";
  646. else
  647. {
  648. stream << " pre_" + function.name + "( data, replyData );\n";
  649. stream << " replyType = \"" << function.return_type << "\";\n";
  650. }
  651. stream << " return true;\n";
  652. stream << " }\n";
  653. }
  654. stream <<
  655. " return KDEDModule::process( fun, data, replyType, replyData );\n"
  656. " }\n"
  657. "\n";
  658. stream <<
  659. "QCStringList Module::functions()\n"
  660. " {\n"
  661. " QCStringList funcs = KDEDModule::functions();\n";
  662. for( TQValueList< Function >::ConstIterator it1 = functions.begin();
  663. it1 != functions.end();
  664. ++it1 )
  665. {
  666. const Function& function = *it1;
  667. if( function.only_qt )
  668. continue;
  669. stream << " funcs << \"" + function.name + "(";
  670. bool need_comma = false;
  671. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  672. it2 != function.args.end();
  673. ++it2 )
  674. {
  675. const Arg& arg = (*it2);
  676. if( arg.ignore )
  677. continue;
  678. if( need_comma )
  679. stream << ",";
  680. need_comma = true;
  681. stream << arg.type;
  682. }
  683. stream << ")\";\n";
  684. }
  685. stream <<
  686. " return funcs;\n"
  687. " }\n"
  688. "\n"
  689. "QCStringList Module::interfaces()\n"
  690. " {\n"
  691. " QCStringList ifaces = KDEDModule::interfaces();\n"
  692. " ifaces << \"KDEIntegration\";\n"
  693. " return ifaces;\n"
  694. " }\n"
  695. "\n";
  696. }
  697. void generateKdePreStub( TQTextStream& stream )
  698. {
  699. for( TQValueList< Function >::ConstIterator it1 = functions.begin();
  700. it1 != functions.end();
  701. ++it1 )
  702. {
  703. const Function& function = *it1;
  704. if( function.only_qt )
  705. continue;
  706. stream << "void Module::pre_" + function.name + "( const TQByteArray& "
  707. + ( function.args.isEmpty() ? "" : "data" )
  708. + ( function.delayed_return ? "" : ", TQByteArray& replyData" )
  709. + " )\n";
  710. stream << " {\n";
  711. if( function.delayed_return )
  712. {
  713. stream << " JobData job;\n";
  714. stream << " job.transaction = kapp->dcopClient()->beginTransaction();\n";
  715. stream << " job.type = JobData::" + TQString( function.name[ 0 ].upper()) + function.name.mid( 1 ) + ";\n";
  716. }
  717. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  718. it2 != function.args.end();
  719. ++it2 )
  720. {
  721. const Arg& arg = (*it2);
  722. if( arg.ignore )
  723. continue;
  724. stream << " " + arg.type + " " + arg.name + ";\n";
  725. }
  726. if( !function.args.isEmpty())
  727. {
  728. stream << " TQDataStream datastream( data, IO_ReadOnly );\n";
  729. stream << " datastream";
  730. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  731. it2 != function.args.end();
  732. ++it2 )
  733. {
  734. const Arg& arg = (*it2);
  735. if( arg.ignore )
  736. continue;
  737. stream << " >> " + arg.name;
  738. }
  739. stream << ";\n";
  740. }
  741. if( function.delayed_return )
  742. stream << " void* handle = " + function.name + "( ";
  743. else
  744. stream << " post_" + function.name + "( " + function.name + "( ";
  745. bool need_comma = false;
  746. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  747. it2 != function.args.end();
  748. ++it2 )
  749. {
  750. const Arg& arg = (*it2);
  751. if( arg.ignore )
  752. continue;
  753. if( need_comma )
  754. stream << ", ";
  755. need_comma = true;
  756. stream << arg.name;
  757. }
  758. if( function.delayed_return )
  759. {
  760. stream << " );\n";
  761. stream << " jobs[ handle ] = job;\n";
  762. }
  763. else
  764. stream << " ), replyData );\n";
  765. stream << " }\n";
  766. stream << "\n";
  767. }
  768. }
  769. void generateKdePostStub( TQTextStream& stream )
  770. {
  771. for( TQValueList< Function >::ConstIterator it1 = functions.begin();
  772. it1 != functions.end();
  773. ++it1 )
  774. {
  775. const Function& function = *it1;
  776. if( function.only_qt )
  777. continue;
  778. stream << "void Module::post_" + function.name + "( ";
  779. bool needs_comma = false;
  780. if( function.delayed_return )
  781. {
  782. stream << "void* handle";
  783. needs_comma = true;
  784. }
  785. if( function.return_type != "void" )
  786. {
  787. if( needs_comma )
  788. stream << ", ";
  789. needs_comma = true;
  790. stream << function.return_type + " ret";
  791. }
  792. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  793. it2 != function.args.end();
  794. ++it2 )
  795. {
  796. const Arg& arg = (*it2);
  797. if( arg.out_argument )
  798. {
  799. if( needs_comma )
  800. stream << ", ";
  801. needs_comma = true;
  802. stream << arg.type + " " + arg.name;
  803. }
  804. }
  805. if( !function.delayed_return )
  806. stream << ( needs_comma ? "," : "" ) << " TQByteArray& replyData";
  807. stream << " )\n";
  808. stream << " {\n";
  809. if( function.delayed_return )
  810. {
  811. stream << " assert( jobs.contains( handle ));\n";
  812. stream << " JobData job = jobs[ handle ];\n";
  813. stream << " jobs.remove( handle );\n";
  814. stream << " TQByteArray replyData;\n";
  815. stream << " TQCString replyType = \"qtkde\";\n";
  816. }
  817. bool return_data = false;
  818. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  819. !return_data && it2 != function.args.end();
  820. ++it2 )
  821. {
  822. if( (*it2).out_argument )
  823. return_data = true;
  824. }
  825. if( function.return_type != "void" || return_data )
  826. stream << " TQDataStream replystream( replyData, IO_WriteOnly );\n";
  827. if( function.return_type != "void" )
  828. stream << " replystream << ret;\n";
  829. if( return_data )
  830. {
  831. stream << " replystream";
  832. for( TQValueList< Arg >::ConstIterator it2 = function.args.begin();
  833. it2 != function.args.end();
  834. ++it2 )
  835. {
  836. const Arg& arg = (*it2);
  837. if( arg.out_argument )
  838. stream << " << " + arg.name;
  839. }
  840. stream << ";\n";
  841. }
  842. if( function.delayed_return )
  843. stream << " kapp->dcopClient()->endTransaction( job.transaction, replyType, replyData );\n";
  844. stream << " }\n";
  845. stream << "\n";
  846. }
  847. }
  848. void generateKdeStubs( TQTextStream& stream )
  849. {
  850. generateKdePreStub( stream );
  851. generateKdePostStub( stream );
  852. // TODO udelat i predbezne deklarace pro skutecne funkce?
  853. }
  854. void generateKdeCpp()
  855. {
  856. TQFile file( "module_functions.cpp" );
  857. if( !file.open( IO_WriteOnly ))
  858. error();
  859. TQTextStream stream( &file );
  860. generateKdeDcop( stream );
  861. generateKdeStubs( stream );
  862. }
  863. void generateKdeH()
  864. {
  865. TQFile file( "module_functions.h" );
  866. if( !file.open( IO_WriteOnly ))
  867. error();
  868. TQTextStream stream( &file );
  869. for( TQValueList< Function >::ConstIterator it1 = functions.begin();
  870. it1 != functions.end();
  871. ++it1 )
  872. {
  873. const Function& function = *it1;
  874. if( function.only_qt )
  875. continue;
  876. Function real_function = function;
  877. if( function.delayed_return )
  878. real_function.return_type = "void*";
  879. generateFunction( stream, real_function, real_function.name, 8,
  880. false /*static*/, false /*orig type*/, true /*ignore deref*/, 2 /*ignore level*/ );
  881. stream << ";\n";
  882. stream << makeIndent( 8 ) + "void pre_" + function.name + "( const TQByteArray& data"
  883. + ( function.delayed_return ? "" : ", TQByteArray& replyData" ) + " );\n";
  884. Function post_function = function;
  885. post_function.stripNonOutArguments();
  886. if( function.return_type != "void" )
  887. {
  888. Arg return_arg;
  889. return_arg.name = "ret";
  890. return_arg.type = function.return_type;
  891. post_function.args.prepend( return_arg );
  892. }
  893. if( function.delayed_return )
  894. {
  895. Arg handle_arg;
  896. handle_arg.name = "handle";
  897. handle_arg.type = "void*";
  898. post_function.args.prepend( handle_arg );
  899. }
  900. else
  901. {
  902. Arg handle_arg;
  903. handle_arg.name = "replyData";
  904. handle_arg.type = "TQByteArray&";
  905. post_function.args.append( handle_arg );
  906. }
  907. post_function.return_type = "void";
  908. generateFunction( stream, post_function, "post_" + post_function.name, 8,
  909. false /*static*/, false /*orig type*/, true /*ignore deref*/, 2 /*ignore level*/ );
  910. stream << ";\n";
  911. }
  912. }
  913. void generateKde()
  914. {
  915. generateKdeCpp();
  916. generateKdeH();
  917. }
  918. void generate()
  919. {
  920. generateTQt();
  921. generateTQtKde();
  922. generateKde();
  923. }
  924. int main (int argc, char *argv[])
  925. {
  926. if (argc > 1) {
  927. parse(TQString(argv[1]));
  928. }
  929. else {
  930. parse(TQString("gen.txt"));
  931. }
  932. generate();
  933. return 0;
  934. }