kalyptus 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582
  1. #!/usr/bin/perl
  2. # KDOC -- C++ and CORBA IDL interface documentation tool.
  3. # Sirtaj Singh Kang <[email protected]>, Jan 1999.
  4. # $Id: kalyptus,v 1.1 2003/09/22 01:35:54 florian Exp $
  5. # All files in this project are distributed under the GNU General
  6. # Public License. This is Free Software.
  7. require 5.000;
  8. use Carp;
  9. use Getopt::Long;
  10. use File::Basename;
  11. use strict;
  12. use Ast;
  13. use kdocUtil;
  14. use kdocAstUtil;
  15. use kdocParseDoc;
  16. use vars qw/ %rootNodes $declNodeType %options @formats_wanted
  17. @includeclasses $includeclasses $skipInternal %defines $defines $match_qt_defines
  18. $libdir $libname $outputdir @libs $striphpath $doPrivate $readstdin
  19. $Version $quiet $debug $debuggen $parseonly $currentfile $cSourceNode $exe
  20. %formats %flagnames $rootNode @classStack $cNode
  21. $lastLine $docNode @includes $cpp $defcppcmd $cppcmd $docincluded
  22. $inExtern %stats %definitions @inputqueue @codeqobject /;
  23. ## globals
  24. %rootNodes = (); # root nodes for each file type
  25. $declNodeType = undef; # last declaration type
  26. # All options
  27. %options = (); # hash of options (set getopt below)
  28. @formats_wanted = ();
  29. $libdir = $ENV{KDOCLIBS};
  30. $libname = "";
  31. $outputdir = ".";
  32. @libs = (); # list of includes
  33. $striphpath = 0;
  34. @includeclasses = (); # names of classes to include
  35. $includeclasses = "";
  36. $doPrivate = 0;
  37. $Version = "0.9";
  38. $quiet = 0;
  39. $debug = 0;
  40. $debuggen = 0;
  41. $parseonly = 0;
  42. $currentfile = "";
  43. $cpp = 0;
  44. $defcppcmd = "g++ -Wp,-C -E";
  45. $cppcmd = "";
  46. $exe = basename $0;
  47. @inputqueue = ();
  48. @codeqobject = split "\n", <<CODE;
  49. public:
  50. virtual QMetaObject *metaObject() const;
  51. virtual const char *className() const;
  52. virtual void* qt_cast( const char* );
  53. virtual bool qt_invoke( int, QUObject* );
  54. virtual bool qt_emit( int, QUObject* );
  55. virtual bool qt_property( int, int, QVariant* );
  56. static QMetaObject* staticMetaObject();
  57. QObject* qObject();
  58. static QString tr( const char *, const char * = 0 );
  59. static QString trUtf8( const char *, const char * = 0 );
  60. private:
  61. CODE
  62. # Supported formats
  63. %formats = ( "java" => "kalyptusCxxToJava", "c" => "kalyptusCxxToC",
  64. "objc" => "kalyptusCxxToObjc", "ruby" => "kalyptusCxxToRuby",
  65. "smoke" => "kalyptusCxxToSmoke", "csharp" => "kalyptusCxxToCSharp",
  66. "ECMA" => "kalyptusCxxToECMA", "pascal" => "kalyptusCxxToPas" );
  67. # these are for expansion of method flags
  68. %flagnames = ( v => 'virtual', 's' => 'static', p => 'pure',
  69. c => 'const', l => 'slot', i => 'inline', n => 'signal' );
  70. %definitions = {
  71. _STYLE_CDE => '',
  72. _STYLE_MOTIF => '',
  73. _STYLE_MOTIF_PLUS => '',
  74. PLUS => '',
  75. _STYLE_PLATINUM => '',
  76. _STYLE_SGI => '',
  77. _STYLE_WINDOWS => '',
  78. QT_STATIC_CONST => 'static const',
  79. Q_EXPORT => '',
  80. Q_REFCOUNT => '',
  81. QM_EXPORT_CANVAS => '',
  82. QM_EXPORT_DNS => '',
  83. QM_EXPORT_ICONVIEW => '',
  84. QM_EXPORT_NETWORK => '',
  85. QM_EXPORT_SQL => '',
  86. QM_EXPORT_WORKSPACE => '',
  87. QT_NO_REMOTE => 'QT_NO_REMOTE',
  88. QT_ACCESSIBILITY_SUPPORT => 'QT_ACCESSIBILITY_SUPPORT',
  89. Q_WS_X11 => 'Q_WS_X11',
  90. Q_DISABLE_COPY => 'Q_DISABLE_COPY',
  91. Q_WS_QWS => 'undef',
  92. Q_WS_MAC => 'undef',
  93. Q_OBJECT => <<'CODE',
  94. public:
  95. virtual QMetaObject *metaObject() const;
  96. virtual const char *className() const;
  97. virtual bool qt_invoke( int, QUObject* );
  98. virtual bool qt_emit( int, QUObject* );
  99. static QString tr( const char *, const char * = 0 );
  100. static QString trUtf8( const char *, const char * = 0 );
  101. private:
  102. CODE
  103. };
  104. =head1 KDOC -- Source documentation tool
  105. Sirtaj Singh Kang <[email protected]>, Dec 1998.
  106. =cut
  107. # read options
  108. Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
  109. GetOptions( \%options,
  110. "format|f=s", \@formats_wanted,
  111. "url|u=s",
  112. "skip-internal", \$skipInternal,
  113. "skip-deprecated|e",
  114. "document-all|a",
  115. "compress|z",
  116. # HTML options
  117. "html-cols=i",
  118. "html-logo=s",
  119. "strip-h-path", \$striphpath,
  120. "outputdir|d=s", \$outputdir,
  121. "stdin|i", \$readstdin,
  122. "name|n=s", \$libname,
  123. "help|h", \&show_usage,
  124. "version|v|V", \&show_version,
  125. "private|p", \$doPrivate,
  126. "libdir|L=s", \$libdir,
  127. "xref|l=s", \@libs,
  128. "classes|c=s", \@includeclasses,
  129. "cpp|P", \$cpp,
  130. "docincluded", \$docincluded,
  131. "cppcmd|C=s", \$cppcmd,
  132. "includedir|I=s", \@includes,
  133. "define=s", \%defines, # define a single preprocessing symbol
  134. "defines=s", \$defines, # file containing preprocessing symbols, one per line
  135. "quiet|q", \$quiet,
  136. "debug|D", \$debug, # debug the parsing
  137. "debuggen", \$debuggen, # debug the file generation
  138. "parse-only", \$parseonly )
  139. || exit 1;
  140. $| = 1 if $debug or $debuggen;
  141. # preprocessor settings
  142. if ( $cppcmd eq "" ) {
  143. $cppcmd = $defcppcmd;
  144. }
  145. else {
  146. $cpp = 1;
  147. }
  148. if ($#includeclasses>=0)
  149. {
  150. $includeclasses = join (" ", @includeclasses);
  151. print "Using Classes: $includeclasses\n" unless $quiet;
  152. }
  153. if ( $#includes >= 0 && !$cpp ) {
  154. die "$exe: --includedir requires --cpp\n";
  155. }
  156. # Check output formats. HTML is the default
  157. if( $#formats_wanted < 0 ) {
  158. push @formats_wanted, "java";
  159. }
  160. foreach my $format ( @formats_wanted ) {
  161. die "$exe: unsupported format '$format'.\n"
  162. if !defined $formats{$format};
  163. }
  164. if( $defines )
  165. {
  166. open( DEFS, $defines ) or die "Couldn't open $defines: $!\n";
  167. my @defs = <DEFS>;
  168. chomp @defs;
  169. close DEFS;
  170. foreach (@defs)
  171. {
  172. $defines{ $_ } = 1 unless exists $defines{ $_ };
  173. }
  174. }
  175. # Check the %defines hash for QT_NO_* symbols and compile the corresponding RE
  176. # Otherwise, compile the default ones. Used for filtering in readCxxLine.
  177. if ( my @qt_defines = map { ($_=~m/^QT_NO_(.*)/)[0] } keys %defines)
  178. {
  179. my $regexp = "m/^#\\s*ifn?def\\s+QT_NO_(?:" . join('|', map { "\$qt_defines[$_]" } 0..$#qt_defines).")/o";
  180. $match_qt_defines = eval "sub { my \$s=shift;
  181. \$s=~/^#\\s*if(n)?def QT_NO/ || return 0;
  182. if(!\$1) { return \$s=~$regexp ? 0:1 }
  183. else { return \$s=~$regexp ? 1:0 }
  184. }";
  185. die if $@;
  186. }
  187. else
  188. {
  189. $match_qt_defines = eval q£
  190. sub
  191. {
  192. my $s = shift;
  193. $s =~ m/^\#\s*ifndef\s+QT_NO_(?:REMOTE| # not in the default compile options
  194. NIS| # ...
  195. XINERAMA|
  196. IMAGEIO_(?:MNG|JPEG)|
  197. STYLE_(?:MAC|INTERLACE|COMPACT)
  198. )/x;
  199. }
  200. £;
  201. die if $@;
  202. }
  203. # Check if there any files to process.
  204. # We do it here to prevent the libraries being loaded up first.
  205. checkFileArgs();
  206. # work out libdir. This is created by kdocLib:writeDoc when
  207. # required.
  208. $libdir = $ENV{HOME}."/.kalyptus" unless $libdir ne "";
  209. ######
  210. ###### main program
  211. ######
  212. readLibraries();
  213. parseFiles();
  214. if ( $parseonly ) {
  215. print "\n\tParse Tree\n\t------------\n\n";
  216. kdocAstUtil::dumpAst( $rootNode );
  217. }
  218. else {
  219. writeDocumentation();
  220. writeLibrary() unless $libname eq "";
  221. }
  222. kdocAstUtil::printDebugStats() if $debug;
  223. exit 0;
  224. ######
  225. sub checkFileArgs
  226. {
  227. return unless $#ARGV < 0;
  228. die "$exe: no input files.\n" unless $readstdin;
  229. # read filenames from standard input
  230. while (<STDIN>) {
  231. chop;
  232. $_ =~ s,\\,/,g; # back to fwd slash (for Windows)
  233. foreach my $file ( split( /\s+/, $_ ) ) {
  234. push @ARGV, $file;
  235. }
  236. }
  237. }
  238. sub readLibraries
  239. {
  240. return if $#libs < 0;
  241. require kdocLib;
  242. foreach my $lib ( @libs ) {
  243. print "$exe: reading lib: $lib\n" unless $quiet;
  244. my $relpath = exists $options{url} ?
  245. $options{url} : $outputdir;
  246. kdocLib::readLibrary( \&getRoot, $lib, $libdir, $relpath );
  247. }
  248. }
  249. sub parseFiles
  250. {
  251. foreach $currentfile ( @ARGV ) {
  252. my $lang = "CXX";
  253. if ( $currentfile =~ /\.idl\s*$/ ) {
  254. # IDL file
  255. $lang = "IDL";
  256. }
  257. # assume cxx file
  258. if( $cpp ) {
  259. # pass through preprocessor
  260. my $cmd = $cppcmd;
  261. foreach my $dir ( @includes ) {
  262. $cmd .= " -I $dir ";
  263. }
  264. $cmd .= " -DQOBJECTDEFS_H $currentfile";
  265. open( INPUT, "$cmd |" )
  266. || croak "Can't preprocess $currentfile";
  267. }
  268. else {
  269. open( INPUT, "$currentfile" )
  270. || croak "Can't read from $currentfile";
  271. }
  272. print "$exe: processing $currentfile\n" unless $quiet;
  273. # reset vars
  274. $rootNode = getRoot( $lang );
  275. # add to file lookup table
  276. my $showname = $striphpath ? basename( $currentfile )
  277. : $currentfile;
  278. $cSourceNode = Ast::New( $showname );
  279. $cSourceNode->AddProp( "NodeType", "source" );
  280. $cSourceNode->AddProp( "Path", $currentfile );
  281. $rootNode->AddPropList( "Sources", $cSourceNode );
  282. # reset state
  283. @classStack = ();
  284. $cNode = $rootNode;
  285. $inExtern = 0;
  286. # parse
  287. my $k = undef;
  288. while ( defined ($k = readDecl()) ) {
  289. print "\nDecl: <$k>[$declNodeType]\n" if $debug;
  290. if( identifyDecl( $k ) && $k =~ /{/ ) {
  291. readCxxCodeBlock();
  292. }
  293. }
  294. close INPUT;
  295. }
  296. }
  297. sub writeDocumentation
  298. {
  299. foreach my $node ( values %rootNodes ) {
  300. # postprocess
  301. kdocAstUtil::linkNamespaces( $node );
  302. kdocAstUtil::makeInherit( $node, $node );
  303. kdocAstUtil::linkReferences( $node, $node );
  304. kdocAstUtil::calcStats( \%stats, $node, $node );
  305. # write
  306. no strict "refs";
  307. foreach my $format ( @formats_wanted ) {
  308. my $pack = $formats{ $format };
  309. require $pack.".pm";
  310. print "Generating bindings for $format ",
  311. "language...\n" unless $quiet;
  312. my $f = "$pack\::writeDoc";
  313. &$f( $libname, $node, $outputdir, \%options );
  314. }
  315. }
  316. }
  317. sub writeLibrary
  318. {
  319. if( $libname ne "" ) {
  320. require kdocLib;
  321. foreach my $lang ( keys %rootNodes ) {
  322. my $node = $rootNodes{ $lang };
  323. kdocLib::writeDoc( $libname, $node, $lang, $libdir,
  324. $outputdir, $options{url},
  325. exists $options{compress} ? 1 : 0 );
  326. }
  327. }
  328. }
  329. ###### Parser routines
  330. =head2 readSourceLine
  331. Returns a raw line read from the current input file.
  332. This is used by routines outside main, since I don t know
  333. how to share fds.
  334. =cut
  335. sub readSourceLine
  336. {
  337. return <INPUT>;
  338. }
  339. =head2 readCxxLine
  340. Reads a C++ source line, skipping comments, blank lines,
  341. preprocessor tokens and the Q_OBJECT macro
  342. =cut
  343. sub readCxxLine
  344. {
  345. my( $p );
  346. my( $l );
  347. while( 1 ) {
  348. $p = shift @inputqueue || <INPUT>;
  349. return undef if !defined ($p);
  350. $p =~ s#//.*$##g; # C++ comment
  351. $p =~ s#/\*(?!\*).*?\*/##g; # C comment
  352. # join all multiline comments
  353. if( $p =~ m#/\*(?!\*)#s ) {
  354. # unterminated comment
  355. LOOP:
  356. while( defined ($l = <INPUT>) ) {
  357. $l =~ s#//.*$##g; # C++ comment
  358. $p .= $l;
  359. $p =~ s#/\*(?!\*).*?\*/##sg; # C comment
  360. last LOOP unless $p =~ m#(/\*(?!\*))|(\*/)#sg;
  361. }
  362. }
  363. if ( $p =~ /^\s*Q_OBJECT/ ) {
  364. push @inputqueue, @codeqobject;
  365. next;
  366. }
  367. # Hack, waiting for real handling of preprocessor defines
  368. $p =~ s/QT_STATIC_CONST/static const/;
  369. $p =~ s/KSVG_GET/KJS::Value get();/;
  370. $p =~ s/KSVG_BASECLASS_GET/KJS::Value get();/;
  371. $p =~ s/KSVG_BRIDGE/KJS::ObjectImp *bridge();/;
  372. $p =~ s/KSVG_FORWARDGET/KJS::Value getforward();/;
  373. $p =~ s/KSVG_PUT/bool put();/;
  374. $p =~ s/KSVG_FORWARDPUT/bool putforward();/;
  375. $p =~ s/KSVG_BASECLASS/virtual KJS::Value cache();/;
  376. if ( $p =~ m/KSVG_DEFINE_PROTOTYPE\((\w+)\)/ ) {
  377. push @inputqueue, split('\n',"namespace KSVG {\nclass $1 {\n};\n};");
  378. }
  379. next if ( $p =~ /^\s*$/s ); # blank lines
  380. # || $p =~ /^\s*Q_OBJECT/ # QObject macro
  381. # );
  382. next if ( $p =~ /^\s*Q_ENUMS/ # ignore Q_ENUMS
  383. || $p =~ /^\s*Q_PROPERTY/ # and Q_PROPERTY
  384. || $p =~ /^\s*Q_OVERRIDE/ # and Q_OVERRIDE
  385. || $p =~ /^\s*K_SYCOCATYPE/ # and K_SYCOCA stuff
  386. || $p =~ /^\s*K_SYCOCAFACTORY/ #
  387. || $p =~ /^\s*K_DCOP/ # and DCOP stuff
  388. || $p =~ /^\s*KSVG_/ # and KSVG stuff ;)
  389. );
  390. # remove all preprocessor macros
  391. if( $p =~ /^\s*#\s*(\w+)/ ) {
  392. # Handling of preprocessed sources: skip anything included from
  393. # other files, unless --docincluded was passed.
  394. if (!$docincluded && $p =~ /^\s*#\s*[0-9]+\s*\".*$/
  395. && not($p =~ /\"$currentfile\"/)) {
  396. # include file markers
  397. while( <INPUT> ) {
  398. last if(/\"$currentfile\"/);
  399. print "Overread $_" if $debug;
  400. };
  401. print "Cont: $_" if $debug;
  402. }
  403. else {
  404. # Skip platform-specific stuff, or #if 0 stuff
  405. # or #else of something we parsed (e.g. for QKeySequence)
  406. if ( $p =~ m/^#\s*ifdef\s*Q_WS_/ or
  407. $p =~ m/^#\s*if\s+defined\(Q_WS_/ or
  408. $p =~ m/^#\s*if\s+defined\(Q_OS_/ or
  409. $p =~ m/^#\s*if\s+defined\(QT_THREAD_SUPPORT/ or
  410. $p =~ m/^#\s*else/ or
  411. $p =~ m/^#\s*if\s+defined\(Q_FULL_TEMPLATE_INSTANTIATION/ or
  412. &$match_qt_defines( $p ) or
  413. $p =~ m/^#\s*if\s+0\s+/ ) {
  414. my $if_depth = 1;
  415. while ( defined $p && $if_depth > 0 ) {
  416. $p = <INPUT>;
  417. last if !defined $p;
  418. $if_depth++ if $p =~ m/^#\s*if/;
  419. $if_depth-- if $p =~ m/^#\s*endif/;
  420. # Exit at #else in the #ifdef QT_NO_ACCEL/#else/#endif case
  421. last if $if_depth == 1 && $p =~ m/^#\s*else\s/;
  422. #ignore elif for now
  423. print "Skipping ifdef'ed line: $p" if $debug;
  424. }
  425. }
  426. # multiline macros
  427. while ( defined $p && $p =~ m#\\\s*$# ) {
  428. $p = <INPUT>;
  429. }
  430. }
  431. next;
  432. }
  433. $lastLine = $p;
  434. return $p;
  435. }
  436. }
  437. =head2 readCxxCodeBlock
  438. Reads a C++ code block (recursive curlies), returning the last line
  439. or undef on error.
  440. Parameters: none
  441. =cut
  442. sub readCxxCodeBlock
  443. {
  444. # Code: begins in a {, ends in }\s*;?
  445. # In between: cxx source, including {}
  446. my ( $count ) = 0;
  447. my $l = undef;
  448. if ( defined $lastLine ) {
  449. print "lastLine: '$lastLine'" if $debug;
  450. my $open = kdocUtil::countReg( $lastLine, "{" );
  451. my $close = kdocUtil::countReg( $lastLine, "}" );
  452. $count = $open - $close;
  453. return $lastLine if ( $open || $close) && $count == 0;
  454. }
  455. # find opening brace
  456. if ( $count == 0 ) {
  457. while( $count == 0 ) {
  458. $l = readCxxLine();
  459. return undef if !defined $l;
  460. $l =~ s/\\.//g;
  461. $l =~ s/'.?'//g;
  462. $l =~ s/".*?"//g;
  463. $count += kdocUtil::countReg( $l, "{" );
  464. print "c ", $count, " at '$l'" if $debug;
  465. }
  466. $count -= kdocUtil::countReg( $l, "}" );
  467. }
  468. # find associated closing brace
  469. while ( $count > 0 ) {
  470. $l = readCxxLine();
  471. croak "Confused by unmatched braces" if !defined $l;
  472. $l =~ s/\\.//g;
  473. $l =~ s/'.?'//g;
  474. $l =~ s/".*?"//g;
  475. my $add = kdocUtil::countReg( $l, "{" );
  476. my $sub = kdocUtil::countReg( $l, "}" );
  477. $count += $add - $sub;
  478. print "o ", $add, " c ", $sub, " at '$l'" if $debug;
  479. }
  480. undef $lastLine;
  481. return $l;
  482. }
  483. =head2 readDecl
  484. Returns a declaration and sets the $declNodeType variable.
  485. A decl starts with a type or keyword and ends with [{};]
  486. The entire decl is returned in a single line, sans newlines.
  487. declNodeType values: undef for error, "a" for access specifier,
  488. "c" for doc comment, "d" for other decls.
  489. readCxxLine is used to read the declaration.
  490. =cut
  491. sub readDecl
  492. {
  493. undef $declNodeType;
  494. my $l = readCxxLine();
  495. my ( $decl ) = "";
  496. if( !defined $l ) {
  497. return undef;
  498. }
  499. elsif ( $l =~ /^\s*(private|public|protected|signals)
  500. (\s+\w+)?\s*:/x ) { # access specifier
  501. $declNodeType = "a";
  502. return $l;
  503. }
  504. elsif ( $l =~ m#^\s*/\*\*# ) { # doc comment
  505. $declNodeType = "c";
  506. return $l;
  507. }
  508. do {
  509. $decl .= $l;
  510. if ( $l =~ /[{};]/ ) {
  511. $decl =~ s/\n/ /gs;
  512. $declNodeType = "d";
  513. return $decl;
  514. }
  515. return undef if !defined ($l = readCxxLine());
  516. } while ( 1 );
  517. }
  518. #### AST Generator Routines
  519. =head2 getRoot
  520. Return a root node for the given type of input file.
  521. =cut
  522. sub getRoot
  523. {
  524. my $type = shift;
  525. carp "getRoot called without type" unless defined $type;
  526. if ( !exists $rootNodes{ $type } ) {
  527. my $node = Ast::New( "Global" ); # parent of all nodes
  528. $node->AddProp( "NodeType", "root" );
  529. $node->AddProp( "RootType", $type );
  530. $node->AddProp( "Compound", 1 );
  531. $node->AddProp( "KidAccess", "public" );
  532. $rootNodes{ $type } = $node;
  533. }
  534. print "getRoot: call for $type\n" if $debug;
  535. return $rootNodes{ $type };
  536. }
  537. =head2 identifyDecl
  538. Parameters: decl
  539. Identifies a declaration returned by readDecl. If a code block
  540. needs to be skipped, this subroutine returns a 1, or 0 otherwise.
  541. =cut
  542. sub identifyDecl
  543. {
  544. my( $decl ) = @_;
  545. my $newNode = undef;
  546. my $skipBlock = 0;
  547. # Doc comment
  548. if ( $declNodeType eq "c" ) {
  549. $docNode = kdocParseDoc::newDocComment( $decl );
  550. # if it's the main doc, it is attached to the root node
  551. if ( defined $docNode->{LibDoc} ) {
  552. kdocParseDoc::attachDoc( $rootNode, $docNode,
  553. $rootNode );
  554. undef $docNode;
  555. }
  556. }
  557. elsif ( $declNodeType eq "a" ) {
  558. newAccess( $decl );
  559. }
  560. # Typedef struct/class
  561. elsif ( $decl =~ /^\s*typedef
  562. \s+(struct|union|class|enum)
  563. \s*([_\w\:]*)
  564. \s*([;{])
  565. /xs ) {
  566. my ($type, $name, $endtag, $rest ) = ($1, $2, $3, $' );
  567. $name = "--" if $name eq "";
  568. warn "typedef '$type' n:'$name'\n" if $debug;
  569. if ( $rest =~ /}\s*([\w_]+(?:::[\w_])*)\s*;/ ) {
  570. # TODO: Doesn't parse members yet!
  571. $endtag = ";";
  572. $name = $1;
  573. }
  574. $newNode = newTypedefComp( $type, $name, $endtag );
  575. }
  576. # Typedef
  577. elsif ( $decl =~ /^\s*typedef\s+
  578. (?:typename\s+)? # `typename' keyword
  579. (.*?\s*[\*&]?) # type
  580. \s+([-\w_\:]+) # name
  581. \s*((?:\[[-\w_\:<>\s]*\])*) # array
  582. \s*[{;]\s*$/xs ) {
  583. print "Typedef: <$1 $3> <$2>\n" if $debug;
  584. $newNode = newTypedef( $1." ".$3, $2 );
  585. }
  586. # Enum
  587. elsif ( $decl =~ /^\s*enum\s+([-\w_:]*)?\s*\{(.*)/s ) {
  588. print "Enum: <$1>\n" if $debug;
  589. my $enumname = defined $2 ? $1 : "";
  590. $newNode = newEnum( $enumname );
  591. }
  592. # Class/Struct
  593. elsif ( $decl =~ /^\s*((?:template\s*<.*>)?) # 1 template
  594. \s*(class|struct|union|namespace) # 2 struct type
  595. (?:\s*Q[A-Z_]*EXPORT[A-Z_]*)?
  596. (?:\s*Q_PACKED)?
  597. (?:\s*Q_REFCOUNT)?
  598. \s+([\w_]+ # 3 name
  599. (?:<[\w_ :,]+?>)? # maybe explicit template
  600. # (eat chars between <> non-hungry)
  601. (?:::[\w_]+)* # maybe nested
  602. )
  603. (.*?) # 4 inheritance
  604. ([;{])/xs ) { # 5 rest
  605. print "Class: [$1]\n\t[$2]\n\t[$3]\n\t[$4]\n\t[$5]\n" if $debug;
  606. my ( $tmpl, $ntype, $name, $rest, $endtag ) =
  607. ( $1, $2, $3, $4, $5 );
  608. if ($includeclasses)
  609. {
  610. if (! ($includeclasses =~ /$name/) )
  611. {
  612. return 1;
  613. }
  614. }
  615. my @inherits = ();
  616. $tmpl =~ s/<(.*)>/$1/ if $tmpl ne "";
  617. if( $rest =~ /^\s*:\s*/ ) {
  618. # inheritance
  619. $rest = $';
  620. @inherits = parseInheritance( $rest );
  621. }
  622. $newNode = newClass( $tmpl, $ntype,
  623. $name, $endtag, @inherits );
  624. }
  625. # IDL compound node
  626. elsif( $decl =~ /^\s*(module|interface|exception) # struct type
  627. \s+([-\w_]+) # name
  628. (.*?) # inheritance?
  629. ([;{])/xs ) {
  630. my ( $type, $name, $rest, $fwd, $complete )
  631. = ( $1, $2, $3, $4 eq ";" ? 1 : 0,
  632. 0 );
  633. my @in = ();
  634. print "IDL: [$type] [$name] [$rest] [$fwd]\n" if $debug;
  635. if( $rest =~ /^\s*:\s*/ ) {
  636. $rest = $';
  637. $rest =~ s/\s+//g;
  638. @in = split ",", $rest;
  639. }
  640. if( $decl =~ /}\s*;/ ) {
  641. $complete = 1;
  642. }
  643. $newNode = newIDLstruct( $type, $name, $fwd, $complete, @in );
  644. }
  645. # Method
  646. elsif ( $decl =~ /^\s*([^=]+?(?:operator\s*(?:\(\)|.?=)\s*)?) # ret+nm
  647. \( (.*?) \) # parameters
  648. \s*((?:const)?)\s*
  649. \s*((?:=\s*0(?:L?))?)\s* # Pureness. is "0L" allowed?
  650. \s*[;{]+/xs ) { # rest
  651. my $tpn = $1; # type + name
  652. my $params = $2;
  653. # Remove constructor initializer, that's not in the params
  654. if ( $params =~ /\s*\)\s*:\s*/ ) {
  655. # Hack: first .* made non-greedy for QSizePolicy using a?(b):c in ctor init
  656. $params =~ s/(.*?)\s*\)\s*:\s*.*$/$1/;
  657. }
  658. my $const = $3 eq "" ? 0 : 1;
  659. my $pure = $4 eq "" ? 0 : 1;
  660. $tpn =~ s/\s+/ /g;
  661. $params =~ s/\s+/ /g;
  662. print "Method: R+N:[$tpn]\n\tP:[$params]\n\t[$const]\n" if $debug;
  663. if ( $tpn =~ /((?:\w+\s*::\s*)?operator.*?)\s*$/ # operator
  664. || $tpn =~ /((?:\w*\s*::\s*~?)?[-\w:]+)\s*$/ ) { # normal
  665. my $name = $1;
  666. $tpn = $`;
  667. $newNode = newMethod( $tpn, $name,
  668. $params, $const, $pure );
  669. }
  670. $skipBlock = 1; # FIXME check end token before doing this!
  671. }
  672. # Using: import namespace
  673. elsif ( $decl =~ /^\s*using\s+namespace\s+(\w+)/ ) {
  674. newNamespace( $1 );
  675. }
  676. # extern block
  677. elsif ( $decl =~ /^\s*extern\s*"(.*)"\s*{/ ) {
  678. $inExtern = 1 unless $decl =~ /}/;
  679. }
  680. # Single variable
  681. elsif ( $decl =~ /^
  682. \s*( (?:[\w_:]+(?:\s+[\w_:]+)*? )# type
  683. \s*(?:<.+>)? # template
  684. \s*(?:[\&\*])? # ptr or ref
  685. (?:\s*(?:const|volatile))* )
  686. \s*([\w_:]+) # name
  687. \s*( (?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? ) # array
  688. \s*((?:=.*)?) # value
  689. \s*([;{])\s*$/xs ) {
  690. my $type = $1;
  691. my $name = $2;
  692. my $arr = $3;
  693. my $val = $4;
  694. my $end = $5;
  695. if ( $type !~ /^friend\s+class\s*/ ) {
  696. print "Var: [$name] type: [$type$arr] val: [$val]\n"
  697. if $debug;
  698. $newNode = newVar( $type.$arr, $name, $val );
  699. }
  700. $skipBlock = 1 if $end eq '{';
  701. }
  702. # Multi variables
  703. elsif ( $decl =~ m/^
  704. \s*( (?:[\w_:]+(?:\s+[\w_:]+)*? ) # type
  705. \s*(?:<.+>)?) # template
  706. \s*( (?:\s*(?: [\&\*][\&\*\s]*)? # ptr or ref
  707. [\w_:]+) # name
  708. \s*(?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? # array
  709. \s*(?:, # extra vars
  710. \s*(?: [\&\*][\&\*\s]*)? # ptr or ref
  711. \s*(?:[\w_:]+) # name
  712. \s*(?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? # array
  713. )*
  714. \s*(?:=.*)?) # value
  715. \s*[;]/xs ) {
  716. my $type = $1;
  717. my $names = $2;
  718. my $end = $3;
  719. my $doc = $docNode;
  720. print "Multivar: type: [$type] names: [$names] \n" if $debug;
  721. foreach my $vardecl ( split( /\s*,\s*/, $names ) ) {
  722. next unless $vardecl =~ m/
  723. \s*((?: [\&\*][\&\*\s]*)?) # ptr or ref
  724. \s*([\w_:]+) # name
  725. \s*( (?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? ) # array
  726. \s*((?:=.*)?) # value
  727. /xs;
  728. my ($ptr, $name, $arr, $val) = ($1, $2, $3, $4);
  729. print "Split: type: [$type$ptr$arr] ",
  730. " name: [$name] val: [$val] \n" if $debug;
  731. my $node = newVar( $type.$ptr.$arr, $name, $val );
  732. $docNode = $doc; # reuse docNode for each
  733. postInitNode( $node ) unless !defined $node;
  734. }
  735. $skipBlock = 1 if $end eq '{';
  736. }
  737. # end of an "extern" block
  738. elsif ( $decl =~ /^\s*}\s*$/ ) {
  739. $inExtern = 0;
  740. }
  741. # end of an in-block declaration
  742. elsif ( $decl =~ /^\s*}\s*(.*?)\s*;\s*$/ ) {
  743. if ( $cNode->{astNodeName} eq "--" ) {
  744. # structure typedefs should have no name preassigned.
  745. # If they do, then the name in
  746. # "typedef struct <name> { ..." is kept instead.
  747. # TODO: Buglet. You should fix YOUR code dammit. ;)
  748. $cNode->{astNodeName} = $1;
  749. my $siblings = $cNode->{Parent}->{KidHash};
  750. undef $siblings->{"--"};
  751. $siblings->{ $1 } = $cNode;
  752. }
  753. if ( $#classStack < 0 ) {
  754. confess "close decl found, but no class in stack!" ;
  755. $cNode = $rootNode;
  756. }
  757. else {
  758. $cNode = pop @classStack;
  759. print "end decl: popped $cNode->{astNodeName}\n"
  760. if $debug;
  761. }
  762. }
  763. # unidentified block start
  764. elsif ( $decl =~ /{/ ) {
  765. print "Unidentified block start: $decl\n" if $debug;
  766. $skipBlock = 1;
  767. }
  768. # explicit template instantiation
  769. elsif ( $decl =~ /template\s+class\s+(?:Q[A-Z_]*EXPORT[A-Z_]*\s*)?\w+\s*<.*>\s*;/x ) {
  770. # Nothing to be done with those.
  771. }
  772. else {
  773. ## decl is unidentified.
  774. warn "Unidentified decl: $decl\n";
  775. }
  776. # once we get here, the last doc node is already used.
  777. # postInitNode should NOT be called for forward decls
  778. postInitNode( $newNode ) unless !defined $newNode;
  779. return $skipBlock;
  780. }
  781. sub postInitNode
  782. {
  783. my $newNode = shift;
  784. carp "Cannot postinit undef node." if !defined $newNode;
  785. # The reasoning here:
  786. # Forward decls never get a source node.
  787. # Once a source node is defined, don't assign another one.
  788. if ( $newNode->{NodeType} ne "Forward" && !defined $newNode->{Source}) {
  789. $newNode->AddProp( "Source", $cSourceNode );
  790. } elsif ( $newNode->{NodeType} eq "Forward" ) {
  791. if ($debug) {
  792. print "postInit: skipping fwd: $newNode->{astNodeName}\n";
  793. }
  794. undef $docNode;
  795. return;
  796. }
  797. if( defined $docNode ) {
  798. kdocParseDoc::attachDoc( $newNode, $docNode, $rootNode );
  799. undef $docNode;
  800. }
  801. }
  802. ##### Node generators
  803. =head2 newEnum
  804. Reads the parameters of an enumeration.
  805. Returns the parameters, or undef on error.
  806. =cut
  807. sub newEnum
  808. {
  809. my ( $enum ) = @_;
  810. my $k = undef;
  811. my $params = "";
  812. $k = $lastLine if defined $lastLine;
  813. if( defined $lastLine && $lastLine =~ /{/ ) {
  814. $params = $';
  815. if ( $lastLine =~ /}(.*?);/ ) {
  816. return initEnum( $enum, $1, $params );
  817. }
  818. }
  819. while ( defined ( $k = readCxxLine() ) ) {
  820. $params .= $k;
  821. if ( $k =~ /}(.*?);/ ) {
  822. return initEnum( $enum, $1, $params );
  823. }
  824. }
  825. return undef;
  826. }
  827. =head2 initEnum
  828. Parameters: name, (ref) params
  829. Returns an initialized enum node.
  830. =cut
  831. sub initEnum
  832. {
  833. my( $name, $end, $params ) = @_;
  834. ($name = $end) if $name eq "" && $end ne "";
  835. $params =~ s#\s+# #sg; # no newlines
  836. $params = $1 if $params =~ /^\s*{?(.*)}/;
  837. print "$name params: [$params]\n" if $debug;
  838. my ( $node ) = Ast::New( $name );
  839. $node->AddProp( "NodeType", "enum" );
  840. $node->AddProp( "Params", $params );
  841. makeParamList( $node, $params, 1 ); # Adds the ParamList property containing the list of param nodes
  842. kdocAstUtil::attachChild( $cNode, $node );
  843. return $node;
  844. }
  845. =head2 newIDLstruct
  846. Parameters: type, name, forward, complete, inherits...
  847. Handles an IDL structure definition (ie module, interface,
  848. exception).
  849. =cut
  850. sub newIDLstruct
  851. {
  852. my ( $type, $name, $fwd, $complete ) = @_;
  853. my $node = exists $cNode->{KidHash} ?
  854. $cNode->{KidHash}->{ $name } : undef;
  855. if( !defined $node ) {
  856. $node = Ast::New( $name );
  857. $node->AddProp( "NodeType", $fwd ? "Forward" : $type );
  858. $node->AddProp( "KidAccess", "public" );
  859. $node->AddProp( "Compound", 1 ) unless $fwd;
  860. kdocAstUtil::attachChild( $cNode, $node );
  861. }
  862. elsif ( $fwd ) {
  863. # If we have a node already, we ignore forwards.
  864. return undef;
  865. }
  866. elsif ( $node->{NodeType} eq "Forward" ) {
  867. # we are defining a previously forward node.
  868. $node->AddProp( "NodeType", $type );
  869. $node->AddProp( "Compound", 1 );
  870. $node->AddProp( "Source", $cSourceNode );
  871. }
  872. # register ancestors.
  873. foreach my $ances ( splice ( @_, 4 ) ) {
  874. my $n = kdocAstUtil::newInherit( $node, $ances );
  875. }
  876. if( !( $fwd || $complete) ) {
  877. print "newIDL: pushing $cNode->{astNodeName},",
  878. " new is $node->{astNodeName}\n"
  879. if $debug;
  880. push @classStack, $cNode;
  881. $cNode = $node;
  882. }
  883. return $node;
  884. }
  885. =head2 newClass
  886. Parameters: tmplArgs, cNodeType, name, endTag, @inheritlist
  887. Handles a class declaration (also fwd decls).
  888. =cut
  889. sub newClass
  890. {
  891. my( $tmplArgs, $cNodeType, $name, $endTag ) = @_;
  892. my $access = "private";
  893. $access = "public" if $cNodeType ne "class";
  894. # try to find an exisiting node, or create a new one
  895. my $oldnode = kdocAstUtil::findRef( $cNode, $name );
  896. my $node = defined $oldnode ? $oldnode : Ast::New( $name );
  897. if ( $endTag ne "{" ) {
  898. # forward
  899. if ( !defined $oldnode ) {
  900. # new forward node
  901. $node->AddProp( "NodeType", "Forward" );
  902. $node->AddProp( "KidAccess", $access );
  903. kdocAstUtil::attachChild( $cNode, $node );
  904. }
  905. return $node;
  906. }
  907. # this is a class declaration
  908. print "ClassName: $name\n" if $debug;
  909. $node->AddProp( "NodeType", $cNodeType );
  910. $node->AddProp( "Compound", 1 );
  911. $node->AddProp( "Source", $cSourceNode );
  912. $node->AddProp( "KidAccess", $access );
  913. $node->AddProp( "Tmpl", $tmplArgs ) unless $tmplArgs eq "";
  914. if ( !defined $oldnode ) {
  915. kdocAstUtil::attachChild( $cNode, $node );
  916. }
  917. # inheritance
  918. foreach my $ances ( splice (@_, 4) ) {
  919. my $type = "";
  920. my $name = $ances;
  921. my $intmpl = undef;
  922. WORD:
  923. foreach my $word ( split ( /([\w:]+(:?\s*<.*>)?)/, $ances ) ) {
  924. next WORD unless $word =~ /^[\w:]/;
  925. if ( $word =~ /(private|public|protected|virtual)/ ) {
  926. $type .= "$1 ";
  927. }
  928. else {
  929. if ( $word =~ /<(.*)>/ ) {
  930. # FIXME: Handle multiple tmpl args
  931. $name = $`;
  932. $intmpl = $1;
  933. }
  934. else {
  935. $name = $word;
  936. }
  937. last WORD;
  938. }
  939. }
  940. # set inheritance access specifier if none specified
  941. if ( $type eq "" ) {
  942. $type = $cNodeType eq "class" ? "private ":"public ";
  943. }
  944. chop $type;
  945. # attach inheritance information
  946. my $n = kdocAstUtil::newInherit( $node, $name );
  947. $n->AddProp( "Type", $type );
  948. $n->AddProp( "TmplType", $intmpl ) if defined $intmpl;
  949. print "In: $name type: $type, tmpl: $intmpl\n" if $debug;
  950. }
  951. # new current node
  952. print "newClass: Pushing $cNode->{astNodeName}\n" if $debug;
  953. push ( @classStack, $cNode );
  954. $cNode = $node;
  955. return $node;
  956. }
  957. =head3 parseInheritance
  958. Param: inheritance decl string
  959. Returns: list of superclasses (template decls included)
  960. This will fail if < and > appear in strings in the decl.
  961. =cut
  962. sub parseInheritance
  963. {
  964. my $instring = shift;
  965. my @inherits = ();
  966. my $accum = "";
  967. foreach $instring ( split (/\s*,\s*/, $instring) ) {
  968. $accum .= $instring.", ";
  969. next unless (kdocUtil::countReg( $accum, "<" )
  970. - kdocUtil::countReg( $accum, ">" ) ) == 0;
  971. # matching no. of < and >, so assume the parent is
  972. # complete
  973. $accum =~ s/,\s*$//;
  974. print "Inherits: '$accum'\n" if $debug;
  975. push @inherits, $accum;
  976. $accum = "";
  977. }
  978. return @inherits;
  979. }
  980. =head2 newNamespace
  981. Param: namespace name.
  982. Returns nothing.
  983. Imports a namespace into the current node, for ref searches etc.
  984. Triggered by "using namespace ..."
  985. =cut
  986. sub newNamespace
  987. {
  988. $cNode->AddPropList( "ImpNames", shift );
  989. }
  990. =head2 newTypedef
  991. Parameters: realtype, name
  992. Handles a type definition.
  993. =cut
  994. sub newTypedef
  995. {
  996. my ( $realtype, $name ) = @_;
  997. my ( $node ) = Ast::New( $name );
  998. $node->AddProp( "NodeType", "typedef" );
  999. $node->AddProp( "Type", $realtype );
  1000. kdocAstUtil::attachChild( $cNode, $node );
  1001. return $node;
  1002. }
  1003. =head2 newTypedefComp
  1004. Params: realtype, name endtoken
  1005. Creates a new compound type definition.
  1006. =cut
  1007. sub newTypedefComp
  1008. {
  1009. my ( $realtype, $name, $endtag ) = @_;
  1010. my ( $node ) = Ast::New( $name );
  1011. $node->AddProp( "NodeType", "typedef" );
  1012. $node->AddProp( "Type", $realtype );
  1013. kdocAstUtil::attachChild( $cNode, $node );
  1014. if ( $endtag eq '{' ) {
  1015. print "newTypedefComp: Pushing $cNode->{astNodeName}\n"
  1016. if $debug;
  1017. push ( @classStack, $cNode );
  1018. $cNode = $node;
  1019. }
  1020. return $node;
  1021. }
  1022. =head2 newMethod
  1023. Parameters: retType, name, params, const, pure?
  1024. Handles a new method declaration or definition.
  1025. =cut
  1026. sub newMethod
  1027. {
  1028. my ( $retType, $name, $params, $const, $pure ) = @_;
  1029. my $parent = $cNode;
  1030. my $class;
  1031. print "Cracked: [$retType] [$name]\n\t[$params]\n\t[$const]\n"
  1032. if $debug;
  1033. if ( $retType =~ /([\w\s_<>,]+)\s*::\s*$/ ) {
  1034. # check if stuff before :: got into rettype by mistake.
  1035. $retType = $`;
  1036. ($name = $1."::".$name);
  1037. $name =~ s/\s+/ /g;
  1038. print "New name = \"$name\" and type = '$retType'\n" if $debug;
  1039. }
  1040. # A 'friend method' declaration isn't a real method declaration
  1041. return undef if ( $retType =~ /^friend\s+/ );
  1042. if( $name =~ /^\s*(.*?)\s*::\s*(.*?)\s*$/ ) {
  1043. # Fully qualified method name.
  1044. $name = $2;
  1045. $class = $1;
  1046. if( $class =~ /^\s*$/ ) {
  1047. $parent = $rootNode;
  1048. }
  1049. elsif ( $class eq $cNode->{astNodeName} ) {
  1050. $parent = $cNode;
  1051. }
  1052. else {
  1053. # ALWAYS IGNORE...
  1054. return undef;
  1055. my $node = kdocAstUtil::findRef( $cNode, $class );
  1056. if ( !defined $node ) {
  1057. # if we couldn't find the name, try again with
  1058. # all template parameters stripped off:
  1059. my $strippedClass = $class;
  1060. $strippedClass =~ s/<[^<>]*>//g;
  1061. $node = kdocAstUtil::findRef( $cNode, $strippedClass );
  1062. # if still not found: give up
  1063. if ( !defined $node ) {
  1064. warn "$exe: Unidentified class: $class ".
  1065. "in $currentfile\:$.\n";
  1066. return undef;
  1067. }
  1068. }
  1069. $parent = $node;
  1070. }
  1071. }
  1072. else {
  1073. # Within current class/global
  1074. }
  1075. # flags
  1076. my $flags = "";
  1077. if( $retType =~ /static/ ) {
  1078. $flags .= "s";
  1079. $retType =~ s/static//g;
  1080. }
  1081. if( $const ) {
  1082. $flags .= "c";
  1083. }
  1084. if( $pure ) {
  1085. $flags .= "p";
  1086. }
  1087. if( $retType =~ /virtual/ ) {
  1088. $flags .= "v";
  1089. $retType =~ s/virtual//g;
  1090. }
  1091. print "\n" if $flags ne "" && $debug;
  1092. if ( !defined $parent->{KidAccess} ) {
  1093. warn "'", $parent->{astNodeName}, "' has no KidAccess ",
  1094. exists $parent->{Forward} ? "(forward)\n" :"\n";
  1095. }
  1096. if ( $parent->{KidAccess} =~ /slot/ ) {
  1097. $flags .= "l";
  1098. }
  1099. elsif ( $parent->{KidAccess} =~ /signal/ ) {
  1100. $flags .= "n";
  1101. }
  1102. $retType =~ s/Q_EXPORT\s*//;
  1103. $retType =~ s/inline\s+//;
  1104. $retType =~ s/^\s*//g;
  1105. $retType =~ s/\s*$//g;
  1106. # node
  1107. my $node = Ast::New( $name );
  1108. $node->AddProp( "NodeType", "method" );
  1109. $node->AddProp( "Flags", $flags );
  1110. $node->AddProp( "ReturnType", $retType );
  1111. $node->AddProp( "Params", $params ); # The raw string with the whole param list
  1112. makeParamList( $node, $params, 0 ); # Adds the ParamList property containing the list of param nodes
  1113. $parent->AddProp( "Pure", 1 ) if $pure;
  1114. kdocAstUtil::attachChild( $parent, $node );
  1115. return $node;
  1116. }
  1117. =head2 makeParamList
  1118. Parameters:
  1119. * method (or enum) node
  1120. * string containing the whole param list
  1121. * 1 for enums
  1122. Adds a property "ParamList" to the method node.
  1123. This property contains a list of nodes, one for each parameter.
  1124. Each parameter node has the following properties:
  1125. * ArgType the type of the argument, e.g. const QString&
  1126. * ArgName the name of the argument - optionnal
  1127. * DefaultValue the default value of the argument - optionnal
  1128. For enum values, ArgType is unset, ArgName is the name, DefaultValue its value.
  1129. Author: David Faure <[email protected]>
  1130. =cut
  1131. sub makeParamList($$$)
  1132. {
  1133. my ( $methodNode, $params, $isEnum ) = @_;
  1134. $params =~ s/\s+/ /g; # normalize multiple spaces/tabs into a single one
  1135. $params =~ s/\s*([,\*\&])\s*/$1 /g; # normalize spaces before and after *, & and ','
  1136. $params =~ s/^\s*void\s*$//; # foo(void) ==> foo()
  1137. $params =~ s/^\s*$//;
  1138. # Make sure the property always exists, makes iteration over it easier
  1139. $methodNode->AddProp( "ParamList", [] );
  1140. my @args = kdocUtil::splitUnnested( ',', $params);
  1141. my $argId = 0;
  1142. foreach my $arg ( @args ) {
  1143. my $argType;
  1144. my $argName;
  1145. my $defaultparam;
  1146. $arg =~ s/\s*([^\s].*[^\s])\s*/$1/; # stripWhiteSpace
  1147. $arg =~ s/(\w+)\[\]/\* $1/; # Turn [] array into *
  1148. # The RE below reads as: = ( string constant or char
  1149. # or some word/number, with optional OR'ed or +'ed flags, and/or function call ).
  1150. if ( $arg =~ s/\s*=\s*(("[^\"]*")|(\'.\')|(([-\w:~]*)\s*([\|\+-]*\s*\w*\s*)*(\(\w*\))?))// ) {
  1151. $defaultparam = $1;
  1152. }
  1153. # Separate arg type from arg name, if the latter is specified
  1154. if ( $arg =~ /(.*)\s+(\w+)\s*$/ ) {
  1155. $argType = $1;
  1156. $argName = $2;
  1157. } else { # unnamed arg - or enum value
  1158. $argType = $arg if (!$isEnum);
  1159. $argName = $arg if ($isEnum);
  1160. }
  1161. $argId++;
  1162. my $node = Ast::New( $argId ); # let's make the arg index the node "name"
  1163. $node->AddProp( "NodeType", "param" );
  1164. $node->AddProp( "ArgType", $argType );
  1165. $node->AddProp( "ArgName", $argName ) if (defined $argName);
  1166. $node->AddProp( "DefaultValue", $defaultparam ) if (defined $defaultparam);
  1167. $methodNode->AddPropList( "ParamList", $node );
  1168. print STDERR "ArgType: $argType ArgName: $argName\n" if ($debug);
  1169. }
  1170. }
  1171. =head2 newAccess
  1172. Parameters: access
  1173. Sets the default "Access" specifier for the current class node. If
  1174. the access is a "slot" type, "_slots" is appended to the access
  1175. string.
  1176. =cut
  1177. sub newAccess
  1178. {
  1179. my ( $access ) = @_;
  1180. return undef unless ($access =~ /^\s*(\w+)\s*(slots)?/);
  1181. print "Access: [$1] [$2]\n" if $debug;
  1182. $access = $1;
  1183. if ( defined $2 && $2 ne "" ) {
  1184. $access .= "_" . $2;
  1185. }
  1186. $cNode->AddProp( "KidAccess", $access );
  1187. return $cNode;
  1188. }
  1189. =head2 newVar
  1190. Parameters: type, name, value
  1191. New variable. Value is ignored if undef
  1192. =cut
  1193. sub newVar
  1194. {
  1195. my ( $type, $name, $val ) = @_;
  1196. my $node = Ast::New( $name );
  1197. $node->AddProp( "NodeType", "var" );
  1198. my $static = 0;
  1199. if ( $type =~ /static/ ) {
  1200. # $type =~ s/static//;
  1201. $static = 1;
  1202. }
  1203. $node->AddProp( "Type", $type );
  1204. $node->AddProp( "Flags", 's' ) if $static;
  1205. $node->AddProp( "Value", $val ) if defined $val;
  1206. kdocAstUtil::attachChild( $cNode, $node );
  1207. return $node;
  1208. }
  1209. =head2 show_usage
  1210. Display usage information and quit.
  1211. =cut
  1212. sub show_usage
  1213. {
  1214. print<<EOF;
  1215. usage:
  1216. $exe [options] [-f format] [-d outdir] [-n name] files... [-llib..]
  1217. See the man page kdoc[1] for more info.
  1218. EOF
  1219. exit 1;
  1220. }
  1221. =head2 show_version
  1222. Display short version information and quit.
  1223. =cut
  1224. sub show_version
  1225. {
  1226. die "$exe: $Version (c) Sirtaj S. Kang <taj\@kde.org>\n";
  1227. }