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-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.sgml. 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 tmpl/$MODULE-unused.sgml.
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 push @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");
89 gtkdoc-mktmpl version @VERSION@ - generate documentation templates
91 --module=MODULE_NAME Name of the doc module being parsed
92 --flag-changes If specified, changes in templates are flagged
93 --output-dir=DIRNAME The directory where the results are stored
94 --only-section-tmpl Only include section information in templates
95 --version Print the version of this program
96 --help Print this help
102 ###############################################################################
103 gtkdoc-mktmpl is deprecated and will be removed from one of the next gtk-doc
105 Please refer to the documentation "Modernizing the documentation"/"GTK-Doc 1.9".
106 ###############################################################################
111 # The directory containing the template files.
112 $TMPL_DIR = $TMPL_DIR ? $TMPL_DIR : "$ROOT_DIR/tmpl";
114 # This file contains the object hierarchy.
115 my $OBJECT_TREE_FILE = "$ROOT_DIR/$MODULE.hierarchy";
117 # The file containing signal handler prototype information.
118 my $SIGNALS_FILE = "$ROOT_DIR/$MODULE.signals";
120 # The file containing Arg information.
121 my $ARGS_FILE = "$ROOT_DIR/$MODULE.args";
123 # Set the flag to indicate changes, if requested.
124 my $CHANGES_FLAG = $FLAG_CHANGES ? "FIXME" : "";
126 # These global arrays store information on signals. Each signal has an entry
127 # in each of these arrays at the same index, like a multi-dimensional array.
128 my @SignalObjects; # The GtkObject which emits the signal.
129 my @SignalNames; # The signal name.
130 my @SignalReturns; # The return type.
131 my @SignalFlags; # Flags for the signal
132 my @SignalPrototypes; # The rest of the prototype of the signal handler.
134 # These global arrays store information on Args. Each Arg has an entry
135 # in each of these arrays at the same index, like a multi-dimensional array.
136 my @ArgObjects; # The GtkObject which has the Arg.
137 my @ArgNames; # The Arg name.
138 my @ArgTypes; # The Arg type - gint, GtkArrowType etc.
139 my @ArgFlags; # How the Arg can be used - readable/writable etc.
141 # These global hashes store declaration info keyed on a symbol name.
143 my %DeclarationTypes;
144 my %DeclarationConditional;
145 my %DeclarationOutput;
147 # These global hashes store the existing documentation.
151 my %SymbolSourceFile;
152 my %SymbolSourceLine;
154 # These global arrays store GObject and subclasses and the hierarchy.
158 &ReadSignalsFile ($SIGNALS_FILE);
159 &ReadArgsFile ($ARGS_FILE);
160 &ReadObjectHierarchy;
162 &ReadDeclarationsFile ("$ROOT_DIR/$MODULE-decl.txt", 0);
163 if (-f "$ROOT_DIR/$MODULE-overrides.txt") {
164 &ReadDeclarationsFile ("$ROOT_DIR/$MODULE-overrides.txt", 1);
166 &ReadExistingTemplates;
170 if (&UpdateTemplates ("$ROOT_DIR/$MODULE-sections.txt")) {
173 &OutputUnusedTemplates;
174 if (&CheckAllDeclarationsOutput) {
178 if ($changed || ! -e "$ROOT_DIR/tmpl.stamp") {
179 open (TIMESTAMP, ">$ROOT_DIR/tmpl.stamp")
180 || die "Can't create $ROOT_DIR/tmpl.stamp";
181 print (TIMESTAMP "timestamp");
185 #############################################################################
186 # Function : ReadExistingTemplates
187 # Description : This reads in all the existing documentation, into the global
188 # variables %SymbolDocs, %SymbolTypes, and %SymbolParams (a
191 #############################################################################
193 sub ReadExistingTemplates {
198 # Read the unused docs first, so they get overridden by any real docs.
199 # (though this shouldn't happen often).
200 my $unused_doc = "$TMPL_DIR/$MODULE-unused.sgml";
201 if (-e $unused_doc) {
202 &ReadTemplateFile ($unused_doc, 0);
205 while (<$TMPL_DIR/*.sgml>) {
206 # print "Reading $_\n";
207 if ($_ eq $unused_doc) {
208 # print "skipping $unused_doc\n";
210 &ReadTemplateFile ($_, 0);
216 #############################################################################
217 # Function : UpdateTemplates
218 # Description : This collects the output for each section of the docs, and
219 # outputs each file when the end of the section is found.
220 # Arguments : $file - the file containing the sections of the docs.
221 #############################################################################
223 sub UpdateTemplates {
225 # print "Reading: $file\n";
228 || die "Can't open $file";
230 # Create the top output directory if it doesn't exist.
231 if (! -e $TMPL_DIR) {
232 mkdir ("$TMPL_DIR", 0777)
233 || die "Can't create directory: $TMPL_DIR";
245 } elsif (m/^<SECTION>/) {
248 } elsif (m/^<SUBSECTION\s*(.*)>/i) {
252 } elsif (m/^<TITLE>(.*)<\/TITLE>/) {
254 # print "Section: $title\n";
256 } elsif (m/^<FILE>(.*)<\/FILE>/) {
259 } elsif (m/^<INCLUDE>(.*)<\/INCLUDE>/) {
262 } elsif (m/^<\/SECTION>/) {
266 # print "End of section: $title\n";
268 $filename =~ s/\s/_/g;
269 $filename .= ".sgml";
271 if (&OutputTemplateFile ($filename, $title, \$output)) {
278 } elsif (m/^(\S+)/) {
280 # print " Symbol: $symbol\n";
282 my $declaration = $Declarations{$1};
283 if (defined ($declaration)) {
284 # We don't want templates for standard macros/functions of
285 # GObjects or private declarations.
286 if ($subsection ne "Standard" && $subsection ne "Private") {
287 $output .= &OutputDeclaration ($DeclarationTypes {$symbol},
288 $symbol, $declaration);
290 $output .= &OutputSignalTemplates ($symbol);
291 $output .= &OutputArgTemplates ($symbol);
294 # Note that the declaration has been output.
295 $DeclarationOutput{$symbol} = 1;
297 if ($declaration eq '##conditional##') {
298 # print "Conditional $DeclarationTypes{$symbol}\n";
302 &LogWarning ($file, $., "No declaration found for: $1");
312 #############################################################################
313 # Function : CheckAllDeclarationsOutput
314 # Description : This steps through all the declarations that were loaded, and
315 # makes sure that each one has been output, by checking the
316 # corresponding flag in the %DeclarationOutput hash. It is
317 # intended to check that any new declarations in new versions
318 # of the module get added to the $MODULE-sections.txt file.
320 #############################################################################
322 sub CheckAllDeclarationsOutput {
325 my $old_unused_file = "$ROOT_DIR/$MODULE-unused.txt";
326 my $new_unused_file = "$ROOT_DIR/$MODULE-unused.new";
328 open (UNUSED, ">$new_unused_file")
329 || die "Can't open $new_unused_file";
331 foreach $symbol (sort keys (%Declarations)) {
332 if (!defined ($DeclarationOutput{$symbol})) {
333 print (UNUSED "$symbol\n");
338 if ($num_unused != 0) {
339 &LogWarning ($old_unused_file, 1, "$num_unused unused declarations.".
340 "They should be added to $MODULE-sections.txt in the appropriate place.");
343 return &UpdateFileIfChanged ($old_unused_file, $new_unused_file, 0);
347 #############################################################################
348 # Function : OutputDeclaration
349 # Description : This returns the template for one symbol & declaration.
350 # Note that it uses the global %SymbolDocs and %SymbolParams to
351 # lookup any existing documentation.
352 # Arguments : $type - the type of the symbol ('FUNCTION'/'MACRO' etc.)
353 # $symbol - the symbol name.
354 # $declaration - the declaration of the symbol.
355 #############################################################################
357 sub OutputDeclaration {
358 my ($type, $symbol, $declaration) = @_;
361 #print "Outputting $type: $symbol\n";
363 # See if symbol already has a description.
364 my ($symbol_desc) = $SymbolDocs{$symbol};
365 my ($template_exists);
366 if (defined ($symbol_desc)) {
367 $template_exists = 1;
368 $symbol_desc =~ s/\s+$//;
370 $template_exists = 0;
371 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
375 <!-- ##### $type $symbol ##### -->
380 # For functions, function typedefs and macros, we output the arguments.
381 # For functions and function typedefs we also output the return value.
382 if ($type eq "FUNCTION" || $type eq "USER_FUNCTION") {
383 # Take out the return type
384 $declaration =~ s/<RETURNS>\s*(.*?)<\/RETURNS>\n//;
385 my $ret_type_decl = $1;
386 my $ret_type_modifier;
388 my $ret_type_pointer;
390 if ($ret_type_decl =~ m/((const\s+|G_CONST_RETURN\s+|unsigned\s+|signed\s+|long\s+|short\s+|struct\s+|enum\s+)*)(\w+)\s*(\**\s*(const|G_CONST_RETURN)?\s*\**\s*(restrict)?\s*)/) {
391 $ret_type_modifier = defined($1) ? $1 : "";
393 $ret_type_pointer = $4;
398 my @fields = ParseFunctionDeclaration($declaration);
400 for (my $i = 0; $i <= $#fields; $i += 2) {
401 my $field_name = $fields[$i];
402 $output .= &OutputParam ($symbol, $field_name, $template_exists, 1, "");
405 if ($ret_type ne "void" || $ret_type_modifier || $ret_type_pointer) {
406 $output .= &OutputParam ($symbol, "Returns", $template_exists, 1, "");
409 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
410 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
411 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
412 $output .= &OutputOldParams ($symbol);
416 if ($type eq "MACRO") {
417 my @fields = ParseMacroDeclaration($declaration);
419 for (my $i = 0; $i <= $#fields; $i +=2) {
420 my $field_name = $fields[$i];
422 $output .= &OutputParam ($symbol, $field_name, $template_exists,
425 $output .= &OutputParam ($symbol, "Returns", $template_exists, 0, "");
426 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
427 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
428 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
429 $output .= &OutputOldParams ($symbol);
433 if ($type eq "STRUCT") {
434 my $is_object_struct = CheckIsObject ($symbol);
435 my @fields = ParseStructDeclaration($declaration, $is_object_struct, 1);
437 for (my $i = 0; $i <= $#fields; $i += 2) {
438 my $field_name = $fields[$i];
439 $output .= &OutputParam ($symbol, $field_name, $template_exists, 1, "");
441 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
442 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
443 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
446 if ($type eq "ENUM") {
447 my @members = ParseEnumDeclaration($declaration);
449 for my $member (@members) {
450 $output .= &OutputParam ($symbol, $member, $template_exists, 1, "");
452 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
453 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
454 $output .= &OutputParam ($symbol, "Stability", $template_exists, 0, "");
459 # Remove the used docs from the hashes.
460 if ($template_exists) {
461 delete $SymbolDocs{$symbol};
462 delete $SymbolParams{$symbol};
469 #############################################################################
470 # Function : OutputParam
471 # Description : This outputs the part of a template for one parameter.
472 # It first checks if the parameter is already described, and if
473 # so it uses that description, and clears it so it isn't output
475 # Arguments : $symbol - the symbol (function or macro) name.
476 # $param_to_output - the parameter to add.
477 # $template_exists - TRUE if the template already existed in
478 # template files. If it did, then we will flag any changes
480 # $force_output - TRUE if the parameter should be output even
481 # if it didn't already exist in the template. (The return
482 # values of macros are added manually if required, and so we
483 # never add it here - we only copy it if it already exists.)
484 # $default_description - the default description of the
485 # parameter to be used if it doesn't already exist. (Signal
486 # handlers have a few common parameters.)
487 #############################################################################
490 my ($symbol, $param_to_output, $template_exists,
491 $force_output, $default_description) = @_;
494 my ($params) = $SymbolParams{$symbol};
495 if (defined ($params)) {
496 for ($j = 0; $j <= $#$params; $j += 2) {
497 my $param_name = $$params[$j];
498 my $param_desc = $$params[$j + 1];
500 if ($param_name eq $param_to_output) {
501 $param_desc =~ s/\s+$//;
503 $$params[$j + 1] = "";
504 return "\@$param_name: $param_desc\n";
509 # If the template was already in a file, flag the new parameter.
510 # If not, the template itself will be flagged, so we don't need to flag
511 # all the new parameters as well.
513 if ($default_description ne "") {
514 $default_description =~ s/\s+$//;
515 return "\@$param_to_output: $default_description\n";
517 if ($template_exists) {
518 return "\@$param_to_output: $CHANGES_FLAG\n";
520 return "\@$param_to_output: \n";
528 #############################################################################
529 # Function : OutputOldParams
530 # Description : This returns all the existing documentation for parameters of
531 # the given function/macro/signal symbol which are unused, with
532 # a comment before them.
533 # Arguments : $symbol - the symbol (function/macro/signal) name.
534 #############################################################################
536 sub OutputOldParams {
540 my ($params) = $SymbolParams{$symbol};
541 if (defined ($params)) {
543 for ($j = 0; $j <= $#$params; $j += 2) {
544 my $param_name = $$params[$j];
545 my $param_desc = $$params[$j + 1];
547 if ($param_name ne "") {
548 $param_desc =~ s/\s+$//;
550 # There's no point keeping it if it has no docs.
551 if ($param_desc ne "") {
552 $output .= "\@$param_name: $param_desc\n";
558 $output = "<!-- # Unused Parameters # -->\n" . $output;
564 #############################################################################
565 # Function : OutputTemplateFile
566 # Description : This outputs one template file.
567 # Arguments : $file - the basename of the file to output.
568 # $title - the title from the $MODULE-sections.txt file. This
569 # will be overridden by any title given in the template file.
570 # $output - reference to the templates to output.
571 #############################################################################
573 sub OutputTemplateFile {
574 my ($file, $title, $output) = @_;
576 my ($short_desc, $long_desc, $see_also, $stability, $image);
578 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Title"})) {
579 $title = $SymbolDocs{"$TMPL_DIR/$file:Title"};
580 delete $SymbolDocs{"$TMPL_DIR/$file:Title"};
582 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Short_Description"})) {
583 $short_desc = $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
584 delete $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
588 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Long_Description"})) {
589 $long_desc = $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
590 delete $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
592 $long_desc = "<para>\n\n</para>\n";
594 if (defined ($SymbolDocs{"$TMPL_DIR/$file:See_Also"})) {
595 $see_also = $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
596 delete $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
598 $see_also = "<para>\n\n</para>\n";
600 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Stability_Level"})) {
601 $stability = $SymbolDocs{"$TMPL_DIR/$file:Stability_Level"};
602 delete $SymbolDocs{"$TMPL_DIR/$file:Stability_Level"};
606 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Image"})) {
607 $image = $SymbolDocs{"$TMPL_DIR/$file:Image"};
608 delete $SymbolDocs{"$TMPL_DIR/$file:Image"};
614 my $old_tmpl_file = "$TMPL_DIR/$file";
615 my $new_tmpl_file = "$TMPL_DIR/$file.new";
617 open (OUTPUT, ">$new_tmpl_file")
618 || die "Can't create $new_tmpl_file";
620 print (OUTPUT <<EOF);
621 <!-- ##### SECTION Title ##### -->
624 <!-- ##### SECTION Short_Description ##### -->
627 <!-- ##### SECTION Long_Description ##### -->
630 <!-- ##### SECTION See_Also ##### -->
633 <!-- ##### SECTION Stability_Level ##### -->
636 <!-- ##### SECTION Image ##### -->
641 print (OUTPUT $$output) unless $ONLY_SECTION_TMPL;
644 return &UpdateFileIfChanged ($old_tmpl_file, $new_tmpl_file, 1);
648 #############################################################################
649 # Function : OutputSignalTemplates
650 # Description : Outputs templates for signal handlers.
651 # Arguments : $title - the title from the $MODULE-sections.txt file. If the
652 # file is describing a GtkObject subclass, the title should
653 # be the name of the class, e.g. 'GtkButton'.
654 #############################################################################
656 sub OutputSignalTemplates {
660 my ($i, $template_exists);
661 for ($i = 0; $i <= $#SignalObjects; $i++) {
662 if ($SignalObjects[$i] eq $title) {
663 # print "Found signal: $SignalObjects[$i]\n";
664 my ($symbol) = "$SignalObjects[$i]::$SignalNames[$i]";
666 # See if symbol already has a description.
667 my ($symbol_desc) = $SymbolDocs{$symbol};
668 if (defined ($symbol_desc)) {
669 $template_exists = 1;
670 $symbol_desc =~ s/\s+$//;
671 delete $SymbolDocs{$symbol};
673 $template_exists = 0;
674 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
678 <!-- ##### SIGNAL $symbol ##### -->
682 my $sourceparams = $SymbolParams{$symbol};
683 my @params = split ("[,\n]", $SignalPrototypes[$i]);
685 for ($j = 0; $j <= $#params; $j++) {
686 my $param = $params[$j];
689 if ($param =~ m/^\s*$/) { next; }
690 if ($param =~ m/^void$/) { next; }
692 if ($param =~ m/^\s*(\w+)\s*(\**)\s*([\w\[\]]+)?\s*$/) {
693 if (defined ($sourceparams)) {
694 $name = $$sourceparams[2 * $j];
699 if (!defined ($name)) {
700 $name = "Param" . ($j + 1);
704 $output .= &OutputParam ($symbol, $name,
706 "the object which received the signal.");
708 $output .= &OutputParam ($symbol, $name,
709 $template_exists, 1, "");
714 if ($SignalReturns[$i] ne "void") {
715 $output .= &OutputParam ($symbol, "Returns", $template_exists,
718 $output .= &OutputOldParams ($symbol);
726 #############################################################################
727 # Function : OutputArgTemplates
728 # Description : Outputs templates for Args.
729 # Arguments : $title - the title from the $MODULE-sections.txt file. If the
730 # file is describing a GtkObject subclass, the title should
731 # be the name of the class, e.g. 'GtkButton'.
732 #############################################################################
734 sub OutputArgTemplates {
739 for ($i = 0; $i <= $#ArgObjects; $i++) {
740 if ($ArgObjects[$i] eq $title) {
741 # print "Found arg: $ArgObjects[$i]\n";
742 # I've only used one colon so we don't clash with signals.
743 my ($symbol) = "$ArgObjects[$i]:$ArgNames[$i]";
745 # See if symbol already has a description.
746 my ($symbol_desc) = $SymbolDocs{$symbol};
747 if (defined ($symbol_desc)) {
748 delete $SymbolDocs{$symbol};
749 $symbol_desc =~ s/\s+$//;
751 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
755 <!-- ##### ARG $symbol ##### -->
765 #############################################################################
766 # Function : OutputUnusedTemplates
767 # Description : This saves any unused documentation into $MODULE-unused.sgml.
769 #############################################################################
771 sub OutputUnusedTemplates {
772 my ($old_unused_file) = "$TMPL_DIR/$MODULE-unused.sgml";
773 my ($new_unused_file) = "$TMPL_DIR/$MODULE-unused.new";
775 open (UNUSED, ">$new_unused_file")
776 || die "Can't open file: $new_unused_file";
779 my ($symbol, $symbol_desc);
780 for $symbol (sort keys %SymbolDocs) {
781 $symbol_desc = $SymbolDocs{$symbol};
783 # print "Unused: $symbol\n";
785 my $type = $SymbolTypes{$symbol};
786 if (!defined ($type)) {
788 &LogWarning ($SymbolSourceFile{$symbol},$SymbolSourceLine{$symbol}, "Unused symbol $symbol has unknown type.");
792 <!-- ##### $type $symbol ##### -->
797 my ($params) = $SymbolParams{$symbol};
798 if (defined ($params)) {
800 for ($j = 0; $j <= $#$params; $j += 2) {
801 my $param_name = $$params[$j];
802 my $param_desc = $$params[$j + 1];
803 $param_desc =~ s/\s+$//;
804 $output .= "\@$param_name: $param_desc\n";
810 print UNUSED $output;
813 &UpdateFileIfChanged ($old_unused_file, $new_unused_file, 1);
817 #############################################################################
818 # LIBRARY FUNCTIONS - These functions are used in both gtkdoc-mkdb and
819 # gtkdoc-mktmpl and should eventually be moved to a
821 #############################################################################
823 #############################################################################
824 # Function : ReadDeclarationsFile
825 # Description : This reads in a file containing the function/macro/enum etc.
828 # Note that in some cases there are several declarations with
829 # the same name, e.g. for conditional macros. In this case we
830 # set a flag in the %DeclarationConditional hash so the
831 # declaration is not shown in the docs.
833 # If a macro and a function have the same name, e.g. for
834 # gtk_object_ref, the function declaration takes precedence.
836 # Some opaque structs are just declared with 'typedef struct
837 # _name name;' in which case the declaration may be empty.
838 # The structure may have been found later in the header, so
839 # that overrides the empty declaration.
841 # Arguments : $file - the declarations file to read
842 # $override - if declarations in this file should override
843 # any current declaration.
844 #############################################################################
846 sub ReadDeclarationsFile {
847 my ($file, $override) = @_;
849 if ($override == 0) {
851 %DeclarationTypes = ();
852 %DeclarationConditional = ();
853 %DeclarationOutput = ();
857 || die "Can't open $file";
858 my $declaration_type = "";
859 my $declaration_name;
862 if (!$declaration_type) {
864 $declaration_type = $1;
865 $declaration_name = "";
866 # print "Found declaration: $declaration_type\n";
870 if (m%^<NAME>(.*)</NAME>%) {
871 $declaration_name = $1;
872 } elsif (m%<DEPRECATED/>%) {
873 # do nothing, just skip the line; we handle this
875 } elsif (m%^</$declaration_type>%) {
876 # print "Found end of declaration: $declaration_name\n";
877 # Check that the declaration has a name
878 if ($declaration_name eq "") {
879 print "ERROR: $declaration_type has no name $file:$.\n";
882 # Check if the symbol is already defined.
883 if (defined ($Declarations{$declaration_name})
885 # Function declarations take precedence.
886 if ($DeclarationTypes{$declaration_name} eq 'FUNCTION') {
888 } elsif ($declaration_type eq 'FUNCTION') {
889 $Declarations{$declaration_name} = $declaration;
890 $DeclarationTypes{$declaration_name} = $declaration_type;
891 } elsif ($DeclarationTypes{$declaration_name}
892 eq $declaration_type) {
893 # If the existing declaration is empty, or is just a
894 # forward declaration of a struct, override it.
895 if ($declaration_type eq 'STRUCT') {
896 if ($Declarations{$declaration_name} =~ m/^\s*(struct\s+\w+\s*;)?\s*$/) {
897 $Declarations{$declaration_name} = $declaration;
898 } elsif ($declaration =~ m/^\s*(struct\s+\w+\s*;)?\s*$/) {
899 # Ignore an empty or forward declaration.
901 &LogWarning ($file, $., "Structure $declaration_name has multiple definitions.");
905 # set flag in %DeclarationConditional hash for
906 # multiply defined macros/typedefs.
907 $DeclarationConditional{$declaration_name} = 1;
910 &LogWarning ($file, $., "$declaration_name has multiple definitions.");
913 $Declarations{$declaration_name} = $declaration;
914 $DeclarationTypes{$declaration_name} = $declaration_type;
916 $declaration_type = "";
926 #############################################################################
927 # Function : ReadSignalsFile
928 # Description : This reads in an existing file which contains information on
929 # all GObject signals. It creates the arrays @SignalNames and
930 # @SignalPrototypes containing info on the signals. The first
931 # line of the SignalPrototype is the return type of the signal
932 # handler. The remaining lines are the parameters passed to it.
933 # The last parameter, "gpointer user_data" is always the same
934 # so is not included.
935 # Arguments : $file - the file containing the signal handler prototype
937 #############################################################################
939 sub ReadSignalsFile {
947 my $signal_prototype;
949 # Reset the signal info.
954 @SignalPrototypes = ();
959 if (!open (INPUT, $file)) {
960 warn "Can't open $file - skipping signals\n";
969 $signal_returns = "";
970 $signal_prototype = "";
973 if (m/^<NAME>(.*)<\/NAME>/) {
975 if ($signal_name =~ m/^(.*)::(.*)$/) {
977 ($signal_name = $2) =~ s/_/-/g;
978 # print "Found signal: $signal_name\n";
980 print "Invalid signal name: $signal_name\n";
982 } elsif (m/^<RETURNS>(.*)<\/RETURNS>/) {
983 $signal_returns = $1;
984 } elsif (m/^<FLAGS>(.*)<\/FLAGS>/) {
986 } elsif (m%^</SIGNAL>%) {
987 # print "Found end of signal: ${signal_object}::${signal_name}\nReturns: ${signal_returns}\n${signal_prototype}";
988 push (@SignalObjects, $signal_object);
989 push (@SignalNames, $signal_name);
990 push (@SignalReturns, $signal_returns);
991 push (@SignalFlags, $signal_flags);
992 push (@SignalPrototypes, $signal_prototype);
995 $signal_prototype .= $_;
1003 #############################################################################
1004 # Function : ReadTemplateFile
1005 # Description : This reads in the manually-edited documentation file
1006 # corresponding to the file currently being created, so we can
1007 # insert the documentation at the appropriate places.
1008 # It outputs %SymbolTypes, %SymbolDocs and %SymbolParams, which
1009 # is a hash of arrays.
1010 # NOTE: This function is duplicated in gtkdoc-mkdb (but
1011 # slightly different).
1012 # Arguments : $docsfile - the template file to read in.
1013 # $skip_unused_params - 1 if the unused parameters should be
1015 #############################################################################
1017 sub ReadTemplateFile {
1018 my ($docsfile, $skip_unused_params) = @_;
1020 # print "Reading $docsfile\n";
1021 if (! -f $docsfile) {
1022 print "File doesn't exist: $docsfile\n";
1026 my $CurrentType = ""; # Type of symbol being read.
1027 my $CurrentSymbol = ""; # Name of symbol being read.
1028 my $SymbolDoc = ""; # Description of symbol being read.
1029 my @Params; # Parameter names and descriptions of current
1030 # function/macro/function typedef.
1031 my $CurrentParam = -1; # Index of parameter currently being read.
1032 # Note that the param array contains pairs
1033 # of param name & description.
1034 my $InUnusedParameters = 0; # True if we are reading in the unused params.
1036 open (DOCS, $docsfile)
1037 || die "Can't open file $docsfile: $!";
1039 if (m/^<!-- ##### ([A-Z_]+) (\S+) ##### -->/) {
1042 if ($symbol eq "Title"
1043 || $symbol eq "Short_Description"
1044 || $symbol eq "Long_Description"
1045 || $symbol eq "See_Also"
1046 || $symbol eq "Stability_Level"
1047 || $symbol eq "Image") {
1048 $symbol = $docsfile . ":" . $symbol;
1051 #print "Found symbol: $symbol\n";
1052 # Remember file and line for the symbol
1053 $SymbolSourceFile{$symbol} = $docsfile;
1054 $SymbolSourceLine{$symbol} = $.;
1056 # Canonicalize signal and argument names to have -, not _
1057 if ($type eq "ARG" || $type eq "SIGNAL") {
1061 # Store previous symbol, but remove any trailing blank lines.
1062 if ($CurrentSymbol ne "") {
1063 $SymbolDoc =~ s/\s+$//;
1064 $SymbolTypes{$CurrentSymbol} = $CurrentType;
1065 $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
1067 if ($CurrentParam >= 0) {
1068 $SymbolParams{$CurrentSymbol} = [ @Params ];
1070 # Delete any existing params in case we are overriding a
1071 # previously read template.
1072 delete $SymbolParams{$CurrentSymbol};
1075 $CurrentType = $type;
1076 $CurrentSymbol = $symbol;
1078 $InUnusedParameters = 0;
1082 } elsif (m/^<!-- # Unused Parameters # -->/) {
1083 $InUnusedParameters = 1;
1087 # Workaround for an old bug that left a mess in the templates.
1088 # This happened with macros with args spread over several lines.
1090 # Skip the next line.
1095 # Workaround for an old bug that left '@:' at start of lines.
1101 # Check if param found. Need to handle "..." and "format...".
1102 if (s/^\@([\w\.]+):\040?//) {
1103 my $param_name = $1;
1104 # Allow variations of 'Returns'
1105 if ($param_name =~ m/^[Rr]eturns?$/) {
1106 $param_name = "Returns";
1108 # print "Found param: $param_name\n";
1109 push (@Params, $param_name);
1115 # When outputting the DocBook we skip unused parameters.
1116 if (!$InUnusedParameters || !$skip_unused_params) {
1117 if ($CurrentParam >= 0) {
1118 $Params[$CurrentParam] .= $_;
1126 # Remember to finish the current symbol doccs.
1127 if ($CurrentSymbol ne "") {
1129 $SymbolDoc =~ s/\s+$//;
1130 $SymbolTypes{$CurrentSymbol} = $CurrentType;
1131 $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
1133 if ($CurrentParam >= 0) {
1134 $SymbolParams{$CurrentSymbol} = [ @Params ];
1136 delete $SymbolParams{$CurrentSymbol};
1145 #############################################################################
1146 # Function : ReadObjectHierarchy
1147 # Description : This reads in the $MODULE-hierarchy.txt file containing all
1148 # the GtkObject subclasses described in this module (and their
1150 # It places them in the @Objects array, and places their level
1151 # in the widget hierarchy in the @ObjectLevels array, at the
1152 # same index. GtkObject, the root object, has a level of 1.
1154 # FIXME: the version in gtkdoc-mkdb also generates tree_index.sgml
1155 # as it goes along, this should be split out into a separate
1159 #############################################################################
1161 sub ReadObjectHierarchy {
1165 if (! -f $OBJECT_TREE_FILE) {
1168 if (!open (INPUT, $OBJECT_TREE_FILE)) {
1169 warn "Can't open $OBJECT_TREE_FILE - skipping object tree\n";
1175 my $level = (length($`)) / 2 + 1;
1176 # print ("Level: $level Object: $object\n");
1178 push (@Objects, $object);
1179 push (@ObjectLevels, $level);
1187 #############################################################################
1188 # Function : ReadArgsFile
1189 # Description : This reads in an existing file which contains information on
1190 # all GObject args. It creates the arrays @ArgObjects, @ArgNames,
1191 # @ArgTypes and @ArgFlags containing info on the args.
1192 # Arguments : $file - the file containing the arg information.
1193 #############################################################################
1204 # Reset the signal info.
1213 if (!open (INPUT, $file)) {
1214 warn "Can't open $file - skipping args\n";
1227 if (m/^<NAME>(.*)<\/NAME>/) {
1229 if ($arg_name =~ m/^(.*)::(.*)$/) {
1231 ($arg_name = $2) =~ s/_/-/g;
1232 # print "Found arg: $arg_name\n";
1234 print "Invalid arg name: $arg_name\n";
1236 } elsif (m/^<TYPE>(.*)<\/TYPE>/) {
1238 } elsif (m/^<FLAGS>(.*)<\/FLAGS>/) {
1240 } elsif (m%^</ARG>%) {
1241 # print "Found end of arg: ${arg_object}::${arg_name}\n${arg_type} : ${arg_flags}\n";
1242 push (@ArgObjects, $arg_object);
1243 push (@ArgNames, $arg_name);
1244 push (@ArgTypes, $arg_type);
1245 push (@ArgFlags, $arg_flags);
1254 #############################################################################
1255 # Function : CheckIsObject
1256 # Description : Returns 1 if the given name is a GObject or a subclass.
1257 # It uses the global @Objects array.
1258 # Note that the @Objects array only contains classes in the
1259 # current module and their ancestors - not all GObject classes.
1260 # Arguments : $name - the name to check.
1261 #############################################################################
1267 foreach $object (@Objects) {
1268 if ($object eq $name) {