patch by: David Nečas <yeti@physics.muni.cz>
[gtk-doc.git] / gtkdoc-scan.in
blob27b039a30f420d1f9846b35cb3692d25c82d8812
1 #!@PERL@ -w
2 # -*- cperl -*-
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 #############################################################################
39 use strict;
40 use Getopt::Long;
41 use Cwd qw(realpath);
43 unshift @INC, '@PACKAGE_DATA_DIR@';
44 require "gtkdoc-common.pl";
46 # Options
48 # name of documentation module
49 my $MODULE;
50 my $OUTPUT_DIR;
51 my @SOURCE_DIRS;
52 my $IGNORE_HEADERS = "";
53 my $REBUILD_TYPES;
54 my $REBUILD_SECTIONS;
55 my $PRINT_VERSION;
56 my $PRINT_HELP;
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");
78 if ($PRINT_VERSION) {
79     print "@VERSION@\n";
80     exit 0;
83 if (!$MODULE) {
84     $PRINT_HELP = 1;
87 if ($PRINT_HELP) {
88     print <<EOF;
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
96                            guards
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
105     exit 0;
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) {
128     $REBUILD_TYPES = 1;
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";
140 my $main_list = "";
141 my $object_list = "";
142 my $file;
144 # do not read files twice; checking it here permits to give both srcdir and
145 # builddir as --source-dir without fear of duplicities
146 my %seen_headers;
148 # The header files to scan are passed in as command-line args.
149 for $file (@ARGV) {
150     &ScanHeader ($file, \$object_list, \$main_list);
153 for my $dir (@SOURCE_DIRS) {
154     &ScanHeaders ($dir, \$object_list, \$main_list);
157 print DECLLIST $object_list, $main_list;
158 close (DECLLIST);
159 close (DECL);
160 close (TYPES) if ($REBUILD_TYPES);
162 &UpdateFileIfChanged ($old_decl_list, $new_decl_list, 1);
163 &UpdateFileIfChanged ($old_decl, $new_decl, 1);
164 &UpdateFileIfChanged ($old_types, $new_types, 1) if ($REBUILD_TYPES);
166 # If there is no MODULE-sections.txt file yet or we are asked to rebuild it,
167 # we copy the MODULE-decl-list.txt file into its place. The user can tweak it
168 # later if they want.
169 if ($REBUILD_SECTIONS || ! -e $sections_file) {
170   `cp $old_decl_list $sections_file`;
173 # If there is no MODULE-overrides.txt file we create an empty one.
174 my $overrides_file = "${OUTPUT_DIR}/$MODULE-overrides.txt";
175 if (! -e $overrides_file) {
176   `touch $overrides_file`;
181 #############################################################################
182 # Function    : ScanHeaders
183 # Description : This scans a directory tree looking for header files.
185 # Arguments   : $source_dir - the directory to scan.
186 #               $object_list - a reference to the list of object functions &
187 #                       declarations.
188 #               $main_list - a reference to the list of other declarations.
189 #############################################################################
191 sub ScanHeaders {
192     my ($source_dir, $object_list, $main_list) = @_;
193 #    print "Scanning source directory: $source_dir\n";
195     # This array holds any subdirectories found.
196     my (@subdirs) = ();
198     opendir (SRCDIR, $source_dir)
199         || die "Can't open source directory $source_dir: $!";
200     my $file;
201     foreach $file (readdir (SRCDIR)) {
202         if ($file eq '.' || $file eq '..' || $file =~ /^\./) {
203             next;
204         } elsif (-d "$source_dir/$file") {
205             push (@subdirs, $file);
206         } elsif ($file =~ m/\.h$/) {
207             &ScanHeader ("$source_dir/$file", $object_list, $main_list);
208         }
209     }
210     closedir (SRCDIR);
212     # Now recursively scan the subdirectories.
213     my $dir;
214     foreach $dir (@subdirs) {
215         next if ($IGNORE_HEADERS =~ m/(\s|^)\Q${dir}\E(\s|$)/);
216         &ScanHeaders ("$source_dir/$dir", $object_list, $main_list);
217     }
221 #############################################################################
222 # Function    : ScanHeader
223 # Description : This scans a header file, looking for declarations of
224 #               functions, macros, typedefs, structs and unions, which it
225 #               outputs to the DECL file.
226 # Arguments   : $input_file - the header file to scan.
227 #               $object_list - a reference to the list of object functions &
228 #                       declarations.
229 #               $main_list - a reference to the list of other declarations.
230 # Returns     : it adds declarations to the appropriate list.
231 #############################################################################
233 sub ScanHeader {
234     my ($input_file, $object_list, $main_list) = @_;
236     my $list = "";                # Holds the resulting list of declarations.
237     my ($in_comment) = 0;                 # True if we are in a comment.
238     my ($in_declaration) = "";    # The type of declaration we are in, e.g.
239                                   #   'function' or 'macro'.
240     my ($skip_block) = 0;                 # True if we should skip a block.
241     my ($symbol);                 # The current symbol being declared.
242     my ($decl);                   # Holds the declaration of the current symbol.
243     my ($ret_type);               # For functions and function typedefs this
244                                   #   holds the function's return type.
245     my ($pre_previous_line) = "";   # The pre-previous line read in - some Gnome
246                                   #   functions have the return type on one
247                                   #   line, the function name on the next,
248                                   #   and the rest of the declaration after.
249     my ($previous_line) = "";     # The previous line read in - some Gnome
250                                   #   functions have the return type on one line
251                                   #   and the rest of the declaration after.
252     my ($first_macro) = 1;        # Used to try to skip the standard #ifdef XXX
253                                   #   #define XXX at the start of headers.
254     my ($level);                          # Used to handle structs which contain nested
255                                   #   structs or unions.
256     my @objects = ();             # Holds declarations that look like GtkObject
257                                   #   subclasses, which we remove from the list.
259     my $file_basename;
261     my $deprecated_conditional_nest = 0;
263     my $deprecated = "";
265     # Don't scan headers twice
266     my $canonical_input_file = realpath $input_file;
267     return if exists $seen_headers{$canonical_input_file};
268     $seen_headers{$canonical_input_file} = 1;
270     if ($input_file =~ m/^.*[\/\\](.*)\.h+$/) {
271         $file_basename = $1;
272     } else {
273         print "WARNING: Can't find basename of file $input_file\n";
274         $file_basename = $input_file;
275     }
277     # Check if the basename is in the list of headers to ignore.
278     if ($IGNORE_HEADERS =~ m/(\s|^)\Q${file_basename}\E\.h(\s|$)/) {
279         #print "DEBUG: File ignored: $input_file\n";
280         return;
281     }
283     if (! -f $input_file) {
284         print "WARNING: File doesn't exist: $input_file\n";
285         return;
286     }
288     #print "DEBUG: Scanning $input_file\n";
290     open(INPUT, $input_file)
291         || die "Can't open $input_file: $!";
292     while(<INPUT>) {
293         # If this is a private header, skip it.
294         if (m%^\s*/\*\s*<\s*private_header\s*>\s*\*/%) {
295             close(INPUT);
296             return;
297         }
299         # Skip to the end of the current comment.
300         if ($in_comment) {
301             #print "Comment: $_";
302             if (m%\*/%) {
303                 $in_comment = 0;
304             }
305             next;
306         }
307         # Skip complete blocks, needed fo inline macros
308         if ($skip_block==1) {
309             if (m%{%) {
310                 $skip_block=2;
311             }
312             next;
313         } elsif ($skip_block==2) {
314             if (m%}%) {
315                 $skip_block=0;
316             }
317             next;
318         }
320         # Keep a count of #if, #ifdef, #ifndef nesting,
321         # and if we enter a deprecation-symbol-bracketed
322         # zone, take note.
323         if (m/^\s*#\s*if(?:n?def\b|\s+!?\s*defined\s*\()\s*(\w+)/) {
324             if ($deprecated_conditional_nest == 0 and $1 =~ /$DEPRECATED_GUARDS/) {
325                  $deprecated_conditional_nest = 1;
326             } elsif ($deprecated_conditional_nest > 0) {
327                  $deprecated_conditional_nest += 1;
328             }
329         } elsif (m/^\s*#\sif/) {
330             if ($deprecated_conditional_nest > 0) {
331                  $deprecated_conditional_nest += 1;
332             }
333         } elsif (m/^\s*#endif/) {
334             if ($deprecated_conditional_nest > 0) {
335                 $deprecated_conditional_nest -= 1;
336             }
337         }
339         # set global that affects AddSymbolToList
340         if ($deprecated_conditional_nest > 0) {
341             $deprecated = "<DEPRECATED/>\n";
342         } else {
343             $deprecated = "";
344         }
346         if (!$in_declaration) {
347             # Skip top-level comments.
348             if (s%^\s*/\*%%) {
349                 if (m%\*/%) {
350                     #print "Found one-line comment: $_";
351                 } else {
352                     $in_comment = 1;
353                     #print "Found start of comment: $_";
354                 }
355                 next;
356             }
358             #print "0: $_";
360             # MACROS
362             if (m/^\s*#\s*define\s+(\w+)/) {
363                 $symbol = $1;
364                 # We assume all macros which start with '_' are private, but
365                 # we accept '_' itself which is the standard gettext macro.
366                 # We also try to skip the first macro if it looks like the
367                 # standard #ifndef HEADER_FILE #define HEADER_FILE etc.
368                 # And we only want TRUE & FALSE defined in GLib (libdefs.h in
369                 # libgnome also defines them if they are not already defined).
370                 if (($symbol !~ m/^_/
371                      && ($previous_line !~ m/#ifndef\s+$symbol/
372                          || $first_macro == 0)
373                      && (($symbol ne 'TRUE' && $symbol ne 'FALSE')
374                          || $MODULE eq 'glib'))
375                     || $symbol eq "_") {
376                     $decl = $_;
377                     $in_declaration = "macro";
378                 }
379                 $first_macro = 0;
380                 #print "DEBUG: Macro: $symbol\n";
383             # TYPEDEF'D FUNCTIONS (i.e. user functions)
385             #                        $1                                $3            $4             $5
386             } elsif (m/^\s*typedef\s+((const\s+|G_CONST_RETURN\s+)?\w+)(\s+const)?\s*(\**)\s*\(\*\s*(\w+)\)\s*\(/) {
387                 my $p3 = defined($3) ? $3 : "";
388                 $ret_type = "$1$p3 $4";
389                 $symbol = $5;
390                 $decl = $';
391                 $in_declaration = "user_function";
392                 #print "DEBUG: user function: $symbol\n";
395             # ENUMS
397             } elsif (s/^\s*enum\s+_(\w+)\s+\{/enum $1 {/) {
398                 # We assume that 'enum _<enum_name> {' is really the
399                 # declaration of enum <enum_name>.
400                 $symbol = $1;
401                 #print "DEBUG: plain enum: $symbol\n";
402                 $decl = $_;
403                 $in_declaration = "enum";
405             } elsif (m/^\s*typedef\s+enum\s+_?(\w+)\s+\1\s*;/) {
406                 # We skip 'typedef enum <enum_name> _<enum_name>;' as the enum will
407                 # be declared elsewhere.
408                 #print "DEBUG: skipping enum typedef: $1\n";
410             } elsif (m/^\s*typedef\s+enum/) {
411                 $symbol = "";
412                 #print "DEBUG: typedef enum: -\n";
413                 $decl = $_;
414                 $in_declaration = "enum";
417             # STRUCTS
419             } elsif (m/^\s*typedef\s+struct\s+_(\w+)\s+\1\s*;/) {
420                 # We've found a 'typedef struct _<name> <name>;'
421                 # This could be an opaque data structure, so we output an
422                 # empty declaration. If the structure is actually found that
423                 # will override this.
424                 #print "DEBUG: struct typedef: $1\n";
425                 &AddSymbolToList (\$list, $1);
426                 print DECL "<STRUCT>\n<NAME>$1</NAME>\n$deprecated</STRUCT>\n";
428             } elsif (m/^\s*struct\s+_(\w+)\s*;/) {
429                 # Skip private structs.
430                 #print "DEBUG: private struct\n";
432             } elsif (m/^\s*struct\s+(\w+)\s*;/) {
433                 # Do a similar thing for normal structs as for typedefs above.
434                 # But we output the declaration as well in this case, so we
435                 # can differentiate it from a typedef.
436                 #print "DEBUG: struct: $1\n";
437                 &AddSymbolToList (\$list, $1);
438                 print DECL "<STRUCT>\n<NAME>$1</NAME>\n$_$deprecated</STRUCT>\n";
440             } elsif (m/^\s*typedef\s+struct\s*\w*\s*{/) {
441                 $symbol = "";
442                 $decl = $_;
443                 $level = 0;
444                 $in_declaration = "struct";
445                 #print "DEBUG: struct\n";
447             # OTHER TYPEDEFS
449             } elsif (m/^\s*typedef\s+struct\s+\w+[\s\*]+(\w+)\s*;/) {
450                 #print "DEBUG: Found struct* typedef: $_";
451                 &AddSymbolToList (\$list, $1);
452                 print DECL "<TYPEDEF>\n<NAME>$1</NAME>\n$deprecated$_</TYPEDEF>\n";
454             } elsif (m/^\s*(G_GNUC_EXTENSION\s+)?typedef\s+(.+[\s\*])(\w+)(\s*\[[^\]]+\])*\s*;/) {
455                 if ($2 !~ m/^struct\s/ && $2 !~ m/^union\s/) {
456                     #print "DEBUG: Found typedef: $_";
457                     &AddSymbolToList (\$list, $3);
458                     print DECL "<TYPEDEF>\n<NAME>$3</NAME>\n$deprecated$_</TYPEDEF>\n";
459                 }
460             } elsif (m/^\s*typedef\s+/) {
461                 #print "DEBUG: Skipping typedef: $_";
464             # VARIABLES (extern'ed variables)
466             } elsif (m/^\s*(extern|[A-Za-z_]+VAR)\s+((const\s+|unsigned\s+)*\w+)(\s+\*+|\*+|\s)\s*([A-Za-z]\w*)\s*;/) {
467                 $symbol = $5;
468                 s/^\s*([A-Za-z_]+VAR)\b/extern/;
469                 #print "DEBUG: Possible extern: $_";
470                 &AddSymbolToList (\$list, $symbol);
471                 print DECL "<VARIABLE>\n<NAME>$symbol</NAME>\n$deprecated$_</VARIABLE>\n";
474             # FUNCTIONS
476             # We assume that functions which start with '_' are private, so
477             # we skip them.
478             #                                                                        $1                                                                                                                                 $2
479             } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*\(\s*\*+\s*([A-Za-z]\w*)\s*\)\s*\(/o) {
480                 $ret_type = $1;
481                 $symbol = $2;
482                 $decl = $';
483                 #print "DEBUG: FunctionPointer: $symbol, Returns: $ret_type\n";
484                 $in_declaration = "function";
486             } elsif (m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*([A-Za-z]\w*)\s*\(/o) {
487                 $ret_type = $1;
488                 $symbol = $2;
489                 $decl = $';
490                 #print "DEBUG: Function: $symbol, Returns: $ret_type\n";
491                 $in_declaration = "function";
493             # Try to catch function declarations which have the return type on
494             # the previous line. But we don't want to catch complete functions
495             # which have been declared G_INLINE_FUNC, e.g. g_bit_nth_lsf in
496             # glib, or 'static inline' functions.
497             } elsif (m/^\s*([A-Za-z]\w*)\s*\(/) {
498                 $symbol = $1;
499                 $decl = $';
501                 if ($previous_line !~ m/^\s*G_INLINE_FUNC/) {
502                     if ($previous_line !~ m/^\s*static\s+/) {
503                         #                                                                       $1                                                                $2
504                         if ($previous_line =~ m/^\s*(?:\b(?:extern|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
505                             $ret_type = $1;
506                             if (defined ($2)) { $ret_type .= " $2"; }
507                             #print "DEBUG: Function: $symbol, Returns: $ret_type\n";
508                             $in_declaration = "function";
509                         }
510                     }
511                 }
512                 else {
513                     if ($previous_line !~ m/^\s*static\s+/) {
514                         #print "DEBUG: skip block after inline function\n";
515                         # now we we need to skip a whole { } block
516                         $skip_block = 1;
517                         #                                                                       $1                                                                $2
518                         if ($previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)?\w+)((?:\s*(?:\*+|\bconst\b|\bG_CONST_RETURN\b))*)\s*$/o) {
519                             $ret_type = $1;
520                             if (defined ($2)) { $ret_type .= " $2"; }
521                             #print "DEBUG: Function: $symbol, Returns: $ret_type\n";
522                             $in_declaration = "function";
523                             # this is a hack to detect the end of declaration
524                             $decl.=";"
525                         }
526                     }
527                 }
529             # Try to catch function declarations with the return type and name
530             # on the previous line(s), and the start of the parameters on this.
531             } elsif (m/^\s*\(/) {
532                 $decl = $';
533                 if ($previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|enum\s+)*\w+)(\s+\*+|\*+|\s)\s*([A-Za-z]\w*)\s*$/o) {
534                     $ret_type = "$1 $2";
535                     $symbol = $3;
536                     #print "DEBUG: Function: $symbol, Returns: $ret_type\n";
537                     $in_declaration = "function";
539                 } elsif ($previous_line =~ m/^\s*\w+\s*$/
540                          && $pre_previous_line =~ m/^\s*(?:\b(?:extern|G_INLINE_FUNC|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)*\w+(?:\**\s+\**(?:const|G_CONST_RETURN))?(?:\s+|\s*\*+))\s*$/o) {
541                     $ret_type = $1;
542                     $ret_type =~ s/\s*\n//;
543                     $in_declaration = "function";
544                     
545                     $symbol = $previous_line;
546                     $symbol =~ s/^\s+//;
547                     $symbol =~ s/\s*\n//;
548                     #print "DEBUG: Function: $symbol, Returns: $ret_type\n";
549                 }
551             #} elsif (m/^extern\s+/) {
552                 #print "DEBUG: Skipping extern: $_";
555             # STRUCTS
557             } elsif (m/^\s*struct\s+_(\w+)\s*\*/) {
558                 # Skip 'struct _<struct_name> *', since it could be a
559                 # return type on its own line.
561             } elsif (m/^\s*struct\s+_(\w+)/) {
562                 # We assume that 'struct _<struct_name>' is really the
563                 # declaration of struct <struct_name>.
564                 $symbol = $1;
565                 $decl = $_;
566                 # we will find the correct level as below we do $level += tr/{//;
567                 $level = 0;
568                 $in_declaration = "struct";
569                 #print "DEBUG: Struct(_): $symbol\n";
572             # UNIONS
574             } elsif (s/^\s*union\s+_(\w+)/union $1/) {
575                 $symbol = $1;
576                 $decl = $_;
577                 $in_declaration = "union";
578                 #print "DEBUG: Union: $symbol\n";
579             }
581         } else {
582             #print "1: $_";
583             # If we were already in the middle of a declaration, we simply add
584             # the current line onto the end of it.
585             $decl .= $_;
586         }
588         #if ($in_declaration ne '') {
589         #    print "= $decl\n";
590         #}
592         # Note that sometimes functions end in ') G_GNUC_PRINTF (2, 3);' or
593         # ') __attribute__ (...);'.
594         if ($in_declaration eq 'function') {
595             if ($decl =~ s/\)\s*(G_GNUC_.*|__attribute__\s*\(.*\)\s*)?;.*$//) {
596                 $decl =~ s%/\*.*?\*/%%gs;       # remove comments.
597                 #$decl =~ s/^\s+//;             # remove leading whitespace.
598                 #$decl =~ s/\s+$//;             # remove trailing whitespace.
599                 $decl =~ s/\s*\n\s*//g;         # remove whitespace at start
600                                                 # and end of lines.
601                 $ret_type =~ s%/\*.*?\*/%%g;    # remove comments in ret type.
602                 &AddSymbolToList (\$list, $symbol);
603                 print DECL "<FUNCTION>\n<NAME>$symbol</NAME>\n$deprecated<RETURNS>$ret_type</RETURNS>\n$decl\n</FUNCTION>\n";
604                 $in_declaration = "";
605             }
606         }
608         if ($in_declaration eq 'user_function') {
609             if ($decl =~ s/\).*$//) {
610                 &AddSymbolToList (\$list, $symbol);
611                 print DECL "<USER_FUNCTION>\n<NAME>$symbol</NAME>\n$deprecated<RETURNS>$ret_type</RETURNS>\n$decl</USER_FUNCTION>\n";
612                 $in_declaration = "";
613             }
614         }
616         if ($in_declaration eq 'macro') {
617             if ($decl !~ m/\\\s*$/) {
618                 &AddSymbolToList (\$list, $symbol);
619                 print DECL "<MACRO>\n<NAME>$symbol</NAME>\n$deprecated$decl</MACRO>\n";
620                 $in_declaration = "";
621             }
622         }
624         if ($in_declaration eq 'enum') {
625             if ($decl =~ m/\}\s*(\w+)?;\s*$/) {
626                 if ($symbol eq "") {
627                     $symbol = $1;
628                 }
629                 &AddSymbolToList (\$list, $symbol);
630                 print DECL "<ENUM>\n<NAME>$symbol</NAME>\n$deprecated$decl</ENUM>\n";
631                 $in_declaration = "";
632             }
633         }
635         # We try to handle nested stucts/unions, but unmatched brackets in
636         # comments will cause problems.
637         if ($in_declaration eq 'struct') {
638             if ($level <= 1 && $decl =~ m/\}\s*(\w*);\s*$/) {
639                 if ($symbol eq "") {
640                     $symbol = $1;
641                 }
643                 if ($symbol =~ m/^(\S+)(Class|Iface|Interface)\b/) {
644                     #print "Found object: $1\n";
645                     $list .= "<TITLE>$1</TITLE>\n$1\n";
646                     push (@objects, $1);
647                 }
648                 #print "Store struct: $symbol\n";
649                 &AddSymbolToList (\$list, $symbol);
651                 print DECL "<STRUCT>\n<NAME>$symbol</NAME>\n$deprecated$decl</STRUCT>\n";
652                 $in_declaration = "";
653             } else {
654                 # We use tr to count the brackets in the line, and adjust
655                 # $level accordingly.
656                 $level += tr/{//;
657                 $level -= tr/}//;
658                 #print "struct/union level : $level\n";
659             }
660         }
662         if ($in_declaration eq 'union') {
663             if ($decl =~ m/\}\s*;\s*$/) {
664                 &AddSymbolToList (\$list, $symbol);
665                 print DECL "<UNION>\n<NAME>$symbol</NAME>\n$deprecated$decl</UNION>\n";
666                 $in_declaration = "";
667             }
668         }
670         $pre_previous_line = $previous_line;
671         $previous_line = $_;
672     }
673     close(INPUT);
674     
675     #print "DEBUG: Scanning $input_file done\n\n\n";
677     # Take out any object structs from the list of declarations as we don't
678     # want them included.
679     my ($object);
680     foreach $object (@objects) {
681         $list =~ s/^$object\n//m;
682         $list =~ s/^${object}Class\n//m;
683         $list =~ s/^${object}Iface\n//m;
684         $list =~ s/^${object}Interface\n//m;
685     }
688     # Try to separate the standard macros and functions, placing them at the
689     # end of the current section, in a subsection named 'Standard'.
690     my ($class) = "";
691     my ($standard_decl) = "";
692     if ($list =~ m/^\S+_IS_(\S*)_CLASS/m) {
693         $class = $1;
694     } elsif ($list =~ m/^\S+_IS_(\S*)/m) {
695         $class = $1;
696     }
698     if ($REBUILD_TYPES) {
699       while ($list =~ m/^\S+_.*_get_type\n/mg) {
700 #        print "Adding get-type: $&\tfrom $input_file\n";
701         print TYPES $&;
702       }
703     }
705     if ($class ne "") {
706         if ($list =~ s/^\S+_IS_$class\n//m)          { $standard_decl .= $&; }
707         if ($list =~ s/^\S+_TYPE_$class\n//m)        { $standard_decl .= $&; }
708         if ($list =~ s/^\S+_.*_get_type\n//m)        { $standard_decl .= $&; }
709         if ($list =~ s/^\S+_${class}_CLASS\n//m)     { $standard_decl .= $&; }
710         if ($list =~ s/^\S+_IS_${class}_CLASS\n//m)  { $standard_decl .= $&; }
711         if ($list =~ s/^\S+_${class}_GET_CLASS\n//m) { $standard_decl .= $&; }
712         if ($list =~ s/^\S+_${class}_GET_IFACE\n//m) { $standard_decl .= $&; }
713         if ($list =~ s/^\S+_${class}_GET_INTERFACE\n//m) { $standard_decl .= $&; }
715         # We do this one last, otherwise it tends to be caught by the IS_$class macro
716         if ($list =~ s/^\S+_$class\n//m)             { $standard_decl = $& . $standard_decl; }
718         if ($standard_decl ne "") {
719             $list .= "<SUBSECTION Standard>\n$standard_decl";
720         }
722         $$object_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n\n";
723     } else {
724         $$main_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n\n";
725     }
729 #############################################################################
730 # Function    : AddSymbolToList
731 # Description : This adds the symbol to the list of declarations, but only if
732 #               it is not already in the list.
733 # Arguments   : $list - reference to the list of symbols, one on each line.
734 #               $symbol - the symbol to add to the list.
735 #############################################################################
737 sub AddSymbolToList {
738     my ($list, $symbol) = @_;
740     if ($$list =~ m/\b\Q$symbol\E\b/) {
741 #       print "Symbol $symbol already in list. skipping\n";
742         return;
743     }
744     $$list .= "$symbol\n";