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-mktmpl
24 # Description : This creates or updates the template files which contain the
25 # manually-edited documentation. (A 'template' is a simple text
26 # form which is filled in with the description of a function,
27 # macro, enum, or struct. For functions and macros it also
28 # contains fields for describing the parameters.)
30 # This script reads in the existing templates, found in
31 # tmpl/*.sgml, moves these files to tmpl/*.sgml.bak, and then
32 # recreates the .sgml files according to the structure given in
33 # the file $MODULE-sections.txt.
35 # Any new templates added, or new function parameters, are
36 # marked with 'FIXME' so you can do a grep to see which parts
39 # Any templates which are no longer used (i.e. they are remove
40 # from $MODULE-sections.txt) are placed in the file
41 # tmpl/$MODULE-unused.txt. If they are included again later
42 # they are automatically copied back into position.
43 # If you are certain that these templates will never be used
44 # again you can delete them from $MODULE-unused.txt.
46 # Any parameters to functions which are no longer used are
47 # separated from the rest of the parameters with the line
48 # '<!-- # Unused Parameters # -->'. It may be that the parameter
49 # name has just been changed, in which case you can copy the
50 # description to the parameter with the new name. You can delete
51 # the unused parameter descriptions when no longer needed.
52 #############################################################################
57 unshift @INC, '@PACKAGE_DATA_DIR@';
58 require "gtkdoc-common.pl";
62 # name of documentation module
68 my $ONLY_SECTION_TMPL;
70 my %optctl = (module => \$MODULE,
71 'flag-changes' => \$FLAG_CHANGES,
72 'output-dir' => \$TMPL_DIR,
73 'only-section-tmpl' => \$ONLY_SECTION_TMPL,
74 'version' => \$PRINT_VERSION,
75 'help' => \$PRINT_HELP);
76 GetOptions(\%optctl, "module=s", "flag-changes!", "output-dir:s", "only-section-tmpl!", "version", "help");
88 print "gtkdoc-mktmpl version @VERSION@\n";
89 print "\n--module=MODULE_NAME Name of the doc module being parsed";
90 print "\n--flag-changes If specified, changes in templates are flagged";
91 print "\n--output-dir=DIRNAME The directory where the results are stored";
92 print "\n--only-section-tmpl Only include section information in templates";
93 print "\n--version Print the version of this program";
94 print "\n--help Print this help\n";
100 # The directory containing the template files.
101 $TMPL_DIR = $TMPL_DIR ? $TMPL_DIR : "$ROOT_DIR/tmpl";
103 # This file contains the object hierarchy.
104 my $OBJECT_TREE_FILE = "$ROOT_DIR/$MODULE.hierarchy";
106 # The file containing signal handler prototype information.
107 my $SIGNALS_FILE = "$ROOT_DIR/$MODULE.signals";
109 # The file containing Arg information.
110 my $ARGS_FILE = "$ROOT_DIR/$MODULE.args";
112 # Set the flag to indicate changes, if requested.
113 my $CHANGES_FLAG = $FLAG_CHANGES ? "FIXME" : "";
115 # These global arrays store information on signals. Each signal has an entry
116 # in each of these arrays at the same index, like a multi-dimensional array.
117 my @SignalObjects; # The GtkObject which emits the signal.
118 my @SignalNames; # The signal name.
119 my @SignalReturns; # The return type.
120 my @SignalFlags; # Flags for the signal
121 my @SignalPrototypes; # The rest of the prototype of the signal handler.
123 # These global arrays store information on Args. Each Arg has an entry
124 # in each of these arrays at the same index, like a multi-dimensional array.
125 my @ArgObjects; # The GtkObject which has the Arg.
126 my @ArgNames; # The Arg name.
127 my @ArgTypes; # The Arg type - gint, GtkArrowType etc.
128 my @ArgFlags; # How the Arg can be used - readable/writable etc.
130 # These global hashes store declaration info keyed on a symbol name.
132 my %DeclarationTypes;
133 my %DeclarationConditional;
134 my %DeclarationOutput;
136 # These global hashes store the existing documentation.
141 # These global arrays store GtkObject and subclasses and the hierarchy.
145 &ReadSignalsFile ($SIGNALS_FILE);
146 &ReadArgsFile ($ARGS_FILE);
147 &ReadObjectHierarchy;
149 &ReadDeclarationsFile ("$ROOT_DIR/$MODULE-decl.txt", 0);
150 if (-f "$ROOT_DIR/$MODULE-overrides.txt") {
151 &ReadDeclarationsFile ("$ROOT_DIR/$MODULE-overrides.txt", 1);
153 &ReadExistingTemplates;
157 if (&UpdateTemplates ("$ROOT_DIR/$MODULE-sections.txt")) {
160 &OutputUnusedTemplates;
161 if (&CheckAllDeclarationsOutput) {
165 if ($changed || ! -e "$ROOT_DIR/tmpl.stamp") {
166 open (TIMESTAMP, ">$ROOT_DIR/tmpl.stamp")
167 || die "Can't create $ROOT_DIR/tmpl.stamp";
168 print (TIMESTAMP "timestamp");
172 #############################################################################
173 # Function : ReadExistingTemplates
174 # Description : This reads in all the existing documentation, into the global
175 # variables %SymbolDocs, %SymbolTypes, and %SymbolParams (a
178 #############################################################################
180 sub ReadExistingTemplates {
185 # Read the unused docs first, so they get overridden by any real docs.
186 # (though this shouldn't happen often).
187 my $unused_doc = "$TMPL_DIR/$MODULE-unused.sgml";
188 if (-e $unused_doc) {
189 &ReadTemplateFile ($unused_doc, 0);
192 while (<$TMPL_DIR/*.sgml>) {
193 # print "Reading $_\n";
194 if ($_ eq $unused_doc) {
195 # print "skipping $unused_doc\n";
197 &ReadTemplateFile ($_, 0);
203 #############################################################################
204 # Function : UpdateTemplates
205 # Description : This collects the output for each section of the docs, and
206 # outputs each file when the end of the section is found.
207 # Arguments : $file - the file containing the sections of the docs.
208 #############################################################################
210 sub UpdateTemplates {
212 # print "Reading: $file\n";
215 || die "Can't open $file";
217 # Create the top output directory if it doesn't exist.
218 if (! -e $TMPL_DIR) {
219 mkdir ("$TMPL_DIR", 0777)
220 || die "Can't create directory: $TMPL_DIR";
231 } elsif (m/^<SECTION>/) {
234 } elsif (m/^<SUBSECTION\s*(.*)>/i) {
238 } elsif (m/^<TITLE>(.*)<\/TITLE>/) {
240 # print "Section: $title\n";
242 } elsif (m/^<FILE>(.*)<\/FILE>/) {
245 } elsif (m/^<INCLUDE>(.*)<\/INCLUDE>/) {
248 } elsif (m/^<\/SECTION>/) {
252 # print "End of section: $title\n";
257 if (&OutputTemplateFile ($file, $title, \$output)) {
264 } elsif (m/^(\S+)/) {
266 # print " Symbol: $symbol\n";
268 my $declaration = $Declarations{$1};
269 if (defined ($declaration)) {
270 # We don't want templates for standard macros/functions of
271 # GtkObjects or private declarations.
272 if ($subsection ne "Standard" && $subsection ne "Private") {
273 $output .= &OutputDeclaration ($DeclarationTypes {$symbol},
274 $symbol, $declaration);
276 $output .= &OutputSignalTemplates ($symbol);
277 $output .= &OutputArgTemplates ($symbol);
280 # Note that the declaration has been output.
281 $DeclarationOutput{$symbol} = 1;
283 if ($declaration eq '##conditional##') {
284 # print "Conditional $DeclarationTypes{$symbol}\n";
288 print "WARNING: No declaration found for: $1\n";
298 #############################################################################
299 # Function : CheckAllDeclarationsOutput
300 # Description : This steps through all the declarations that were loaded, and
301 # makes sure that each one has been output, by checking the
302 # corresponding flag in the %DeclarationOutput hash. It is
303 # intended to check that any new declarations in new versions
304 # of GTK/Gnome get added to the $MODULE-sections.txt file.
306 #############################################################################
308 sub CheckAllDeclarationsOutput {
311 my $old_unused_file = "$ROOT_DIR/$MODULE-unused.txt";
312 my $new_unused_file = "$ROOT_DIR/$MODULE-unused.new";
314 open (UNUSED, ">$new_unused_file")
315 || die "Can't open $new_unused_file";
317 foreach $symbol (sort keys (%Declarations)) {
318 if (!defined ($DeclarationOutput{$symbol})) {
319 print (UNUSED "$symbol\n");
324 if ($num_unused != 0) {
326 =============================================================================
327 WARNING: $num_unused unused declarations.
328 These can be found in $MODULE-unused.txt.
329 They should be added to $MODULE-sections.txt in the appropriate place.
330 =============================================================================
334 return &UpdateFileIfChanged ($old_unused_file, $new_unused_file, 0);
338 #############################################################################
339 # Function : OutputDeclaration
340 # Description : This returns the template for one symbol & declaration.
341 # Note that it uses the global %SymbolDocs and %SymbolParams to
342 # lookup any existing documentation.
343 # Arguments : $type - the type of the symbol ('FUNCTION'/'MACRO' etc.)
344 # $symbol - the symbol name.
345 # $declaration - the declaration of the symbol.
346 #############################################################################
348 sub OutputDeclaration {
349 my ($type, $symbol, $declaration) = @_;
352 # print "Outputting $type: $symbol\n";
354 # See if symbol already has a description.
355 my ($symbol_desc) = $SymbolDocs{$symbol};
356 my ($template_exists);
357 if (defined ($symbol_desc)) {
358 $template_exists = 1;
359 $symbol_desc =~ s/\s+$//;
361 $template_exists = 0;
362 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
366 <!-- ##### $type $symbol ##### -->
371 # For functions, function typedefs and macros, we output the arguments.
372 # For functions and function typedefs we also output the return value.
373 if ($type eq "FUNCTION" || $type eq "USER_FUNCTION") {
374 # Take out the return type
375 $declaration =~ s/<RETURNS>\s*((const\s+|G_CONST_RETURN\s+|unsigned\s+|struct\s+|enum\s+)*)(\w+)\s*(\**\s*(const|G_CONST_RETURN)?\s*\**\s*(restrict)?\s*)<\/RETURNS>\n//;
376 my $ret_type_modifier = defined($1) ? $1 : "";
378 my $ret_type_pointer = $4;
382 while ($declaration ne "") {
383 if ($declaration =~ s/^[\s,]+//) {
384 # skip whitespace and commas
387 } elsif ($declaration =~ s/^void\s*[,\n]//) {
388 if ($param_num != 0) {
389 print "WARNING: void used as parameter in function $symbol\n";
392 } elsif ($declaration =~ s/^...\s*[,\n]//) {
393 $output .= &OutputParam ($symbol, "Varargs",
394 $template_exists, 1, "");
396 # Try to match a standard parameter (keep in sync with gtkdoc-mkdb)
398 } elsif ($declaration =~ s/^\s*((?:G_CONST_RETURN|G_GNUC_UNUSED|unsigned long|unsigned short|signed long|signed short|unsigned|signed|long|short|volatile|const)\s+)*((?:struct\b|enum\b)?\s*\w+)\s*((?:(?:const\b|restrict\b)?\s*\*?\s*(?:const\b|restrict\b)?\s*)*)(\w+)?\s*((?:\[\S*\])*)\s*[,\n]//) {
399 my $pre = defined($1) ? $1 : "";
401 my $ptr = defined($3) ? $3 : "";
402 my $name = defined($4) ? $4 : "";
408 if ($ptr && $ptr !~ m/\*$/) { $ptr .= " "; }
410 if (($name eq "") && $pre =~ m/^((un)?signed .*)\s?/ ) {
416 #print "$symbol: '$pre' '$type' '$ptr' '$name' \n";
419 $name = "Param" . ($param_num + 1);
421 $output .= &OutputParam ($symbol, $name, $template_exists, 1,
424 # Try to match parameters which are functions (keep in sync with gtkdoc-mkdb)
425 # $1 $2 $3 $4 $5 $7 $8
426 } elsif ($declaration =~ s/^(const\s+|G_CONST_RETURN\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(?:restrict\b)?\s*(const\s+)?\(\s*\*+\s*(\w+)\s*\)\s*\(([^)]*)\)\s*[,\n]//) {
428 $output .= &OutputParam ($symbol, $name, $template_exists, 1,
432 print "###Can't parse args for function $symbol: $declaration\n";
439 if ($ret_type ne "void" || $ret_type_modifier || $ret_type_pointer) {
440 $output .= &OutputParam ($symbol, "Returns", $template_exists, 1,
443 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
444 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
445 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
446 $output .= &OutputOldParams ($symbol);
450 if ($type eq "MACRO") {
451 if ($declaration =~ m/^\s*#\s*define\s+\w+\(([^\)]*)\)/) {
455 $params =~ s/\\\n//g;
456 foreach $param (split (/,/, $params)) {
459 if ($param =~ m/\S/) {
460 $output .= &OutputParam ($symbol, $param, $template_exists,
465 $output .= &OutputParam ($symbol, "Returns", $template_exists, 0, "");
466 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
467 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
468 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
469 $output .= &OutputOldParams ($symbol);
473 if ($type eq "STRUCT") {
474 my $is_object_struct = CheckIsObject ($symbol);
475 my @fields = ParseStructDeclaration($declaration, $is_object_struct, 1);
477 for (my $i = 0; $i <= $#fields; $i += 2) {
478 my $field_name = $fields[$i];
479 $output .= &OutputParam ($symbol, $field_name, $template_exists, 1, "");
481 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
482 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
483 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
486 if ($type eq "ENUM") {
487 my @members = ParseEnumDeclaration($declaration);
489 for my $member (@members) {
490 $output .= &OutputParam ($symbol, $member, $template_exists, 1, "");
492 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
493 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
494 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
499 # Remove the used docs from the hashes.
500 if ($template_exists) {
501 delete $SymbolDocs{$symbol};
502 delete $SymbolParams{$symbol};
509 #############################################################################
510 # Function : OutputParam
511 # Description : This outputs the part of a template for one parameter.
512 # It first checks if the parameter is already described, and if
513 # so it uses that description, and clears it so it isn't output
515 # Arguments : $symbol - the symbol (function or macro) name.
516 # $param_to_output - the parameter to add.
517 # $template_exists - TRUE if the template already existed in
518 # template files. If it did, then we will flag any changes
520 # $force_output - TRUE if the parameter should be output even
521 # if it didn't already exist in the template. (The return
522 # values of macros are added manually if required, and so we
523 # never add it here - we only copy it if it already exists.)
524 # $default_description - the default description of the
525 # parameter to be used if it doesn't already exist. (Signal
526 # handlers have a few common parameters.)
527 #############################################################################
530 my ($symbol, $param_to_output, $template_exists,
531 $force_output, $default_description) = @_;
534 my ($params) = $SymbolParams{$symbol};
535 if (defined ($params)) {
536 for ($j = 0; $j <= $#$params; $j += 2) {
537 my $param_name = $$params[$j];
538 my $param_desc = $$params[$j + 1];
540 if ($param_name eq $param_to_output) {
541 $param_desc =~ s/\s+$//;
543 $$params[$j + 1] = "";
544 return "\@$param_name: $param_desc\n";
549 # If the template was already in a file, flag the new parameter.
550 # If not, the template itself will be flagged, so we don't need to flag
551 # all the new parameters as well.
553 if ($default_description ne "") {
554 $default_description =~ s/\s+$//;
555 return "\@$param_to_output: $default_description\n";
557 if ($template_exists) {
558 return "\@$param_to_output: $CHANGES_FLAG\n";
560 return "\@$param_to_output: \n";
568 #############################################################################
569 # Function : OutputOldParams
570 # Description : This returns all the existing documentation for parameters of
571 # the given function/macro/signal symbol which are unused, with
572 # a comment before them.
573 # Arguments : $symbol - the symbol (function/macro/signal) name.
574 #############################################################################
576 sub OutputOldParams {
580 my ($params) = $SymbolParams{$symbol};
581 if (defined ($params)) {
583 for ($j = 0; $j <= $#$params; $j += 2) {
584 my $param_name = $$params[$j];
585 my $param_desc = $$params[$j + 1];
587 if ($param_name ne "") {
588 $param_desc =~ s/\s+$//;
590 # There's no point keeping it if it has no docs.
591 if ($param_desc ne "") {
592 $output .= "\@$param_name: $param_desc\n";
598 $output = "<!-- # Unused Parameters # -->\n" . $output;
604 #############################################################################
605 # Function : OutputTemplateFile
606 # Description : This outputs one template file.
607 # Arguments : $file - the basename of the file to output.
608 # $title - the title from the $MODULE-sections.txt file. This
609 # will be overridden by any title given in the template file.
610 # $output - reference to the templates to output.
611 #############################################################################
613 sub OutputTemplateFile {
614 my ($file, $title, $output) = @_;
616 my ($short_desc, $long_desc, $see_also, $stability);
618 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Title"})) {
619 $title = $SymbolDocs{"$TMPL_DIR/$file:Title"};
620 delete $SymbolDocs{"$TMPL_DIR/$file:Title"};
622 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Short_Description"})) {
623 $short_desc = $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
624 delete $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
628 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Long_Description"})) {
629 $long_desc = $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
630 delete $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
632 $long_desc = "<para>\n\n</para>\n";
634 if (defined ($SymbolDocs{"$TMPL_DIR/$file:See_Also"})) {
635 $see_also = $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
636 delete $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
638 $see_also = "<para>\n\n</para>\n";
640 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Stability_Level"})) {
641 $stability = $SymbolDocs{"$TMPL_DIR/$file:Stability_Level"};
642 delete $SymbolDocs{"$TMPL_DIR/$file:Stability_Level"};
648 my $old_tmpl_file = "$TMPL_DIR/$file";
649 my $new_tmpl_file = "$TMPL_DIR/$file.new";
651 open (OUTPUT, ">$new_tmpl_file")
652 || die "Can't create $new_tmpl_file";
654 print (OUTPUT <<EOF);
655 <!-- ##### SECTION Title ##### -->
658 <!-- ##### SECTION Short_Description ##### -->
661 <!-- ##### SECTION Long_Description ##### -->
664 <!-- ##### SECTION See_Also ##### -->
667 <!-- ##### SECTION Stability_Level ##### -->
672 print (OUTPUT $$output) unless $ONLY_SECTION_TMPL;
675 return &UpdateFileIfChanged ($old_tmpl_file, $new_tmpl_file, 1);
679 #############################################################################
680 # Function : OutputSignalTemplates
681 # Description : Outputs templates for signal handlers.
682 # Arguments : $title - the title from the $MODULE-sections.txt file. If the
683 # file is describing a GtkObject subclass, the title should
684 # be the name of the class, e.g. 'GtkButton'.
685 #############################################################################
687 sub OutputSignalTemplates {
691 my ($i, $template_exists);
692 for ($i = 0; $i <= $#SignalObjects; $i++) {
693 if ($SignalObjects[$i] eq $title) {
694 # print "Found signal: $SignalObjects[$i]\n";
695 my ($symbol) = "$SignalObjects[$i]::$SignalNames[$i]";
697 # See if symbol already has a description.
698 my ($symbol_desc) = $SymbolDocs{$symbol};
699 if (defined ($symbol_desc)) {
700 $template_exists = 1;
701 $symbol_desc =~ s/\s+$//;
702 delete $SymbolDocs{$symbol};
704 $template_exists = 0;
705 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
709 <!-- ##### SIGNAL $symbol ##### -->
713 my $sourceparams = $SymbolParams{$symbol};
714 my @params = split ("[,\n]", $SignalPrototypes[$i]);
716 for ($j = 0; $j <= $#params; $j++) {
717 my $param = $params[$j];
720 if ($param =~ m/^\s*$/) { next; }
721 if ($param =~ m/^void$/) { next; }
723 if ($param =~ m/^\s*(\w+)\s*(\**)\s*([\w\[\]]+)?\s*$/) {
724 if (defined ($sourceparams)) {
725 $name = $$sourceparams[2 * $j];
730 if (!defined ($name)) {
731 $name = "Param" . ($j + 1);
735 $output .= &OutputParam ($symbol, $name,
737 "the object which received the signal.");
739 $output .= &OutputParam ($symbol, $name,
740 $template_exists, 1, "");
745 if ($SignalReturns[$i] ne "void") {
746 $output .= &OutputParam ($symbol, "Returns", $template_exists,
749 $output .= &OutputOldParams ($symbol);
757 #############################################################################
758 # Function : OutputArgTemplates
759 # Description : Outputs templates for Args.
760 # Arguments : $title - the title from the $MODULE-sections.txt file. If the
761 # file is describing a GtkObject subclass, the title should
762 # be the name of the class, e.g. 'GtkButton'.
763 #############################################################################
765 sub OutputArgTemplates {
770 for ($i = 0; $i <= $#ArgObjects; $i++) {
771 if ($ArgObjects[$i] eq $title) {
772 # print "Found arg: $ArgObjects[$i]\n";
773 # I've only used one colon so we don't clash with signals.
774 my ($symbol) = "$ArgObjects[$i]:$ArgNames[$i]";
776 # See if symbol already has a description.
777 my ($symbol_desc) = $SymbolDocs{$symbol};
778 if (defined ($symbol_desc)) {
779 delete $SymbolDocs{$symbol};
780 $symbol_desc =~ s/\s+$//;
782 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
786 <!-- ##### ARG $symbol ##### -->
796 #############################################################################
797 # Function : OutputUnusedTemplates
798 # Description : This saves any unused documentation into $MODULE-unused.sgml.
800 #############################################################################
802 sub OutputUnusedTemplates {
803 my ($old_unused_file) = "$TMPL_DIR/$MODULE-unused.sgml";
804 my ($new_unused_file) = "$TMPL_DIR/$MODULE-unused.new";
806 open (UNUSED, ">$new_unused_file")
807 || die "Can't open file: $new_unused_file";
810 my ($symbol, $symbol_desc);
811 for $symbol (sort keys %SymbolDocs) {
812 $symbol_desc = $SymbolDocs{$symbol};
814 # print "Unused: $symbol\n";
816 my $type = $SymbolTypes{$symbol};
817 if (!defined ($type)) {
819 print "WARNING: Unused symbol $symbol has unknown type\n";
823 <!-- ##### $type $symbol ##### -->
828 my ($params) = $SymbolParams{$symbol};
829 if (defined ($params)) {
831 for ($j = 0; $j <= $#$params; $j += 2) {
832 my $param_name = $$params[$j];
833 my $param_desc = $$params[$j + 1];
834 $param_desc =~ s/\s+$//;
835 $output .= "\@$param_name: $param_desc\n";
841 print UNUSED $output;
844 &UpdateFileIfChanged ($old_unused_file, $new_unused_file, 1);
848 #############################################################################
849 # LIBRARY FUNCTIONS - These functions are used in both gtkdoc-mkdb and
850 # gtkdoc-mktmpl and should eventually be moved to a
852 #############################################################################
854 #############################################################################
855 # Function : ReadDeclarationsFile
856 # Description : This reads in a file containing the function/macro/enum etc.
859 # Note that in some cases there are several declarations with
860 # the same name, e.g. for conditional macros. In this case we
861 # set a flag in the %DeclarationConditional hash so the
862 # declaration is not shown in the docs.
864 # If a macro and a function have the same name, e.g. for
865 # gtk_object_ref, the function declaration takes precedence.
867 # Some opaque structs are just declared with 'typedef struct
868 # _name name;' in which case the declaration may be empty.
869 # The structure may have been found later in the header, so
870 # that overrides the empty declaration.
872 # Arguments : $file - the declarations file to read
873 # $override - if declarations in this file should override
874 # any current declaration.
875 #############################################################################
877 sub ReadDeclarationsFile {
878 my ($file, $override) = @_;
880 if ($override == 0) {
882 %DeclarationTypes = ();
883 %DeclarationConditional = ();
884 %DeclarationOutput = ();
888 || die "Can't open $file";
889 my $declaration_type = "";
890 my $declaration_name;
893 if (!$declaration_type) {
895 $declaration_type = $1;
896 $declaration_name = "";
897 # print "Found declaration: $declaration_type\n";
901 if (m%^<NAME>(.*)</NAME>%) {
902 $declaration_name = $1;
903 } elsif (m%<DEPRECATED/>%) {
904 # do nothing, just skip the line; we handle this
906 } elsif (m%^</$declaration_type>%) {
907 # print "Found end of declaration: $declaration_name\n";
908 # Check that the declaration has a name
909 if ($declaration_name eq "") {
910 print "ERROR: $declaration_type has no name $file:$.\n";
913 # Check if the symbol is already defined.
914 if (defined ($Declarations{$declaration_name})
916 # Function declarations take precedence.
917 if ($DeclarationTypes{$declaration_name} eq 'FUNCTION') {
919 } elsif ($declaration_type eq 'FUNCTION') {
920 $Declarations{$declaration_name} = $declaration;
921 $DeclarationTypes{$declaration_name} = $declaration_type;
922 } elsif ($DeclarationTypes{$declaration_name}
923 eq $declaration_type) {
924 # If the existing declaration is empty, or is just a
925 # forward declaration of a struct, override it.
926 if ($declaration_type eq 'STRUCT') {
927 if ($Declarations{$declaration_name} =~ m/^\s*(struct\s+\w+\s*;)?\s*$/) {
928 $Declarations{$declaration_name} = $declaration;
929 } elsif ($declaration =~ m/^\s*(struct\s+\w+\s*;)?\s*$/) {
930 # Ignore an empty or forward declaration.
932 print "WARNING: Structure has multiple definitions: $declaration_name\n";
936 # set flag in %DeclarationConditional hash for
937 # multiply defined macros/typedefs.
938 $DeclarationConditional{$declaration_name} = 1;
941 print "WARNING: $declaration_name has multiple definitions\n";
944 $Declarations{$declaration_name} = $declaration;
945 $DeclarationTypes{$declaration_name} = $declaration_type;
947 $declaration_type = "";
957 #############################################################################
958 # Function : ReadSignalsFile
959 # Description : This reads in an existing file which contains information on
960 # all GTK signals. It creates the arrays @SignalNames and
961 # @SignalPrototypes containing info on the signals. The first
962 # line of the SignalPrototype is the return type of the signal
963 # handler. The remaining lines are the parameters passed to it.
964 # The last parameter, "gpointer user_data" is always the same
965 # so is not included.
966 # Arguments : $file - the file containing the signal handler prototype
968 #############################################################################
970 sub ReadSignalsFile {
978 my $signal_prototype;
980 # Reset the signal info.
985 @SignalPrototypes = ();
990 if (!open (INPUT, $file)) {
991 warn "Can't open $file - skipping signals\n";
1000 $signal_returns = "";
1001 $signal_prototype = "";
1004 if (m/^<NAME>(.*)<\/NAME>/) {
1006 if ($signal_name =~ m/^(.*)::(.*)$/) {
1007 $signal_object = $1;
1008 ($signal_name = $2) =~ s/_/-/g;
1009 # print "Found signal: $signal_name\n";
1011 print "Invalid signal name: $signal_name\n";
1013 } elsif (m/^<RETURNS>(.*)<\/RETURNS>/) {
1014 $signal_returns = $1;
1015 } elsif (m/^<FLAGS>(.*)<\/FLAGS>/) {
1017 } elsif (m%^</SIGNAL>%) {
1018 # print "Found end of signal: ${signal_object}::${signal_name}\nReturns: ${signal_returns}\n${signal_prototype}";
1019 push (@SignalObjects, $signal_object);
1020 push (@SignalNames, $signal_name);
1021 push (@SignalReturns, $signal_returns);
1022 push (@SignalFlags, $signal_flags);
1023 push (@SignalPrototypes, $signal_prototype);
1026 $signal_prototype .= $_;
1034 #############################################################################
1035 # Function : ReadTemplateFile
1036 # Description : This reads in the manually-edited documentation file
1037 # corresponding to the file currently being created, so we can
1038 # insert the documentation at the appropriate places.
1039 # It outputs %SymbolTypes, %SymbolDocs and %SymbolParams, which
1040 # is a hash of arrays.
1041 # NOTE: This function is duplicated in gtkdoc-mkdb (but
1042 # slightly different).
1043 # Arguments : $docsfile - the template file to read in.
1044 # $skip_unused_params - 1 if the unused parameters should be
1046 #############################################################################
1048 sub ReadTemplateFile {
1049 my ($docsfile, $skip_unused_params) = @_;
1051 # print "Reading $docsfile\n";
1052 if (! -f $docsfile) {
1053 print "File doesn't exist: $docsfile\n";
1057 my $CurrentType = ""; # Type of symbol being read.
1058 my $CurrentSymbol = ""; # Name of symbol being read.
1059 my $SymbolDoc = ""; # Description of symbol being read.
1060 my @Params; # Parameter names and descriptions of current
1061 # function/macro/function typedef.
1062 my $CurrentParam = -1; # Index of parameter currently being read.
1063 # Note that the param array contains pairs
1064 # of param name & description.
1065 my $InUnusedParameters = 0; # True if we are reading in the unused params.
1067 open (DOCS, $docsfile)
1068 || die "Can't open file $docsfile: $!";
1070 if (m/^<!-- ##### ([A-Z_]+) (\S+) ##### -->/) {
1073 if ($symbol eq "Title"
1074 || $symbol eq "Short_Description"
1075 || $symbol eq "Long_Description"
1076 || $symbol eq "See_Also"
1077 || $symbol eq "Stability_Level") {
1078 $symbol = $docsfile . ":" . $symbol;
1079 # print "Found symbol: $symbol\n";
1082 # Canonicalize signal and argument names to have -, not _
1083 if ($type eq "ARG" || $type eq "SIGNAL") {
1087 # Store previous symbol, but remove any trailing blank lines.
1088 if ($CurrentSymbol ne "") {
1089 $SymbolDoc =~ s/\s+$//;
1090 $SymbolTypes{$CurrentSymbol} = $CurrentType;
1091 $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
1092 if ($CurrentParam >= 0) {
1093 $SymbolParams{$CurrentSymbol} = [ @Params ];
1095 # Delete any existing params in case we are overriding a
1096 # previously read template.
1097 delete $SymbolParams{$CurrentSymbol};
1100 $CurrentType = $type;
1101 $CurrentSymbol = $symbol;
1103 $InUnusedParameters = 0;
1107 } elsif (m/^<!-- # Unused Parameters # -->/) {
1108 $InUnusedParameters = 1;
1112 # Workaround for an old bug that left a mess in the templates.
1113 # This happened with macros with args spread over several lines.
1115 # Skip the next line.
1120 # Workaround for an old bug that left '@:' at start of lines.
1126 # Check if param found. Need to handle "..." and "format...".
1127 if (s/^\@([\w\.]+):\040?//) {
1128 my $param_name = $1;
1129 # Allow variations of 'Returns'
1130 if ($param_name =~ m/^[Rr]eturns?$/) {
1131 $param_name = "Returns";
1133 # print "Found param: $param_name\n";
1134 push (@Params, $param_name);
1140 # When outputting the DocBook we skip unused parameters.
1141 if (!$InUnusedParameters || !$skip_unused_params) {
1142 if ($CurrentParam >= 0) {
1143 $Params[$CurrentParam] .= $_;
1151 # Remember to finish the current symbol doccs.
1152 if ($CurrentSymbol ne "") {
1153 $SymbolDoc =~ s/\s+$//;
1154 $SymbolTypes{$CurrentSymbol} = $CurrentType;
1155 $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
1156 if ($CurrentParam >= 0) {
1157 $SymbolParams{$CurrentSymbol} = [ @Params ];
1159 delete $SymbolParams{$CurrentSymbol};
1167 #############################################################################
1168 # Function : ReadObjectHierarchy
1169 # Description : This reads in the $MODULE-hierarchy.txt file containing all
1170 # the GtkObject subclasses described in this module (and their
1172 # It places them in the @Objects array, and places their level
1173 # in the widget hierarchy in the @ObjectLevels array, at the
1174 # same index. GtkObject, the root object, has a level of 1.
1176 # FIXME: the version in gtkdoc-mkdb also generates tree_index.sgml
1177 # as it goes along, this should be split out into a separate
1181 #############################################################################
1183 sub ReadObjectHierarchy {
1187 if (! -f $OBJECT_TREE_FILE) {
1190 if (!open (INPUT, $OBJECT_TREE_FILE)) {
1191 warn "Can't open $OBJECT_TREE_FILE - skipping object tree\n";
1197 my $level = (length($`)) / 2 + 1;
1198 # print ("Level: $level Object: $object\n");
1200 push (@Objects, $object);
1201 push (@ObjectLevels, $level);
1209 #############################################################################
1210 # Function : ReadArgsFile
1211 # Description : This reads in an existing file which contains information on
1212 # all GTK args. It creates the arrays @ArgObjects, @ArgNames,
1213 # @ArgTypes and @ArgFlags containing info on the args.
1214 # Arguments : $file - the file containing the arg information.
1215 #############################################################################
1226 # Reset the signal info.
1235 if (!open (INPUT, $file)) {
1236 warn "Can't open $file - skipping args\n";
1249 if (m/^<NAME>(.*)<\/NAME>/) {
1251 if ($arg_name =~ m/^(.*)::(.*)$/) {
1253 ($arg_name = $2) =~ s/_/-/g;
1254 # print "Found arg: $arg_name\n";
1256 print "Invalid arg name: $arg_name\n";
1258 } elsif (m/^<TYPE>(.*)<\/TYPE>/) {
1260 } elsif (m/^<FLAGS>(.*)<\/FLAGS>/) {
1262 } elsif (m%^</ARG>%) {
1263 # print "Found end of arg: ${arg_object}::${arg_name}\n${arg_type} : ${arg_flags}\n";
1264 push (@ArgObjects, $arg_object);
1265 push (@ArgNames, $arg_name);
1266 push (@ArgTypes, $arg_type);
1267 push (@ArgFlags, $arg_flags);
1276 #############################################################################
1277 # Function : CheckIsObject
1278 # Description : Returns 1 if the given name is a GtkObject or a subclass.
1279 # It uses the global @Objects array.
1280 # Note that the @Objects array only contains classes in the
1281 # current module and their ancestors - not all GTK classes.
1282 # Arguments : $name - the name to check.
1283 #############################################################################
1289 foreach $object (@Objects) {
1290 if ($object eq $name) {