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 %optctl = (module => \$MODULE,
69 'flag-changes' => \$FLAG_CHANGES,
70 'output-dir' => \$TMPL_DIR,
71 'version' => \$PRINT_VERSION);
72 GetOptions(\%optctl, "module=s", "flag-changes!", "output-dir:s", "version");
81 # The directory containing the template files.
82 $TMPL_DIR = $TMPL_DIR ? $TMPL_DIR : "$ROOT_DIR/tmpl";
84 # This file contains the object hierarchy.
85 my $OBJECT_TREE_FILE = "$ROOT_DIR/$MODULE.hierarchy";
87 # The file containing signal handler prototype information.
88 my $SIGNALS_FILE = "$ROOT_DIR/$MODULE.signals";
90 # The file containing Arg information.
91 my $ARGS_FILE = "$ROOT_DIR/$MODULE.args";
93 # Set the flag to indicate changes, if requested.
94 my $CHANGES_FLAG = $FLAG_CHANGES ? "FIXME" : "";
96 # These global arrays store information on signals. Each signal has an entry
97 # in each of these arrays at the same index, like a multi-dimensional array.
98 my @SignalObjects; # The GtkObject which emits the signal.
99 my @SignalNames; # The signal name.
100 my @SignalReturns; # The return type.
101 my @SignalPrototypes; # The rest of the prototype of the signal handler.
103 # These global arrays store information on Args. Each Arg has an entry
104 # in each of these arrays at the same index, like a multi-dimensional array.
105 my @ArgObjects; # The GtkObject which has the Arg.
106 my @ArgNames; # The Arg name.
107 my @ArgTypes; # The Arg type - gint, GtkArrowType etc.
108 my @ArgFlags; # How the Arg can be used - readable/writable etc.
110 # These global hashes store declaration info keyed on a symbol name.
112 my %DeclarationTypes;
113 my %DeclarationConditional;
114 my %DeclarationOutput;
116 # These global hashes store the existing documentation.
121 # These global arrays store GtkObject and subclasses and the hierarchy.
125 &ReadSignalsFile ($SIGNALS_FILE);
126 &ReadArgsFile ($ARGS_FILE);
127 &ReadObjectHierarchy;
129 &ReadDeclarationsFile ("$ROOT_DIR/$MODULE-decl.txt", 0);
130 if (-f "$ROOT_DIR/$MODULE-overrides.txt") {
131 &ReadDeclarationsFile ("$ROOT_DIR/$MODULE-overrides.txt", 1);
133 &ReadExistingTemplates;
137 if (&UpdateTemplates ("$ROOT_DIR/$MODULE-sections.txt")) {
140 &OutputUnusedTemplates;
141 if (&CheckAllDeclarationsOutput) {
145 if ($changed || ! -e "$ROOT_DIR/tmpl.stamp") {
146 open (TIMESTAMP, ">$ROOT_DIR/tmpl.stamp")
147 || die "Can't create $ROOT_DIR/tmpl.stamp";
148 print (TIMESTAMP "timestamp");
152 #############################################################################
153 # Function : ReadExistingTemplates
154 # Description : This reads in all the existing documentation, into the global
155 # variables %SymbolDocs, %SymbolTypes, and %SymbolParams (a
158 #############################################################################
160 sub ReadExistingTemplates {
165 # Read the unused docs first, so they get overridden by any real docs.
166 # (though this shouldn't happen often).
167 my $unused_doc = "$TMPL_DIR/$MODULE-unused.sgml";
168 if (-e $unused_doc) {
169 &ReadTemplateFile ($unused_doc, 0);
172 while (<$TMPL_DIR/*.sgml>) {
173 # print "Reading $_\n";
174 if ($_ eq $unused_doc) {
175 # print "skipping $unused_doc\n";
177 &ReadTemplateFile ($_, 0);
183 #############################################################################
184 # Function : UpdateTemplates
185 # Description : This collects the output for each section of the docs, and
186 # outputs each file when the end of the section is found.
187 # Arguments : $file - the file containing the sections of the docs.
188 #############################################################################
190 sub UpdateTemplates {
192 # print "Reading: $file\n";
195 || die "Can't open $file";
197 # Create the top output directory if it doesn't exist.
198 if (! -e $TMPL_DIR) {
199 mkdir ("$TMPL_DIR", 0777)
200 || die "Can't create directory: $TMPL_DIR";
211 } elsif (m/^<SECTION>/) {
214 } elsif (m/^<SUBSECTION\s*(.*)>/i) {
218 } elsif (m/^<TITLE>(.*)<\/TITLE>/) {
220 # print "Section: $title\n";
222 } elsif (m/^<FILE>(.*)<\/FILE>/) {
225 } elsif (m/^<INCLUDE>(.*)<\/INCLUDE>/) {
228 } elsif (m/^<\/SECTION>/) {
232 # print "End of section: $title\n";
237 if (&OutputTemplateFile ($file, $title, \$output)) {
244 } elsif (m/^(\S+)/) {
246 # print " Symbol: $symbol\n";
248 my $declaration = $Declarations{$1};
249 if (defined ($declaration)) {
250 # We don't want templates for standard macros/functions of
251 # GtkObjects or private declarations.
252 if ($subsection ne "Standard" && $subsection ne "Private") {
253 $output .= &OutputDeclaration ($DeclarationTypes {$symbol},
254 $symbol, $declaration);
257 # Note that the declaration has been output.
258 $DeclarationOutput{$symbol} = 1;
260 if ($declaration eq '##conditional##') {
261 # print "Conditional $DeclarationTypes{$symbol}\n";
264 print "WARNING: No declaration for: $1\n";
274 #############################################################################
275 # Function : CheckAllDeclarationsOutput
276 # Description : This steps through all the declarations that were loaded, and
277 # makes sure that each one has been output, by checking the
278 # corresponding flag in the %DeclarationOutput hash. It is
279 # intended to check that any new declarations in new versions
280 # of GTK/Gnome get added to the $MODULE-sections.txt file.
282 #############################################################################
284 sub CheckAllDeclarationsOutput {
287 my $old_unused_file = "$ROOT_DIR/$MODULE-unused.txt";
288 my $new_unused_file = "$ROOT_DIR/$MODULE-unused.new";
290 open (UNUSED, ">$new_unused_file")
291 || die "Can't open $new_unused_file";
293 foreach $symbol (keys (%Declarations)) {
294 if (!defined ($DeclarationOutput{$symbol})) {
295 print (UNUSED "$symbol\n");
300 if ($num_unused != 0) {
302 =============================================================================
303 WARNING: $num_unused unused declarations.
304 These can be found in $MODULE-unused.txt.
305 They should be added to $MODULE-sections.txt in the appropriate place.
306 =============================================================================
310 return &UpdateFileIfChanged ($old_unused_file, $new_unused_file, 0);
314 #############################################################################
315 # Function : OutputDeclaration
316 # Description : This returns the template for one symbol & declaration.
317 # Note that it uses the global %SymbolDocs and %SymbolParams to
318 # lookup any existing documentation.
319 # Arguments : $type - the type of the symbol ('FUNCTION'/'MACRO' etc.)
320 # $symbol - the symbol name.
321 # $declaration - the declaration of the symbol.
322 #############################################################################
324 sub OutputDeclaration {
325 my ($type, $symbol, $declaration) = @_;
328 # print "Outputting $type: $symbol\n";
330 # See if symbol already has a description.
331 my ($symbol_desc) = $SymbolDocs{$symbol};
332 my ($template_exists);
333 if (defined ($symbol_desc)) {
334 $template_exists = 1;
335 $symbol_desc =~ s/\s+$//;
337 $template_exists = 0;
338 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
342 <!-- ##### $type $symbol ##### -->
347 # For functions, function typedefs and macros, we output the arguments.
348 # For functions and function typedefs we also output the return value.
349 if ($type eq "FUNCTION" || $type eq "USER_FUNCTION") {
350 # Take out the return type
351 $declaration =~ s/<RETURNS>\s*(const\s+|G_CONST_RETURN\s+|unsigned\s+)*(\w+)\s*(\**)\s*<\/RETURNS>\n//;
356 while ($declaration ne "") {
357 if ($declaration =~ s/^[\s,]+//) {
358 # skip whitespace and commas
361 } elsif ($declaration =~ s/^void\s*[,\n]//) {
362 if ($param_num != 0) {
363 print "WARNING: void used as parameter in function $symbol\n";
366 } elsif ($declaration =~ s/^...\s*[,\n]//) {
367 $output .= &OutputParam ($symbol, "Varargs",
368 $template_exists, 1, "");
370 # Try to match a standard parameter.
371 } elsif ($declaration =~ s/^(const\s+|G_CONST_RETURN\s+|unsigned\s+)*(struct\s+)?((?:long\s+|short\s+)?\w+)\s*(\**)\s*(const\s+)?(\**)?\s*(\w+)?\s*((?:\[\S*\])*)\s*[,\n]//) {
375 $name = "Param" . ($param_num + 1);
377 $output .= &OutputParam ($symbol, $name, $template_exists, 1,
380 # Try to match parameters which are functions.
381 } elsif ($declaration =~ s/^(const\s+|G_CONST_RETURN\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(const\s+)?\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*[,\n]//) {
383 $output .= &OutputParam ($symbol, $name, $template_exists, 1,
387 print "###Can't parse args for function $symbol: $declaration\n";
394 if ($ret_type ne "void") {
395 $output .= &OutputParam ($symbol, "Returns", $template_exists, 1,
398 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
399 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
400 $output .= &OutputOldParams ($symbol);
404 if ($type eq "MACRO") {
405 if ($declaration =~ m/^\s*#\s*define\s+\w+\(([^\)]*)\)/) {
407 foreach $param (split (/,/, $1)) {
410 if ($param =~ m/\S/) {
411 $output .= &OutputParam ($symbol, $param, $template_exists,
416 $output .= &OutputParam ($symbol, "Returns", $template_exists, 0, "");
417 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
418 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
419 $output .= &OutputOldParams ($symbol);
423 if ($type eq "STRUCT") {
424 my $is_object_struct = CheckIsObject ($symbol);
425 my @fields = ParseStructDeclaration($declaration, $is_object_struct);
427 for (my $i = 0; $i <= $#fields; $i += 2) {
428 my $field_name = $fields[$i];
429 $output .= &OutputParam ($symbol, $field_name, $template_exists, 1, "");
431 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
432 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
435 if ($type eq "ENUM") {
436 my @members = ParseEnumDeclaration($declaration);
438 for my $member (@members) {
439 $output .= &OutputParam ($symbol, $member, $template_exists, 1, "");
441 $output .= &OutputParam ($symbol, "Deprecated", $template_exists, 0, "");
442 $output .= &OutputParam ($symbol, "Since", $template_exists, 0, "");
447 # Remove the used docs from the hashes.
448 if ($template_exists) {
449 delete $SymbolDocs{$symbol};
450 delete $SymbolParams{$symbol};
457 #############################################################################
458 # Function : OutputParam
459 # Description : This outputs the part of a template for one parameter.
460 # It first checks if the parameter is already described, and if
461 # so it uses that description, and clears it so it isn't output
463 # Arguments : $symbol - the symbol (function or macro) name.
464 # $param_to_output - the parameter to add.
465 # $template_exists - TRUE if the template already existed in
466 # template files. If it did, then we will flag any changes
468 # $force_output - TRUE if the parameter should be output even
469 # if it didn't already exist in the template. (The return
470 # values of macros are added manually if required, and so we
471 # never add it here - we only copy it if it already exists.)
472 # $default_description - the default description of the
473 # parameter to be used if it doesn't already exist. (Signal
474 # handlers have a few common parameters.)
475 #############################################################################
478 my ($symbol, $param_to_output, $template_exists,
479 $force_output, $default_description) = @_;
482 my ($params) = $SymbolParams{$symbol};
483 if (defined ($params)) {
484 for ($j = 0; $j <= $#$params; $j += 2) {
485 my $param_name = $$params[$j];
486 my $param_desc = $$params[$j + 1];
488 if ($param_name eq $param_to_output) {
489 $param_desc =~ s/\s+$//;
491 $$params[$j + 1] = "";
492 return "\@$param_name: $param_desc\n";
497 # If the template was already in a file, flag the new parameter.
498 # If not, the template itself will be flagged, so we don't need to flag
499 # all the new parameters as well.
501 if ($default_description ne "") {
502 $default_description =~ s/\s+$//;
503 return "\@$param_to_output: $default_description\n";
505 if ($template_exists) {
506 return "\@$param_to_output: $CHANGES_FLAG\n";
508 return "\@$param_to_output: \n";
516 #############################################################################
517 # Function : OutputOldParams
518 # Description : This returns all the existing documentation for parameters of
519 # the given function/macro/signal symbol which are unused, with
520 # a comment before them.
521 # Arguments : $symbol - the symbol (function/macro/signal) name.
522 #############################################################################
524 sub OutputOldParams {
528 my ($params) = $SymbolParams{$symbol};
529 if (defined ($params)) {
531 for ($j = 0; $j <= $#$params; $j += 2) {
532 my $param_name = $$params[$j];
533 my $param_desc = $$params[$j + 1];
535 if ($param_name ne "") {
536 $param_desc =~ s/\s+$//;
537 $output .= "\@$param_name: $param_desc\n";
542 $output = "<!-- # Unused Parameters # -->\n" . $output;
548 #############################################################################
549 # Function : OutputTemplateFile
550 # Description : This outputs one template file.
551 # Arguments : $file - the basename of the file to output.
552 # $title - the title from the $MODULE-sections.txt file. This
553 # will be overridden by any title given in the template file.
554 # $output - reference to the templates to output.
555 #############################################################################
557 sub OutputTemplateFile {
558 my ($file, $title, $output) = @_;
560 my ($short_desc, $long_desc, $see_also);
562 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Title"})) {
563 $title = $SymbolDocs{"$TMPL_DIR/$file:Title"};
564 delete $SymbolDocs{"$TMPL_DIR/$file:Title"};
566 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Short_Description"})) {
567 $short_desc = $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
568 delete $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
572 if (defined ($SymbolDocs{"$TMPL_DIR/$file:Long_Description"})) {
573 $long_desc = $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
574 delete $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
576 $long_desc = "<para>\n\n</para>\n";
578 if (defined ($SymbolDocs{"$TMPL_DIR/$file:See_Also"})) {
579 $see_also = $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
580 delete $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
582 $see_also = "<para>\n\n</para>\n";
585 my $old_tmpl_file = "$TMPL_DIR/$file";
586 my $new_tmpl_file = "$TMPL_DIR/$file.new";
588 open (OUTPUT, ">$new_tmpl_file")
589 || die "Can't create $new_tmpl_file";
591 print (OUTPUT <<EOF);
592 <!-- ##### SECTION Title ##### -->
595 <!-- ##### SECTION Short_Description ##### -->
598 <!-- ##### SECTION Long_Description ##### -->
601 <!-- ##### SECTION See_Also ##### -->
606 print (OUTPUT $$output);
607 &OutputSignalTemplates ($title);
608 &OutputArgTemplates ($title);
611 return &UpdateFileIfChanged ($old_tmpl_file, $new_tmpl_file, 1);
615 #############################################################################
616 # Function : OutputSignalTemplates
617 # Description : Outputs templates for signal handlers.
618 # Arguments : $title - the title from the $MODULE-sections.txt file. If the
619 # file is describing a GtkObject subclass, the title should
620 # be the name of the class, e.g. 'GtkButton'.
621 #############################################################################
623 sub OutputSignalTemplates {
627 my ($i, $template_exists);
628 for ($i = 0; $i <= $#SignalObjects; $i++) {
629 if ($SignalObjects[$i] eq $title) {
630 # print "Found signal: $SignalObjects[$i]\n";
631 my ($symbol) = "$SignalObjects[$i]::$SignalNames[$i]";
633 # See if symbol already has a description.
634 my ($symbol_desc) = $SymbolDocs{$symbol};
635 if (defined ($symbol_desc)) {
636 $template_exists = 1;
637 $symbol_desc =~ s/\s+$//;
638 delete $SymbolDocs{$symbol};
640 $template_exists = 0;
641 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
645 <!-- ##### SIGNAL $symbol ##### -->
649 my $sourceparams = $SymbolParams{$symbol};
650 my @params = split ("[,\n]", $SignalPrototypes[$i]);
652 for ($j = 0; $j <= $#params; $j++) {
653 my $param = $params[$j];
656 if ($param =~ m/^\s*$/) { next; }
657 if ($param =~ m/^void$/) { next; }
659 if ($param =~ m/^\s*(\w+)\s*(\**)\s*([\w\[\]]+)?\s*$/) {
660 if (defined($sourceparams)) {
661 $name = $$sourceparams[2 * $j];
663 elsif (defined($3)) {
666 $name = "Param" . ($j + 1);
669 $output .= &OutputParam ($symbol, $name,
671 "the object which received the signal.");
673 $output .= &OutputParam ($symbol, $name,
674 $template_exists, 1, "");
679 if ($SignalReturns[$i] ne "void") {
680 $output .= &OutputParam ($symbol, "Returns", $template_exists,
683 $output .= &OutputOldParams ($symbol);
687 print (OUTPUT $output);
691 #############################################################################
692 # Function : OutputArgTemplates
693 # Description : Outputs templates for Args.
694 # Arguments : $title - the title from the $MODULE-sections.txt file. If the
695 # file is describing a GtkObject subclass, the title should
696 # be the name of the class, e.g. 'GtkButton'.
697 #############################################################################
699 sub OutputArgTemplates {
704 for ($i = 0; $i <= $#ArgObjects; $i++) {
705 if ($ArgObjects[$i] eq $title) {
706 # print "Found arg: $ArgObjects[$i]\n";
707 # I've only used one colon so we don't clash with signals.
708 my ($symbol) = "$ArgObjects[$i]:$ArgNames[$i]";
710 # See if symbol already has a description.
711 my ($symbol_desc) = $SymbolDocs{$symbol};
712 if (defined ($symbol_desc)) {
713 delete $SymbolDocs{$symbol};
714 $symbol_desc =~ s/\s+$//;
716 $symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
720 <!-- ##### ARG $symbol ##### -->
726 print (OUTPUT $output);
730 #############################################################################
731 # Function : OutputUnusedTemplates
732 # Description : This saves any unused documentation into $MODULE-unused.sgml.
734 #############################################################################
736 sub OutputUnusedTemplates {
737 my ($old_unused_file) = "$TMPL_DIR/$MODULE-unused.sgml";
738 my ($new_unused_file) = "$TMPL_DIR/$MODULE-unused.new";
740 open (UNUSED, ">$new_unused_file")
741 || die "Can't open file: $new_unused_file";
744 my ($symbol, $symbol_desc);
745 for $symbol (sort keys %SymbolDocs) {
746 $symbol_desc = $SymbolDocs{$symbol};
748 # print "Unused: $symbol\n";
750 my $type = $SymbolTypes{$symbol};
751 if (!defined ($type)) {
753 print "WARNING: Unused symbol $symbol has unknown type\n";
757 <!-- ##### $type $symbol ##### -->
762 my ($params) = $SymbolParams{$symbol};
763 if (defined ($params)) {
765 for ($j = 0; $j <= $#$params; $j += 2) {
766 my $param_name = $$params[$j];
767 my $param_desc = $$params[$j + 1];
768 $param_desc =~ s/\s+$//;
769 $output .= "\@$param_name: $param_desc\n";
775 print UNUSED $output;
778 &UpdateFileIfChanged ($old_unused_file, $new_unused_file, 1);
782 #############################################################################
783 # LIBRARY FUNCTIONS - These functions are used in both gtkdoc-mkdb and
784 # gtkdoc-mktmpl and should eventually be moved to a
786 #############################################################################
788 #############################################################################
789 # Function : ReadDeclarationsFile
790 # Description : This reads in a file containing the function/macro/enum etc.
793 # Note that in some cases there are several declarations with
794 # the same name, e.g. for conditional macros. In this case we
795 # set a flag in the %DeclarationConditional hash so the
796 # declaration is not shown in the docs.
798 # If a macro and a function have the same name, e.g. for
799 # gtk_object_ref, the function declaration takes precedence.
801 # Some opaque structs are just declared with 'typedef struct
802 # _name name;' in which case the declaration may be empty.
803 # The structure may have been found later in the header, so
804 # that overrides the empty declaration.
806 # Arguments : $file - the declarations file to read
807 # $override - if declarations in this file should override
808 # any current declaration.
809 #############################################################################
811 sub ReadDeclarationsFile {
812 my ($file, $override) = @_;
814 if ($override == 0) {
816 %DeclarationTypes = ();
817 %DeclarationConditional = ();
818 %DeclarationOutput = ();
822 || die "Can't open $file";
823 my $declaration_type = "";
824 my $declaration_name;
827 if (!$declaration_type) {
829 $declaration_type = $1;
830 $declaration_name = "";
831 # print "Found declaration: $declaration_type\n";
835 if (m%^<NAME>(.*)</NAME>%) {
836 $declaration_name = $1;
837 } elsif (m%<DEPRECATED/>%) {
838 # do nothing, just skip the line; we handle this
840 } elsif (m%^</$declaration_type>%) {
841 # print "Found end of declaration: $declaration_name\n";
842 # Check that the declaration has a name
843 if ($declaration_name eq "") {
844 print "ERROR: $declaration_type has no name $file:$.\n";
847 # Check if the symbol is already defined.
848 if (defined ($Declarations{$declaration_name})
850 # Function declarations take precedence.
851 if ($DeclarationTypes{$declaration_name} eq 'FUNCTION') {
853 } elsif ($declaration_type eq 'FUNCTION') {
854 $Declarations{$declaration_name} = $declaration;
855 $DeclarationTypes{$declaration_name} = $declaration_type;
856 } elsif ($DeclarationTypes{$declaration_name}
857 eq $declaration_type) {
858 # If the existing declaration is empty override it.
859 if ($declaration_type eq 'STRUCT') {
860 if ($Declarations{$declaration_name} =~ m/^\s*$/) {
861 $Declarations{$declaration_name} = $declaration;
862 } elsif ($declaration =~ m/^\s*$/) {
863 # Ignore an empty declaration.
865 print "WARNING: Structure has multiple definitions: $declaration_name\n";
869 # set flag in %DeclarationConditional hash for
870 # multiply defined macros/typedefs.
871 $DeclarationConditional{$declaration_name} = 1;
874 print "WARNING: $declaration_name has multiple definitions\n";
877 $Declarations{$declaration_name} = $declaration;
878 $DeclarationTypes{$declaration_name} = $declaration_type;
880 $declaration_type = "";
890 #############################################################################
891 # Function : ReadSignalsFile
892 # Description : This reads in an existing file which contains information on
893 # all GTK signals. It creates the arrays @SignalNames and
894 # @SignalPrototypes containing info on the signals. The first
895 # line of the SignalPrototype is the return type of the signal
896 # handler. The remaining lines are the parameters passed to it.
897 # The last parameter, "gpointer user_data" is always the same
898 # so is not included.
899 # Arguments : $file - the file containing the signal handler prototype
901 #############################################################################
903 sub ReadSignalsFile {
910 my $signal_prototype;
912 # Reset the signal info.
916 @SignalPrototypes = ();
921 if (!open (INPUT, $file)) {
922 warn "Can't open $file - skipping signals\n";
931 $signal_returns = "";
932 $signal_prototype = "";
935 if (m/^<NAME>(.*)<\/NAME>/) {
937 if ($signal_name =~ m/^(.*)::(.*)$/) {
939 ($signal_name = $2) =~ s/_/-/g;
940 # print "Found signal: $signal_name\n";
942 print "Invalid signal name: $signal_name\n";
944 } elsif (m/^<RETURNS>(.*)<\/RETURNS>/) {
945 $signal_returns = $1;
946 } elsif (m%^</SIGNAL>%) {
947 # print "Found end of signal: ${signal_object}::${signal_name}\nReturns: ${signal_returns}\n${signal_prototype}";
948 push (@SignalObjects, $signal_object);
949 push (@SignalNames, $signal_name);
950 push (@SignalReturns, $signal_returns);
951 push (@SignalPrototypes, $signal_prototype);
954 $signal_prototype .= $_;
962 #############################################################################
963 # Function : ReadTemplateFile
964 # Description : This reads in the manually-edited documentation file
965 # corresponding to the file currently being created, so we can
966 # insert the documentation at the appropriate places.
967 # It outputs %SymbolTypes, %SymbolDocs and %SymbolParams, which
968 # is a hash of arrays.
969 # NOTE: This function is duplicated in gtkdoc-mkdb (but
970 # slightly different).
971 # Arguments : $docsfile - the template file to read in.
972 # $skip_unused_params - 1 if the unused parameters should be
974 #############################################################################
976 sub ReadTemplateFile {
977 my ($docsfile, $skip_unused_params) = @_;
979 # print "Reading $docsfile\n";
980 if (! -f $docsfile) {
981 print "File doesn't exist: $docsfile\n";
985 my $CurrentType = ""; # Type of symbol being read.
986 my $CurrentSymbol = ""; # Name of symbol being read.
987 my $SymbolDoc = ""; # Description of symbol being read.
988 my @Params; # Parameter names and descriptions of current
989 # function/macro/function typedef.
990 my $CurrentParam = -1; # Index of parameter currently being read.
991 # Note that the param array contains pairs
992 # of param name & description.
993 my $InUnusedParameters = 0; # True if we are reading in the unused params.
995 open (DOCS, $docsfile)
996 || die "Can't open file $docsfile: $!";
998 if (m/^<!-- ##### ([A-Z_]+) (\S+) ##### -->/) {
1001 if ($symbol eq "Title"
1002 || $symbol eq "Short_Description"
1003 || $symbol eq "Long_Description"
1004 || $symbol eq "See_Also") {
1005 $symbol = $docsfile . ":" . $symbol;
1006 # print "Found symbol: $symbol\n";
1009 # Canonicalize signal and argument names to have -, not _
1010 if ($type eq "ARG" || $type eq "SIGNAL") {
1014 # Store previous symbol, but remove any trailing blank lines.
1015 if ($CurrentSymbol ne "") {
1016 $SymbolDoc =~ s/\s+$//;
1017 $SymbolTypes{$CurrentSymbol} = $CurrentType;
1018 $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
1019 if ($CurrentParam >= 0) {
1020 $SymbolParams{$CurrentSymbol} = [ @Params ];
1022 # Delete any existing params in case we are overriding a
1023 # previously read template.
1024 delete $SymbolParams{$CurrentSymbol};
1027 $CurrentType = $type;
1028 $CurrentSymbol = $symbol;
1030 $InUnusedParameters = 0;
1034 } elsif (m/^<!-- # Unused Parameters # -->/) {
1035 $InUnusedParameters = 1;
1039 # Check if param found
1040 if (s/^\@(\S+):\040?//) {
1041 my $param_name = $1;
1042 # Allow variations of 'Returns'
1043 if ($param_name =~ m/^[Rr]eturns?$/) {
1044 $param_name = "Returns";
1046 # print "Found param: $param_name\n";
1047 push (@Params, $param_name);
1053 # When outputting the DocBook we skip unused parameters.
1054 if (!$InUnusedParameters || !$skip_unused_params) {
1055 if ($CurrentParam >= 0) {
1056 $Params[$CurrentParam] .= $_;
1064 # Remember to finish the current symbol doccs.
1065 if ($CurrentSymbol ne "") {
1066 $SymbolDoc =~ s/\s+$//;
1067 $SymbolTypes{$CurrentSymbol} = $CurrentType;
1068 $SymbolDocs{$CurrentSymbol} = $SymbolDoc;
1069 if ($CurrentParam >= 0) {
1070 $SymbolParams{$CurrentSymbol} = [ @Params ];
1072 delete $SymbolParams{$CurrentSymbol};
1080 #############################################################################
1081 # Function : ReadObjectHierarchy
1082 # Description : This reads in the $MODULE-hierarchy.txt file containing all
1083 # the GtkObject subclasses described in this module (and their
1085 # It places them in the @Objects array, and places their level
1086 # in the widget hierarchy in the @ObjectLevels array, at the
1087 # same index. GtkObject, the root object, has a level of 1.
1089 # FIXME: the version in gtkdoc-mkdb also generates tree_index.sgml
1090 # as it goes along, this should be split out into a separate
1094 #############################################################################
1096 sub ReadObjectHierarchy {
1100 if (! -f $OBJECT_TREE_FILE) {
1103 if (!open (INPUT, $OBJECT_TREE_FILE)) {
1104 warn "Can't open $OBJECT_TREE_FILE - skipping object tree\n";
1110 my $level = (length($`)) / 2 + 1;
1111 # print ("Level: $level Object: $object\n");
1113 push (@Objects, $object);
1114 push (@ObjectLevels, $level);
1122 #############################################################################
1123 # Function : ReadArgsFile
1124 # Description : This reads in an existing file which contains information on
1125 # all GTK args. It creates the arrays @ArgObjects, @ArgNames,
1126 # @ArgTypes and @ArgFlags containing info on the args.
1127 # Arguments : $file - the file containing the arg information.
1128 #############################################################################
1139 # Reset the signal info.
1148 if (!open (INPUT, $file)) {
1149 warn "Can't open $file - skipping args\n";
1162 if (m/^<NAME>(.*)<\/NAME>/) {
1164 if ($arg_name =~ m/^(.*)::(.*)$/) {
1166 ($arg_name = $2) =~ s/_/-/g;
1167 # print "Found arg: $arg_name\n";
1169 print "Invalid arg name: $arg_name\n";
1171 } elsif (m/^<TYPE>(.*)<\/TYPE>/) {
1173 } elsif (m/^<FLAGS>(.*)<\/FLAGS>/) {
1175 } elsif (m%^</ARG>%) {
1176 # print "Found end of arg: ${arg_object}::${arg_name}\n${arg_type} : ${arg_flags}\n";
1177 push (@ArgObjects, $arg_object);
1178 push (@ArgNames, $arg_name);
1179 push (@ArgTypes, $arg_type);
1180 push (@ArgFlags, $arg_flags);
1189 #############################################################################
1190 # Function : CheckIsObject
1191 # Description : Returns 1 if the given name is a GtkObject or a subclass.
1192 # It uses the global @Objects array.
1193 # Note that the @Objects array only contains classes in the
1194 # current module and their ancestors - not all GTK classes.
1195 # Arguments : $name - the name to check.
1196 #############################################################################
1202 foreach $object (@Objects) {
1203 if ($object eq $name) {
1211 #############################################################################
1212 # Function : ParseStructDeclaration
1213 # Description : This function takes a structure declaration and
1214 # breaks it into individual type declarations.
1215 # Arguments : $declaration - the declaration to parse
1216 # $is_object - true if this is an object structure
1217 # $typefunc - function reference to apply to type
1218 # $namefunc - function reference to apply to name
1219 #############################################################################
1221 sub ParseStructDeclaration {
1222 my ($declaration, $is_object, $typefunc, $namefunc) = @_;
1224 # Remove all private parts of the declaration
1226 # For objects, assume private
1228 $declaration =~ s!(struct\s+\w*\s*\{)
1230 (?:/\*\s*<\s*public\s*>\s*\*/|(?=\}))!$1!msgx;
1233 # Assume end of declaration if line begins with '}'
1234 $declaration =~ s!\n?[ \t]*/\*\s*<\s*(private|protected)\s*>\s*\*/
1236 (?:/\*\s*<\s*public\s*>\s*\*/|(?=^\}))!!msgx;
1238 # Remove all other comments;
1239 $declaration =~ s@/\*([^*]+|\*(?!/))*\*/@ @g;
1243 if ($declaration =~ /^\s*$/) {
1247 # Prime match after "struct {" declaration
1248 if (!scalar($declaration =~ m/struct\s+\w*\s*\{/msg)) {
1249 die "Structure declaration '$declaration' does not begin with struct [NAME] {\n";
1252 # Treat lines in sequence, allowing singly nested anonymous structs
1254 while ($declaration =~ m/\s*([^{;]+(\{[^\}]*\}[^{;]+)?);/msg) {
1257 last if $line =~ /^\s*\}\s*\w*\s*$/;
1259 # FIXME: Just ignore nested structs and unions for now
1260 next if $line =~ /{/;
1262 # FIXME: The regexes here are the same as in OutputFunction;
1263 # this functionality should be separated out.
1266 (const\s+|unsigned\s+)*(struct\s+)? # mod1
1271 (\w+(?:\s*,\s*\w+)*)\s* # name
1272 (?:((?:\[[^\]]*\]\s*)+) | # array
1273 (:\s*\d+))?\s* # bits
1275 my $mod1 = defined($1) ? $1 : "";
1276 if (defined($2)) { $mod1 .= $2; }
1279 my $mod2 = defined($5) ? $5 : "";
1282 $ptr1 = " " . $ptr1;
1283 my $array = defined($8) ? $8 : "";
1284 my $bits = defined($9) ? " $9" : "";
1285 my $ptype = defined $typefunc ? $typefunc->($type) : $type;
1288 # As a hack, we allow the "name" to be of the form
1289 # "a, b, c". This isn't the correct C syntax, but
1290 # at least we get "gint16 x, y" right. Such constructs
1291 # should really be completely removed from the source.
1292 # Or we should really try to understand the C syntax
1295 my @names = split /\s*,\s*/, $name;
1296 for my $n (@names) {
1298 if (defined $namefunc) {
1299 $n = $namefunc->($n);
1301 push @result, "$mod1$ptype$ptr1$mod2$ptr2$n$array$bits";
1304 # Try to match structure members which are functions
1305 } elsif ($line =~ m/^
1306 (const\s+|G_CONST_RETURN\s+|unsigned\s+)*(struct\s+)? # mod1
1310 \(\s*\*\s*(\w+)\s*\)\s* # name
1311 \(([^)]*)\)\s* # func_params
1314 my $mod1 = defined($1) ? $1 : "";
1315 if (defined($2)) { $mod1 .= $2; }
1318 my $mod2 = defined($5) ? $5 : "";
1320 my $func_params = $7;
1321 my $ptype = defined $typefunc ? $typefunc->($type) : $type;
1322 my $pname = defined $namefunc ? $namefunc->($name) : $name;
1324 push @result, $name;
1325 push @result, "$mod1$ptype$ptr1$mod2 (*$pname) ($func_params)";
1328 warn "Cannot parse structure field \"$line\"";
1336 #############################################################################
1337 # Function : ParseEnumDeclaration
1338 # Description : This function takes a enumeration declaration and
1339 # breaks it into individual enum member declarations.
1340 # Arguments : $declaration - the declaration to parse
1341 #############################################################################
1343 sub ParseEnumDeclaration {
1344 my ($declaration, $is_object) = @_;
1347 $declaration =~ s@/\*([^*]+|\*(?!/))*\*/@ @g;
1351 if ($declaration =~ /^\s*$/) {
1355 # Remove parenthesized expressions (in macros like GTK_BLAH = BLAH(1,3))
1356 # to avoid getting confused by commas they might contain. This
1357 # doesn't handle nested parentheses correctly.
1359 $declaration =~ s/\([^)]*\)//g;
1361 # Prime match after "typedef enum {" declaration
1362 if (!scalar($declaration =~ m/typedef\s+enum\s*\{/msg)) {
1363 die "Enum declaration '$declaration' does not begin with typedef enum {\n";
1366 # Treat lines in sequence.
1367 while ($declaration =~ m/\s*([^,\}]+)([,\}])/msg) {
1369 my $terminator = $2;
1371 if ($line =~ m/^(\w+)\s*(=.*)?$/msg) {
1374 # Special case for GIOCondition, where the values are specified by
1375 # macros which expand to include the equal sign like '=1'.
1376 } elsif ($line =~ m/^(\w+)\s*GLIB_SYSDEF_POLL/msg) {
1379 # Special case include of <gdk/gdkcursors.h>, just ignore it
1380 } elsif ($line =~ m/^#include/) {
1384 warn "Cannot parse enumeration member \"$line\"";
1387 last if $terminator eq '}';