4 # gtk-doc - GTK DocBook documentation generator.
5 # Copyright (C) 1998 Damon Chaplin
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #############################################################################
23 # Script : gtkdoc-scan
24 # Description : Extracts declarations of functions, macros, enums, structs
25 # and unions from header files.
27 # It is called with a module name, an optional source directory,
28 # an optional output directory, and the header files to scan.
30 # It outputs all declarations found to a file named
31 # '$MODULE-decl.txt', and the list of decarations to another
32 # file '$MODULE-decl-list.txt'.
34 # This second list file is typically copied to
35 # '$MODULE-sections.txt' and organized into sections ready to
36 # output the SGML pages.
37 #############################################################################
43 push @INC, '@PACKAGE_DATA_DIR@';
44 require "gtkdoc-common.pl";
48 # name of documentation module
52 my $IGNORE_HEADERS = "";
57 # regexp matching cpp symbols which surround deprecated stuff
58 # e.g. 'GTK_ENABLE_BROKEN|GTK_DISABLE_DEPRECATED'
59 # these are detected if they are used as #if FOO, #ifndef FOO, or #ifdef FOO
60 my $DEPRECATED_GUARDS;
61 # regexp matching decorators that should be ignored
62 my $IGNORE_DECORATORS;
64 my %optctl = (module => \$MODULE,
65 'source-dir' => \@SOURCE_DIRS,
66 'ignore-headers' => \$IGNORE_HEADERS,
67 'output-dir' => \$OUTPUT_DIR,
68 'rebuild-types' => \$REBUILD_TYPES,
69 'rebuild-sections' => \$REBUILD_SECTIONS,
70 'version' => \$PRINT_VERSION,
71 'help' => \$PRINT_HELP,
72 'deprecated-guards' => \$DEPRECATED_GUARDS,
73 'ignore-decorators' => \$IGNORE_DECORATORS);
74 GetOptions(\%optctl, "module=s", "source-dir:s", "ignore-headers:s",
75 "output-dir:s", "rebuild-types", "rebuild-sections", "version",
76 "help", "deprecated-guards:s", "ignore-decorators:s");
89 gtkdoc-scan version @VERSION@ - scan header files for public symbols
91 --module=MODULE_NAME Name of the doc module being parsed
92 --source-dir=DIRNAME Directories containing the source files to scan
93 --ignore-headers=FILES A space-separated list of header files not to scan
94 --output-dir=DIRNAME The directory where the results are stored
95 --deprecated-guards=GUARDS A |-separated list of symbols used as deprecation
97 --ignore-decorators=DECS A |-separated list of addition decorators in
98 declarations that should be ignored
99 --rebuild-sections Rebuild (overwrite) the MODULE-sections.txt file
100 --rebuild-types Automatically recreate the MODULE.types file using
101 all the *_get_type() functions found
102 --version Print the version of this program
103 --help Print this help
108 $DEPRECATED_GUARDS = $DEPRECATED_GUARDS ? $DEPRECATED_GUARDS : "does_not_match_any_cpp_symbols_at_all_nope";
110 $IGNORE_DECORATORS = $IGNORE_DECORATORS || "(?=no)match";
112 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
114 if (!-d ${OUTPUT_DIR}) {
115 mkdir($OUTPUT_DIR, 0755) || die "Cannot create $OUTPUT_DIR: $!";
118 my $old_decl_list = "${OUTPUT_DIR}/$MODULE-decl-list.txt";
119 my $new_decl_list = "${OUTPUT_DIR}/$MODULE-decl-list.new";
120 my $old_decl = "${OUTPUT_DIR}/$MODULE-decl.txt";
121 my $new_decl = "${OUTPUT_DIR}/$MODULE-decl.new";
122 my $old_types = "${OUTPUT_DIR}/$MODULE.types";
123 my $new_types = "${OUTPUT_DIR}/$MODULE.types.new";
124 my $sections_file = "${OUTPUT_DIR}/$MODULE-sections.txt";
126 # If this is the very first run then we create the .types file automatically.
127 if (! -e $sections_file && ! -e $old_types) {
131 open (DECLLIST, ">$new_decl_list")
132 || die "Can't open $new_decl_list";
133 open (DECL, ">$new_decl")
134 || die "Can't open $new_decl";
135 if ($REBUILD_TYPES) {
136 open (TYPES, ">$new_types")
137 || die "Can't open $new_types";
141 my $object_list = "";
147 # do not read files twice; checking it here permits to give both srcdir and
148 # builddir as --source-dir without fear of duplicities
151 # The header files to scan are passed in as command-line args.
153 &ScanHeader ($file, \$object_list, \$main_list);
156 for my $dir (@SOURCE_DIRS) {
157 &ScanHeaders ($dir, \$object_list, \$main_list);
160 print DECLLIST $object_list, $main_list;
163 if ($REBUILD_TYPES) {
166 foreach $func (sort(@get_types)) {
167 print TYPES "$func\n";
170 &UpdateFileIfChanged ($old_types, $new_types, 1);
172 # remove the file if empty
173 if (scalar (@get_types) == 0) {
174 unlink ("$new_types");
178 &UpdateFileIfChanged ($old_decl_list, $new_decl_list, 1);
179 &UpdateFileIfChanged ($old_decl, $new_decl, 1);
181 # If there is no MODULE-sections.txt file yet or we are asked to rebuild it,
182 # we copy the MODULE-decl-list.txt file into its place. The user can tweak it
183 # later if they want.
184 if ($REBUILD_SECTIONS || ! -e $sections_file) {
185 `cp $old_decl_list $sections_file`;
188 # If there is no MODULE-overrides.txt file we create an empty one
189 # because EXTRA_DIST in gtk-doc.make requires it.
190 my $overrides_file = "${OUTPUT_DIR}/$MODULE-overrides.txt";
191 if (! -e $overrides_file) {
192 `touch $overrides_file`;
197 #############################################################################
198 # Function : ScanHeaders
199 # Description : This scans a directory tree looking for header files.
201 # Arguments : $source_dir - the directory to scan.
202 # $object_list - a reference to the list of object functions &
204 # $main_list - a reference to the list of other declarations.
205 #############################################################################
208 my ($source_dir, $object_list, $main_list) = @_;
209 #print "Scanning source directory: $source_dir\n";
211 # This array holds any subdirectories found.
214 opendir (SRCDIR, $source_dir)
215 || die "Can't open source directory $source_dir: $!";
217 foreach $file (readdir (SRCDIR)) {
218 if ($file eq '.' || $file eq '..' || $file =~ /^\./) {
220 } elsif (-d "$source_dir/$file") {
221 push (@subdirs, $file);
222 } elsif ($file =~ m/\.h$/) {
223 &ScanHeader ("$source_dir/$file", $object_list, $main_list);
228 # Now recursively scan the subdirectories.
230 foreach $dir (@subdirs) {
231 next if ($IGNORE_HEADERS =~ m/(\s|^)\Q${dir}\E(\s|$)/);
232 &ScanHeaders ("$source_dir/$dir", $object_list, $main_list);
237 #############################################################################
238 # Function : ScanHeader
239 # Description : This scans a header file, looking for declarations of
240 # functions, macros, typedefs, structs and unions, which it
241 # outputs to the DECL file.
242 # Arguments : $input_file - the header file to scan.
243 # $object_list - a reference to the list of object functions &
245 # $main_list - a reference to the list of other declarations.
246 # Returns : it adds declarations to the appropriate list.
247 #############################################################################
250 my ($input_file, $object_list, $main_list) = @_;
252 my $list = ""; # Holds the resulting list of declarations.
253 my ($in_comment) = 0; # True if we are in a comment.
254 my ($in_declaration) = ""; # The type of declaration we are in, e.g.
255 # 'function' or 'macro'.
256 my ($skip_block) = 0; # True if we should skip a block.
257 my ($symbol); # The current symbol being declared.
258 my ($decl); # Holds the declaration of the current symbol.
259 my ($ret_type); # For functions and function typedefs this
260 # holds the function's return type.
261 my ($pre_previous_line) = ""; # The pre-previous line read in - some Gnome
262 # functions have the return type on one
263 # line, the function name on the next,
264 # and the rest of the declaration after.
265 my ($previous_line) = ""; # The previous line read in - some Gnome
266 # functions have the return type on one line
267 # and the rest of the declaration after.
268 my ($first_macro) = 1; # Used to try to skip the standard #ifdef XXX
269 # #define XXX at the start of headers.
270 my ($level); # Used to handle structs/unions which contain
271 # nested structs or unions.
272 my @objects = (); # Holds declarations that look like GtkObject
273 # subclasses, which we remove from the list.
277 my $deprecated_conditional_nest = 0;
281 # Don't scan headers twice
282 my $canonical_input_file = realpath $input_file;
283 return if exists $seen_headers{$canonical_input_file};
284 $seen_headers{$canonical_input_file} = 1;
286 if ($input_file =~ m/^.*[\/\\](.*)\.h+$/) {
289 print "WARNING: Can't find basename of file $input_file\n";
290 $file_basename = $input_file;
293 # Check if the basename is in the list of headers to ignore.
294 if ($IGNORE_HEADERS =~ m/(\s|^)\Q${file_basename}\E\.h(\s|$)/) {
295 #print "DEBUG: File ignored: $input_file\n";
299 if (! -f $input_file) {
300 print "WARNING: File doesn't exist: $input_file\n";
304 #print "DEBUG: Scanning $input_file\n";
306 open(INPUT, $input_file)
307 || die "Can't open $input_file: $!";
309 # If this is a private header, skip it.
310 if (m%^\s*/\*\s*<\s*private_header\s*>\s*\*/%) {
315 # Skip to the end of the current comment.
317 #print "Comment: $_";
323 # Skip complete blocks, needed fo inline macros
324 if ($skip_block==1) {
329 } elsif ($skip_block==2) {
336 # Keep a count of #if, #ifdef, #ifndef nesting,
337 # and if we enter a deprecation-symbol-bracketed
339 if (m/^\s*#\s*if(?:n?def\b|\s+!?\s*defined\s*\()\s*(\w+)/) {
340 if ($deprecated_conditional_nest == 0 and $1 =~ /$DEPRECATED_GUARDS/) {
341 $deprecated_conditional_nest = 1;
342 } elsif ($deprecated_conditional_nest > 0) {
343 $deprecated_conditional_nest += 1;
345 } elsif (m/^\s*#\sif/) {
346 if ($deprecated_conditional_nest > 0) {
347 $deprecated_conditional_nest += 1;
349 } elsif (m/^\s*#endif/) {
350 if ($deprecated_conditional_nest > 0) {
351 $deprecated_conditional_nest -= 1;
355 # set global that affects AddSymbolToList
356 if ($deprecated_conditional_nest > 0) {
357 $deprecated = "<DEPRECATED/>\n";
362 if (!$in_declaration) {
363 # Skip top-level comments.
366 #print "Found one-line comment: $_";
369 #print "Found start of comment: $_";
378 if (m/^\s*#\s*define\s+(\w+)/) {
380 # We assume all macros which start with '_' are private, but
381 # we accept '_' itself which is the standard gettext macro.
382 # We also try to skip the first macro if it looks like the
383 # standard #ifndef HEADER_FILE #define HEADER_FILE etc.
384 # And we only want TRUE & FALSE defined in GLib (libdefs.h in
385 # libgnome also defines them if they are not already defined).
386 if (($symbol !~ m/^_/
387 && ($previous_line !~ m/#ifndef\s+$symbol/
388 || $first_macro == 0)
389 && (($symbol ne 'TRUE' && $symbol ne 'FALSE')
390 || $MODULE eq 'glib'))
393 $in_declaration = "macro";
396 #print "DEBUG: Macro: $symbol\n";
399 # TYPEDEF'D FUNCTIONS (i.e. user functions)
402 } elsif (m/^\s*typedef\s+((const\s+|G_CONST_RETURN\s+)?\w+)(\s+const)?\s*(\**)\s*\(\*\s*(\w+)\)\s*\(/) {
403 my $p3 = defined($3) ? $3 : "";
404 $ret_type = "$1$p3 $4";
407 $in_declaration = "user_function";
408 #print "DEBUG: user function (1): $symbol, Returns: $ret_type\n";
411 } elsif (($previous_line =~ m/^\s*typedef\s*/) && m/^\s*((const\s+|G_CONST_RETURN\s+)?\w+)(\s+const)?\s*(\**)\s*\(\*\s*(\w+)\)\s*\(/) {
412 my $p3 = defined($3) ? $3 : "";
413 $ret_type = "$1$p3 $4";
416 $in_declaration = "user_function";
417 #print "DEBUG: user function (2): $symbol, Returns: $ret_type\n";
420 } elsif (($previous_line =~ m/^\s*typedef\s*/) && m/^\s*(\**)\s*\(\*\s*(\w+)\)\s*\(/) {
425 if ($previous_line =~ m/^\s*typedef\s*((const\s+|G_CONST_RETURN\s+)?\w+)(\s+const)?\s*/) {
426 my $p3 = defined($3) ? $3 : "";
427 $ret_type = "$1$p3 ".$ret_type;
428 $in_declaration = "user_function";
429 #print "DEBUG: user function (3): $symbol, Returns: $ret_type\n";
432 # FUNCTION POINTER VARIABLES
434 } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((const\s+|G_CONST_RETURN\s+)?\w+)(\s+const)?\s*(\**)\s*\(\*\s*(\w+)\)\s*\(/o) {
435 my $p3 = defined($3) ? $3 : "";
436 $ret_type = "$1$p3 $4";
439 $in_declaration = "user_function";
440 #print "DEBUG: function pointer variable: $symbol, Returns: $ret_type\n";
444 } elsif (s/^\s*enum\s+_(\w+)\s+\{/enum $1 {/) {
445 # We assume that 'enum _<enum_name> {' is really the
446 # declaration of enum <enum_name>.
448 #print "DEBUG: plain enum: $symbol\n";
450 $in_declaration = "enum";
452 } elsif (m/^\s*typedef\s+enum\s+_?(\w+)\s+\1\s*;/) {
453 # We skip 'typedef enum <enum_name> _<enum_name>;' as the enum will
454 # be declared elsewhere.
455 #print "DEBUG: skipping enum typedef: $1\n";
457 } elsif (m/^\s*typedef\s+enum/) {
459 #print "DEBUG: typedef enum: -\n";
461 $in_declaration = "enum";
466 } elsif (m/^\s*typedef\s+(struct|union)\s+_(\w+)\s+\2\s*;/) {
467 # We've found a 'typedef struct _<name> <name>;'
468 # This could be an opaque data structure, so we output an
469 # empty declaration. If the structure is actually found that
470 # will override this.
471 my $structsym = uc $1;
472 #print "DEBUG: $structsym typedef: $2\n";
473 &AddSymbolToList (\$list, $2);
474 print DECL "<$structsym>\n<NAME>$2</NAME>\n$deprecated</$structsym>\n";
476 } elsif (m/^\s*(?:struct|union)\s+_(\w+)\s*;/) {
477 # Skip private structs/unions.
478 #print "DEBUG: private struct/union\n";
480 } elsif (m/^\s*(struct|union)\s+(\w+)\s*;/) {
481 # Do a similar thing for normal structs as for typedefs above.
482 # But we output the declaration as well in this case, so we
483 # can differentiate it from a typedef.
484 my $structsym = uc $1;
485 #print "DEBUG: $structsym: $2\n";
486 &AddSymbolToList (\$list, $2);
487 print DECL "<$structsym>\n<NAME>$2</NAME>\n$_$deprecated</$structsym>\n";
489 } elsif (m/^\s*typedef\s+(struct|union)\s*\w*\s*{/) {
493 $in_declaration = $1;
494 #print "DEBUG: $1\n";
498 } elsif (m/^\s*typedef\s+(?:struct|union)\s+\w+[\s\*]+(\w+)\s*;/) {
499 #print "DEBUG: Found struct/union(*) typedef $1: $_";
500 &AddSymbolToList (\$list, $1);
501 print DECL "<TYPEDEF>\n<NAME>$1</NAME>\n$deprecated$_</TYPEDEF>\n";
503 } elsif (m/^\s*(G_GNUC_EXTENSION\s+)?typedef\s+(.+[\s\*])(\w+)(\s*\[[^\]]+\])*\s*;/) {
504 if ($2 !~ m/^struct\s/ && $2 !~ m/^union\s/) {
505 #print "DEBUG: Found typedef: $_";
506 &AddSymbolToList (\$list, $3);
507 print DECL "<TYPEDEF>\n<NAME>$3</NAME>\n$deprecated$_</TYPEDEF>\n";
509 } elsif (m/^\s*typedef\s+/) {
510 #print "DEBUG: Skipping typedef: $_";
513 # VARIABLES (extern'ed variables)
515 } elsif (m/^\s*(extern|[A-Za-z_]+VAR)\s+((const\s+|signed\s+|unsigned\s+)*\w+)(\s+\*+|\*+|\s)\s*([A-Za-z]\w*)\s*;/) {
517 s/^\s*([A-Za-z_]+VAR)\b/extern/;
518 #print "DEBUG: Possible extern: $_";
519 &AddSymbolToList (\$list, $symbol);
520 print DECL "<VARIABLE>\n<NAME>$symbol</NAME>\n$deprecated$_</VARIABLE>\n";
525 # We assume that functions which start with '_' are private, so
528 } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|signed\s+|unsigned\s+|long\s+|short\s+|struct\s+|union\s+|enum\s+)*_\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*\(\s*\*+\s*([A-Za-z]\w*)\s*\)\s*\(/o) {
532 #print "DEBUG: internal Function: $symbol, Returns: $ret_type\n";
533 $in_declaration = "function";
536 } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|signed\s+|unsigned\s+|long\s+|short\s+|struct\s+|union\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*([A-Za-z]\w*)\s*\(/o) {
540 #print "DEBUG: Function (1): $symbol, Returns: $ret_type\n";
541 $in_declaration = "function";
543 # Try to catch function declarations which have the return type on
544 # the previous line. But we don't want to catch complete functions
545 # which have been declared G_INLINE_FUNC, e.g. g_bit_nth_lsf in
546 # glib, or 'static inline' functions.
547 } elsif (m/^\s*([A-Za-z]\w*)\s*\(/) {
551 if ($previous_line !~ m/^\s*G_INLINE_FUNC/) {
552 if ($previous_line !~ m/^\s*static\s+/) {
554 if ($previous_line =~ m/^\s*(?:\b(?:extern|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|signed\s+|unsigned\s+|struct\s+|union\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
556 if (defined ($2)) { $ret_type .= " $2"; }
557 #print "DEBUG: Function (2): $symbol, Returns: $ret_type\n";
558 $in_declaration = "function";
563 if ($previous_line !~ m/^\s*static\s+/) {
564 #print "DEBUG: skip block after inline function\n";
565 # now we we need to skip a whole { } block
568 if ($previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|signed\s+|unsigned\s+|struct\s+|union\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
570 if (defined ($2)) { $ret_type .= " $2"; }
571 #print "DEBUG: Function (3): $symbol, Returns: $ret_type\n";
572 $in_declaration = "function";
573 # this is a hack to detect the end of declaration
579 # Try to catch function declarations with the return type and name
580 # on the previous line(s), and the start of the parameters on this.
581 } elsif (m/^\s*\(/) {
583 if ($previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|signed\s+|unsigned\s+|enum\s+)*\w+)(\s+\*+|\*+|\s)\s*([A-Za-z]\w*)\s*$/o) {
586 #print "DEBUG: Function (4): $symbol, Returns: $ret_type\n";
587 $in_declaration = "function";
589 } elsif ($previous_line =~ m/^\s*\w+\s*$/
590 && $pre_previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|signed\s+|unsigned\s+|struct\s+|union\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*$/o) {
592 $ret_type =~ s/\s*\n//;
593 $in_declaration = "function";
595 $symbol = $previous_line;
597 $symbol =~ s/\s*\n//;
598 #print "DEBUG: Function (5): $symbol, Returns: $ret_type\n";
601 #} elsif (m/^extern\s+/) {
602 #print "DEBUG: Skipping extern: $_";
607 } elsif (m/^\s*struct\s+_(\w+)\s*\*/) {
608 # Skip 'struct _<struct_name> *', since it could be a
609 # return type on its own line.
611 } elsif (m/^\s*struct\s+_(\w+)/) {
612 # We assume that 'struct _<struct_name>' is really the
613 # declaration of struct <struct_name>.
616 # we will find the correct level as below we do $level += tr/{//;
618 $in_declaration = "struct";
619 #print "DEBUG: Struct(_): $symbol\n";
624 } elsif (m/^\s*union\s+_(\w+)\s*\*/) {
625 # Skip 'union _<union_name> *' (see above)
626 } elsif (m/^\s*union\s+_(\w+)/) {
630 $in_declaration = "union";
631 #print "DEBUG: Union(_): $symbol\n";
636 # If we were already in the middle of a declaration, we simply add
637 # the current line onto the end of it.
641 #if ($in_declaration ne '') {
642 # print "$in_declaration = $decl\n";
645 # Note that sometimes functions end in ') G_GNUC_PRINTF (2, 3);' or
646 # ') __attribute__ (...);'.
647 if ($in_declaration eq 'function') {
648 if ($decl =~ s/\)\s*(G_GNUC_.*|${IGNORE_DECORATORS}\s*|__attribute__\s*\(.*\)\s*)?;.*$//) {
649 $decl =~ s%/\*.*?\*/%%gs; # remove comments.
650 #$decl =~ s/^\s+//; # remove leading whitespace.
651 #$decl =~ s/\s+$//; # remove trailing whitespace.
652 $decl =~ s/\s*\n\s*/ /gs; # consolidate whitespace at start
654 $ret_type =~ s%/\*.*?\*/%%g; # remove comments in ret type.
655 &AddSymbolToList (\$list, $symbol);
656 print DECL "<FUNCTION>\n<NAME>$symbol</NAME>\n$deprecated<RETURNS>$ret_type</RETURNS>\n$decl\n</FUNCTION>\n";
657 if ($REBUILD_TYPES) {
658 # check if this looks like a get_type function and if so remember
659 if (($symbol =~ m/_get_type$/) && ($ret_type =~ m/GType/) && ($decl =~ m/(void|)/)) {
660 #print "Adding get-type: [$ret_type] [$symbol] [$decl]\tfrom $input_file\n";
661 push (@get_types, $symbol);
664 $in_declaration = "";
668 if ($in_declaration eq 'user_function') {
669 if ($decl =~ s/\).*$//) {
670 &AddSymbolToList (\$list, $symbol);
671 print DECL "<USER_FUNCTION>\n<NAME>$symbol</NAME>\n$deprecated<RETURNS>$ret_type</RETURNS>\n$decl</USER_FUNCTION>\n";
672 $in_declaration = "";
676 if ($in_declaration eq 'macro') {
677 if ($decl !~ m/\\\s*$/) {
678 &AddSymbolToList (\$list, $symbol);
679 print DECL "<MACRO>\n<NAME>$symbol</NAME>\n$deprecated$decl</MACRO>\n";
680 $in_declaration = "";
684 if ($in_declaration eq 'enum') {
685 if ($decl =~ m/\}\s*(\w+)?;\s*$/) {
689 &AddSymbolToList (\$list, $symbol);
690 print DECL "<ENUM>\n<NAME>$symbol</NAME>\n$deprecated$decl</ENUM>\n";
691 $in_declaration = "";
695 # We try to handle nested stucts/unions, but unmatched brackets in
696 # comments will cause problems.
697 if ($in_declaration eq 'struct' or $in_declaration eq 'union') {
698 if ($level <= 1 && $decl =~ m/\}\s*(\w*);\s*$/) {
703 if ($symbol =~ m/^(\S+)(Class|Iface|Interface)\b/) {
705 #print "Found object: $1\n";
706 $list = "<TITLE>$objectname</TITLE>\n$list";
707 push (@objects, $objectname);
709 #print "Store struct: $symbol\n";
710 &AddSymbolToList (\$list, $symbol);
712 my $structsym = uc $in_declaration;
713 print DECL "<$structsym>\n<NAME>$symbol</NAME>\n$deprecated$decl</$structsym>\n";
714 $in_declaration = "";
716 # We use tr to count the brackets in the line, and adjust
717 # $level accordingly.
720 #print "struct/union level : $level\n";
724 $pre_previous_line = $previous_line;
729 #print "DEBUG: Scanning $input_file done\n\n\n";
732 # Try to separate the standard macros and functions, placing them at the
733 # end of the current section, in a subsection named 'Standard'.
735 my ($standard_decl) = "";
736 if ($list =~ m/^\S+_IS_(\S*)_CLASS/m) {
738 } elsif ($list =~ m/^\S+_IS_(\S*)/m) {
743 if ($list =~ s/^\S+_IS_$class\n//m) { $standard_decl .= $&; }
744 if ($list =~ s/^\S+_TYPE_$class\n//m) { $standard_decl .= $&; }
745 if ($list =~ s/^\S+_.*_get_type\n//m) { $standard_decl .= $&; }
746 if ($list =~ s/^\S+_${class}_CLASS\n//m) { $standard_decl .= $&; }
747 if ($list =~ s/^\S+_IS_${class}_CLASS\n//m) { $standard_decl .= $&; }
748 if ($list =~ s/^\S+_${class}_GET_CLASS\n//m) { $standard_decl .= $&; }
749 if ($list =~ s/^\S+_${class}_GET_IFACE\n//m) { $standard_decl .= $&; }
750 if ($list =~ s/^\S+_${class}_GET_INTERFACE\n//m) { $standard_decl .= $&; }
752 # We do this one last, otherwise it tends to be caught by the IS_$class macro
753 if ($list =~ s/^\S+_$class\n//m) { $standard_decl = $& . $standard_decl; }
755 if ($standard_decl ne "") {
756 $list .= "<SUBSECTION Standard>\n$standard_decl";
760 $$object_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n\n";
764 $$main_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n\n";
770 #############################################################################
771 # Function : AddSymbolToList
772 # Description : This adds the symbol to the list of declarations, but only if
773 # it is not already in the list.
774 # Arguments : $list - reference to the list of symbols, one on each line.
775 # $symbol - the symbol to add to the list.
776 #############################################################################
778 sub AddSymbolToList {
779 my ($list, $symbol) = @_;
781 if ($$list =~ m/\b\Q$symbol\E\b/) {
782 # print "Symbol $symbol already in list. skipping\n";
785 $$list .= "$symbol\n";