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 #############################################################################
42 unshift @INC, '@PACKAGE_DATA_DIR@';
43 require "gtkdoc-common.pl";
47 # name of documentation module
51 my $IGNORE_HEADERS = "";
56 # regexp matching cpp symbols which surround deprecated stuff
57 # e.g. 'GTK_ENABLE_BROKEN|GTK_DISABLE_DEPRECATED'
58 # these are detected if they are used as #if FOO, #ifndef FOO, or #ifdef FOO
59 my $DEPRECATED_GUARDS;
60 # regexp matching decorators that should be ignored
61 my $IGNORE_DECORATORS;
63 my %optctl = (module => \$MODULE,
64 'source-dir' => \@SOURCE_DIRS,
65 'ignore-headers' => \$IGNORE_HEADERS,
66 'output-dir' => \$OUTPUT_DIR,
67 'rebuild-types' => \$REBUILD_TYPES,
68 'rebuild-sections' => \$REBUILD_SECTIONS,
69 'version' => \$PRINT_VERSION,
70 'help' => \$PRINT_HELP,
71 'deprecated-guards' => \$DEPRECATED_GUARDS,
72 'ignore-decorators' => \$IGNORE_DECORATORS);
73 GetOptions(\%optctl, "module=s", "source-dir:s", "ignore-headers:s",
74 "output-dir:s", "rebuild-types", "rebuild-sections", "version",
75 "help", "deprecated-guards:s", "ignore-decorators:s");
87 print "gtkdoc-scan version @VERSION@\n";
88 print "\n--module=MODULE_NAME Name of the doc module being parsed";
89 print "\n--source-dir=DIRNAME Directories containing the source files to scan";
90 print "\n--ignore-headers=FILES A space-separated list of header files not to scan";
91 print "\n--output-dir=DIRNAME The directory where the results are stored";
92 print "\n--deprecated-guards=GUARDS A |-separated list of symbols used as deprecation guards";
93 print "\n--ignore-decorators=DECS A |-separated list of addition decorators in declarations that should be ignored";
94 print "\n--rebuild-sections Rebuild (overwrite) the MODULE-sections.txt file";
95 print "\n--rebuild-types Automatically recreate the MODULE.types file using all the *_get_type() functions found";
96 print "\n--version Print the version of this program";
97 print "\n--help Print this help\n";
101 $DEPRECATED_GUARDS = $DEPRECATED_GUARDS ? $DEPRECATED_GUARDS : "does_not_match_any_cpp_symbols_at_all_nope";
103 $IGNORE_DECORATORS = $IGNORE_DECORATORS || "(?=no)match";
105 $OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : ".";
107 if (!-d ${OUTPUT_DIR}) {
108 mkdir($OUTPUT_DIR, 0755) || die "Cannot create $OUTPUT_DIR: $!";
111 my $old_decl_list = "${OUTPUT_DIR}/$MODULE-decl-list.txt";
112 my $new_decl_list = "${OUTPUT_DIR}/$MODULE-decl-list.new";
113 my $old_decl = "${OUTPUT_DIR}/$MODULE-decl.txt";
114 my $new_decl = "${OUTPUT_DIR}/$MODULE-decl.new";
115 my $old_types = "${OUTPUT_DIR}/$MODULE.types";
116 my $new_types = "${OUTPUT_DIR}/$MODULE.types.new";
117 my $sections_file = "${OUTPUT_DIR}/$MODULE-sections.txt";
119 # If this is the very first run then we create the .types file automatically.
120 if (! -e $sections_file && ! -e $old_types) {
124 open (DECLLIST, ">$new_decl_list")
125 || die "Can't open $new_decl_list";
126 open (DECL, ">$new_decl")
127 || die "Can't open $new_decl";
128 if ($REBUILD_TYPES) {
129 open (TYPES, ">$new_types")
130 || die "Can't open $new_types";
134 my $object_list = "";
137 # The header files to scan are passed in as command-line args.
139 &ScanHeader ($file, \$object_list, \$main_list);
142 for my $dir (@SOURCE_DIRS) {
143 &ScanHeaders ($dir, \$object_list, \$main_list);
146 print DECLLIST $object_list, $main_list;
149 close (TYPES) if ($REBUILD_TYPES);
151 &UpdateFileIfChanged ($old_decl_list, $new_decl_list, 1);
152 &UpdateFileIfChanged ($old_decl, $new_decl, 1);
153 &UpdateFileIfChanged ($old_types, $new_types, 1) if ($REBUILD_TYPES);
155 # If there is no MODULE-sections.txt file yet or we are asked to rebuild it,
156 # we copy the MODULE-decl-list.txt file into its place. The user can tweak it
157 # later if they want.
158 if ($REBUILD_SECTIONS || ! -e $sections_file) {
159 `cp $old_decl_list $sections_file`;
162 # If there is no MODULE-overrides.txt file we create an empty one.
163 my $overrides_file = "${OUTPUT_DIR}/$MODULE-overrides.txt";
164 if (! -e $overrides_file) {
165 `touch $overrides_file`;
170 #############################################################################
171 # Function : ScanHeaders
172 # Description : This scans a directory tree looking for header files.
174 # Arguments : $source_dir - the directory to scan.
175 # $object_list - a reference to the list of object functions &
177 # $main_list - a reference to the list of other declarations.
178 #############################################################################
181 my ($source_dir, $object_list, $main_list) = @_;
182 # print "Scanning source directory: $source_dir\n";
184 # This array holds any subdirectories found.
187 opendir (SRCDIR, $source_dir)
188 || die "Can't open source directory $source_dir: $!";
190 foreach $file (readdir (SRCDIR)) {
191 if ($file eq '.' || $file eq '..' || $file =~ /^\./) {
193 } elsif (-d "$source_dir/$file") {
194 push (@subdirs, $file);
195 } elsif ($file =~ m/\.h$/) {
196 &ScanHeader ("$source_dir/$file", $object_list, $main_list);
201 # Now recursively scan the subdirectories.
203 foreach $dir (@subdirs) {
204 next if ($IGNORE_HEADERS =~ m/(\s|^)\Q${dir}\E(\s|$)/);
205 &ScanHeaders ("$source_dir/$dir", $object_list, $main_list);
210 #############################################################################
211 # Function : ScanHeader
212 # Description : This scans a header file, looking for declarations of
213 # functions, macros, typedefs, structs and unions, which it
214 # outputs to the DECL file.
215 # Arguments : $input_file - the header file to scan.
216 # $object_list - a reference to the list of object functions &
218 # $main_list - a reference to the list of other declarations.
219 # Returns : it adds declarations to the appropriate list.
220 #############################################################################
223 my ($input_file, $object_list, $main_list) = @_;
224 # print "DEBUG: Scanning $input_file\n";
226 my $list = ""; # Holds the resulting list of declarations.
227 my ($in_comment) = 0; # True if we are in a comment.
228 my ($in_declaration) = ""; # The type of declaration we are in, e.g.
229 # 'function' or 'macro'.
230 my ($symbol); # The current symbol being declared.
231 my ($decl); # Holds the declaration of the current symbol.
232 my ($ret_type); # For functions and function typedefs this
233 # holds the function's return type.
234 my ($pre_previous_line) = ""; # The pre-previous line read in - some Gnome
235 # functions have the return type on one
236 # line, the function name on the next,
237 # and the rest of the declaration after.
238 my ($previous_line) = ""; # The previous line read in - some Gnome
239 # functions have the return type on one line
240 # and the rest of the declaration after.
241 my ($first_macro) = 1; # Used to try to skip the standard #ifdef XXX
242 # #define XXX at the start of headers.
243 my ($level); # Used to handle structs which contain nested
245 my @objects = (); # Holds declarations that look like GtkObject
246 # subclasses, which we remove from the list.
250 my $deprecated_conditional_nest = 0;
254 if ($input_file =~ m/^.*[\/\\](.*)\.h$/) {
257 print "WARNING: Can't find basename of file $input_file\n";
258 $file_basename = $input_file;
261 # Check if the basename is in the list of headers to ignore.
262 if ($IGNORE_HEADERS =~ m/(\s|^)\Q${file_basename}\E\.h(\s|$)/) {
263 # print "DEBUG: File ignored: $input_file\n";
267 if (! -f $input_file) {
268 print "File doesn't exist: $input_file\n";
272 open(INPUT, $input_file)
273 || die "Can't open $input_file: $!";
275 # If this is a private header, skip it.
276 if (m%^\s*/\*\s*<\s*private_header\s*>\s*\*/%) {
281 # Skip to the end of the current comment.
283 # print "Comment: $_";
290 # Keep a count of #if, #ifdef, #ifndef nesting,
291 # and if we enter a deprecation-symbol-bracketed
293 if (m/^\s*#\s*if(?:n?def\b|\s+!?\s*defined\s*\()\s*(\w+)/) {
294 if ($deprecated_conditional_nest == 0 and $1 =~ /$DEPRECATED_GUARDS/) {
295 $deprecated_conditional_nest = 1;
296 } elsif ($deprecated_conditional_nest > 0) {
297 $deprecated_conditional_nest += 1;
299 } elsif (m/^\s*#\sif/) {
300 if ($deprecated_conditional_nest > 0) {
301 $deprecated_conditional_nest += 1;
303 } elsif (m/^\s*#endif/) {
304 if ($deprecated_conditional_nest > 0) {
305 $deprecated_conditional_nest -= 1;
309 # set global that affects AddSymbolToList
310 if ($deprecated_conditional_nest > 0) {
311 $deprecated = "<DEPRECATED/>\n";
316 if (!$in_declaration) {
317 # Skip top-level comments.
320 # print "Found one-line comment: $_";
323 # print "Found start of comment: $_";
330 if (m/^\s*#\s*define\s+(\w+)/) {
332 # We assume all macros which start with '_' are private, but
333 # we accept '_' itself which is the standard gettext macro.
334 # We also try to skip the first macro if it looks like the
335 # standard #ifndef HEADER_FILE #define HEADER_FILE etc.
336 # And we only want TRUE & FALSE defined in GLib (libdefs.h in
337 # libgnome also defines them if they are not already defined).
338 if (($symbol !~ m/^_/
339 && ($previous_line !~ m/#ifndef\s+$symbol/
340 || $first_macro == 0)
341 && (($symbol ne 'TRUE' && $symbol ne 'FALSE')
342 || $MODULE eq 'glib'))
345 $in_declaration = "macro";
350 # TYPEDEF'D FUNCTIONS (i.e. user functions)
352 } elsif (m/^\s*typedef\s+((const\s+|G_CONST_RETURN\s+)?\w+)\s*(\**)\s*\(\*\s*(\w+)\)\s*\(/) {
356 $in_declaration = "user_function";
361 } elsif (s/^\s*enum\s+_(\w+)\s+\{/enum $1 {/) {
362 # We assume that 'enum _<enum_name> {' is really the
363 # declaration of enum <enum_name>.
365 # print "DEBUG: plain enum: $symbol\n";
367 $in_declaration = "enum";
369 } elsif (m/^\s*typedef\s+enum\s+_(\w+)\s+\1\s*;/) {
370 # We skip 'typedef <enum_name> _<enum_name>;' as the enum will
371 # be declared elsewhere.
372 # print "DEBUG: skipping enum typedef: $1\n";
374 } elsif (m/^\s*typedef\s+enum/) {
376 # print "DEBUG: typedef enum: -\n";
378 $in_declaration = "enum";
383 } elsif (m/^\s*typedef\s+struct\s+_(\w+)\s+\1\s*;/) {
384 # We've found a 'typedef struct _<name> <name>;'
385 # This could be an opaque data structure, so we output an
386 # empty declaration. If the structure is actually found that
387 # will override this.
388 # print "DEBUG: struct typedef: $1\n";
389 &AddSymbolToList (\$list, $1);
390 print DECL "<STRUCT>\n<NAME>$1</NAME>\n$deprecated</STRUCT>\n";
392 } elsif (m/^\s*struct\s+_(\w+)\s*;/) {
393 # Skip private structs.
395 } elsif (m/^\s*struct\s+(\w+)\s*;/) {
396 # Do a similar thing for normal structs as for typedefs above.
397 # But we output the declaration as well in this case, so we
398 # can differentiate it from a typedef.
399 &AddSymbolToList (\$list, $1);
400 print DECL "<STRUCT>\n<NAME>$1</NAME>\n$_$deprecated</STRUCT>\n";
402 } elsif (m/^\s*typedef\s+struct\s*\w*\s*{/) {
406 $in_declaration = "struct";
408 } elsif (m/^\s*struct\s+_?(\w+)/) {
409 # We assume that 'struct _<struct_name>' is really the
410 # declaration of struct <struct_name>.
414 $in_declaration = "struct";
419 } elsif (s/^\s*union\s+_(\w+)/union $1/) {
422 $in_declaration = "union";
427 } elsif (m/^\s*typedef\s+struct\s+\w+[\s\*]+(\w+)\s*;/) {
428 # print "Found struct* typedef: $_";
429 &AddSymbolToList (\$list, $1);
430 print DECL "<TYPEDEF>\n<NAME>$1</NAME>\n$deprecated$_</TYPEDEF>\n";
432 } elsif (m/^\s*(G_GNUC_EXTENSION\s+)?typedef\s+(.+[\s\*])(\w+)(\s*\[[^\]]+\])*\s*;/) {
433 if ($2 !~ m/^struct\s/ && $2 !~ m/^union\s/) {
434 # print "Found typedef: $_";
435 &AddSymbolToList (\$list, $3);
436 print DECL "<TYPEDEF>\n<NAME>$3</NAME>\n$deprecated$_</TYPEDEF>\n";
438 } elsif (m/^\s*typedef\s+/) {
439 # print "Skipping typedef: $_";
442 # VARIABLES (extern'ed variables)
444 } elsif (m/^\s*(extern|[A-Za-z_]+VAR)\s+((const\s+|unsigned\s+)*\w+)(\s+\*+|\*+|\s)\s*([A-Za-z]\w*)\s*;/) {
446 s/^\s*([A-Za-z_]+VAR)\b/extern/;
447 # print "Possible extern: $_";
448 &AddSymbolToList (\$list, $symbol);
449 print DECL "<VARIABLE>\n<NAME>$symbol</NAME>\n$deprecated$_</VARIABLE>\n";
454 # We assume that functions which start with '_' are private, so
456 } 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*\(/) {
461 # print "Function: $symbol, Returns: $ret_type\n";
463 $in_declaration = "function";
465 # Try to catch function declarations which have the return type on
466 # the previous line. But we don't want to catch complete functions
467 # which have been declared G_INLINE_FUNC, e.g. g_bit_nth_lsf in
468 # glib, or 'static inline' functions.
469 } elsif (m/^\s*([A-Za-z]\w*)\s*\(/) {
472 if ($previous_line !~ m/^\s*G_INLINE_FUNC/
473 && $previous_line !~ m/^\s*static\s+/) {
474 if ($previous_line =~ m/^\s*(?:\b(?:extern|${IGNORE_DECORATORS})\b\s*)*((?:const\s+|G_CONST_RETURN\s+|unsigned\s+|enum\s+)?\w+)(\s*\*+)?\s*$/) {
476 if (defined ($2)) { $ret_type .= " $2"; }
477 # print "Function: $symbol, Returns: $ret_type\n";
478 $in_declaration = "function";
482 # Try to catch function declarations with the return type and name
483 # on the previous line(s), and the start of the parameters on this.
484 } elsif (m/^\s*\(/) {
486 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*$/) {
489 # print "Function: $symbol, Returns: $ret_type\n";
490 $in_declaration = "function";
492 } elsif ($previous_line =~ m/^\s*\w+\s*$/
493 && $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*$/) {
495 $ret_type =~ s/\s*\n//;
496 $in_declaration = "function";
498 $symbol = $previous_line;
500 $symbol =~ s/\s*\n//;
501 # print "Function: $symbol, Returns: $ret_type\n";
504 # } elsif (m/^extern\s+/) {
505 # print "Skipping extern: $_";
509 # If we were already in the middle of a declaration, we simply add
510 # the current line onto the end of it.
514 # Note that sometimes functions end in ') G_GNUC_PRINTF (2, 3);' or
515 # ') __attribute__ (...);'.
516 if ($in_declaration eq 'function') {
517 if ($decl =~ s/\)\s*(G_GNUC_.*|__attribute__\s*\(.*\)\s*)?;.*$//) {
518 $decl =~ s%/\*.*?\*/%%gs; # remove comments.
519 # $decl =~ s/^\s+//; # remove leading whitespace.
520 # $decl =~ s/\s+$//; # remove trailing whitespace.
521 $decl =~ s/\s*\n\s*//g; # remove whitespace at start
523 $ret_type =~ s%/\*.*?\*/%%g; # remove comments in ret type.
524 &AddSymbolToList (\$list, $symbol);
525 print DECL "<FUNCTION>\n<NAME>$symbol</NAME>\n$deprecated<RETURNS>$ret_type</RETURNS>\n$decl\n</FUNCTION>\n";
526 $in_declaration = "";
530 if ($in_declaration eq 'user_function') {
531 if ($decl =~ s/\).*$//) {
532 &AddSymbolToList (\$list, $symbol);
533 print DECL "<USER_FUNCTION>\n<NAME>$symbol</NAME>\n$deprecated<RETURNS>$ret_type</RETURNS>\n$decl</USER_FUNCTION>\n";
534 $in_declaration = "";
538 if ($in_declaration eq 'macro') {
539 if ($decl !~ m/\\\s*$/) {
540 &AddSymbolToList (\$list, $symbol);
541 print DECL "<MACRO>\n<NAME>$symbol</NAME>\n$deprecated$decl</MACRO>\n";
542 $in_declaration = "";
546 if ($in_declaration eq 'enum') {
547 if ($decl =~ m/\}\s*(\w+)?;\s*$/) {
551 &AddSymbolToList (\$list, $symbol);
552 print DECL "<ENUM>\n<NAME>$symbol</NAME>\n$deprecated$decl</ENUM>\n";
553 $in_declaration = "";
557 # We try to handle nested stucts/unions, but unmatched brackets in
558 # comments will cause problems.
559 if ($in_declaration eq 'struct') {
560 if ($level <= 1 && $decl =~ m/\}\s*(\w*);\s*$/) {
565 if ($symbol =~ m/^(\S+)Class/) {
566 # print "Found object: $1\n";
567 $list .= "<TITLE>$1</TITLE>\n$1\n";
570 &AddSymbolToList (\$list, $symbol);
572 print DECL "<STRUCT>\n<NAME>$symbol</NAME>\n$deprecated$decl</STRUCT>\n";
573 $in_declaration = "";
575 # We use tr to count the brackets in the line, and adjust
576 # $level accordingly.
582 if ($in_declaration eq 'union') {
583 if ($decl =~ m/\}\s*;\s*$/) {
584 &AddSymbolToList (\$list, $symbol);
585 print DECL "<UNION>\n<NAME>$symbol</NAME>\n$deprecated$decl</UNION>\n";
586 $in_declaration = "";
590 $pre_previous_line = $previous_line;
595 # Take out any object structs from the list of declarations as we don't
596 # want them included.
598 foreach $object (@objects) {
599 $list =~ s/^$object\n//m;
600 $list =~ s/^${object}Class\n//m;
604 # Try to separate the standard macros and functions, placing them at the
605 # end of the current section, in a subsection named 'Standard'.
607 my ($standard_decl) = "";
608 if ($list =~ m/^\S+_IS_(\S*)_CLASS/m) {
610 } elsif ($list =~ m/^\S+_IS_(\S*)/m) {
614 if ($REBUILD_TYPES) {
615 while ($list =~ m/^\S+_.*_get_type\n/mg) {
616 # print "Adding get-type: $&\tfrom $input_file\n";
622 if ($list =~ s/^\S+_IS_$class\n//m) { $standard_decl .= $&; }
623 if ($list =~ s/^\S+_TYPE_$class\n//m) { $standard_decl .= $&; }
624 if ($list =~ s/^\S+_.*_get_type\n//m) { $standard_decl .= $&; }
625 if ($list =~ s/^\S+_${class}_CLASS\n//m) { $standard_decl .= $&; }
626 if ($list =~ s/^\S+_IS_${class}_CLASS\n//m) { $standard_decl .= $&; }
627 if ($list =~ s/^\S+_${class}_GET_CLASS\n//m) { $standard_decl .= $&; }
628 if ($list =~ s/^\S+_${class}_GET_IFACE\n//m) { $standard_decl .= $&; }
630 # We do this one last, otherwise it tends to be caught by the IS_$class macro
631 if ($list =~ s/^\S+_$class\n//m) { $standard_decl = $& . $standard_decl; }
633 if ($standard_decl ne "") {
634 $list .= "<SUBSECTION Standard>\n$standard_decl";
637 $$object_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n\n";
639 $$main_list .= "<SECTION>\n<FILE>$file_basename</FILE>\n$list</SECTION>\n\n";
644 #############################################################################
645 # Function : AddSymbolToList
646 # Description : This adds the symbol to the list of declarations, but only if
647 # it is not already in the list.
648 # Arguments : $list - reference to the list of symbols, one on each line.
649 # $symbol - the symbol to add to the list.
650 #############################################################################
652 sub AddSymbolToList {
653 my ($list, $symbol) = @_;
655 if ($$list =~ m/\b\Q$symbol\E\b/) {
656 # print "Symbol $symbol already in list. skipping\n";
659 $$list .= "$symbol\n";