mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
1347 lines
40 KiB
Text
1347 lines
40 KiB
Text
|
#!/usr/bin/perl -w
|
||
|
#
|
||
|
# gtk-doc - GTK DocBook documentation generator.
|
||
|
# Copyright (C) 1998 Damon Chaplin
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License as published by
|
||
|
# the Free Software Foundation; either version 2 of the License, or
|
||
|
# (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program; if not, write to the Free Software
|
||
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
#
|
||
|
|
||
|
#############################################################################
|
||
|
# Script : gtkdoc-mktmpl
|
||
|
# Description : This creates or updates the template files which contain the
|
||
|
# manually-edited documentation. (A 'template' is a simple text
|
||
|
# form which is filled in with the description of a function,
|
||
|
# macro, enum, or struct. For functions and macros it also
|
||
|
# contains fields for describing the parameters.)
|
||
|
#
|
||
|
# This script reads in the existing templates, found in
|
||
|
# tmpl/*.sgml, moves these files to tmpl/*.sgml.bak, and then
|
||
|
# recreates the .sgml files according to the structure given in
|
||
|
# the file $MODULE-sections.txt.
|
||
|
#
|
||
|
# Any new templates added, or new function parameters, are
|
||
|
# marked with 'FIXME' so you can do a grep to see which parts
|
||
|
# need updating.
|
||
|
#
|
||
|
# Any templates which are no longer used (i.e. they are remove
|
||
|
# from $MODULE-sections.txt) are placed in the file
|
||
|
# tmpl/$MODULE-unused.txt. If they are included again later
|
||
|
# they are automatically copied back into position.
|
||
|
# If you are certain that these templates will never be used
|
||
|
# again you can delete them from $MODULE-unused.txt.
|
||
|
#
|
||
|
# Any parameters to functions which are no longer used are
|
||
|
# separated from the rest of the parameters with the line
|
||
|
# '<!-- # Unused Parameters # -->'. It may be that the parameter
|
||
|
# name has just been changed, in which case you can copy the
|
||
|
# description to the parameter with the new name. You can delete
|
||
|
# the unused parameter descriptions when no longer needed.
|
||
|
#############################################################################
|
||
|
|
||
|
use strict;
|
||
|
use Getopt::Long;
|
||
|
|
||
|
# Options
|
||
|
|
||
|
# name of documentation module
|
||
|
my $MODULE;
|
||
|
my $TMPL_DIR;
|
||
|
my $FLAG_CHANGES;
|
||
|
|
||
|
my %optctl = (module => \$MODULE,
|
||
|
'flag-changes' => \$FLAG_CHANGES,
|
||
|
'output-dir' => \$TMPL_DIR);
|
||
|
GetOptions(\%optctl, "module=s", "flag-changes!", "output-dir:s");
|
||
|
|
||
|
my $ROOT_DIR = ".";
|
||
|
|
||
|
# The directory containing the template files.
|
||
|
$TMPL_DIR = $TMPL_DIR ? $TMPL_DIR : "$ROOT_DIR/tmpl";
|
||
|
|
||
|
# This file contains the object hierarchy.
|
||
|
my $OBJECT_TREE_FILE = "$ROOT_DIR/$MODULE.hierarchy";
|
||
|
|
||
|
# The file containing signal handler prototype information.
|
||
|
my $SIGNALS_FILE = "$ROOT_DIR/$MODULE.signals";
|
||
|
|
||
|
# The file containing Arg information.
|
||
|
my $ARGS_FILE = "$ROOT_DIR/$MODULE.args";
|
||
|
|
||
|
# Set the flag to indicate changes, if requested.
|
||
|
my $CHANGES_FLAG = $FLAG_CHANGES ? "FIXME" : "";
|
||
|
|
||
|
# These global arrays store information on signals. Each signal has an entry
|
||
|
# in each of these arrays at the same index, like a multi-dimensional array.
|
||
|
my @SignalObjects; # The GtkObject which emits the signal.
|
||
|
my @SignalNames; # The signal name.
|
||
|
my @SignalReturns; # The return type.
|
||
|
my @SignalPrototypes; # The rest of the prototype of the signal handler.
|
||
|
|
||
|
# These global arrays store information on Args. Each Arg has an entry
|
||
|
# in each of these arrays at the same index, like a multi-dimensional array.
|
||
|
my @ArgObjects; # The GtkObject which has the Arg.
|
||
|
my @ArgNames; # The Arg name.
|
||
|
my @ArgTypes; # The Arg type - gint, GtkArrowType etc.
|
||
|
my @ArgFlags; # How the Arg can be used - readable/writable etc.
|
||
|
|
||
|
# These global hashes store declaration info keyed on a symbol name.
|
||
|
my %Declarations;
|
||
|
my %DeclarationTypes;
|
||
|
my %DeclarationConditional;
|
||
|
my %DeclarationOutput;
|
||
|
|
||
|
# These global hashes store the existing documentation.
|
||
|
my %SymbolDocs;
|
||
|
my %SymbolTypes;
|
||
|
my %SymbolParams;
|
||
|
|
||
|
# These global arrays store GtkObject and subclasses and the hierarchy.
|
||
|
my @Objects;
|
||
|
my @ObjectLevels;
|
||
|
|
||
|
&ReadSignalsFile ($SIGNALS_FILE);
|
||
|
&ReadArgsFile ($ARGS_FILE);
|
||
|
&ReadObjectHierarchy;
|
||
|
|
||
|
&ReadExistingTemplates;
|
||
|
&BackupExistingTemplates;
|
||
|
&UpdateTemplates ("$ROOT_DIR/$MODULE-sections.txt");
|
||
|
&OutputUnusedTemplates;
|
||
|
&CheckAllDeclarationsOutput;
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ReadExistingTemplates
|
||
|
# Description : This reads in all the existing documentation, into the global
|
||
|
# variables %SymbolDocs, %SymbolTypes, and %SymbolParams (a
|
||
|
# hash of arrays).
|
||
|
# Arguments : none
|
||
|
#############################################################################
|
||
|
|
||
|
sub ReadExistingTemplates {
|
||
|
%SymbolDocs = ();
|
||
|
%SymbolTypes = ();
|
||
|
%SymbolParams = ();
|
||
|
|
||
|
# Read the unused docs first, so they get overridden by any real docs.
|
||
|
# (though this shouldn't happen often).
|
||
|
my $unused_doc = "$TMPL_DIR/$MODULE-unused.sgml";
|
||
|
if (-e $unused_doc) {
|
||
|
&ReadTemplateFile ($unused_doc, 0);
|
||
|
}
|
||
|
|
||
|
while (<$TMPL_DIR/*.sgml>) {
|
||
|
# print "Reading $_\n";
|
||
|
if ($_ eq $unused_doc) {
|
||
|
# print "skipping $unused_doc\n";
|
||
|
} else {
|
||
|
&ReadTemplateFile ($_, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : BackupExistingTemplates
|
||
|
# Description : This moves all existing .sgml to .sgml.bak.
|
||
|
# Arguments : none
|
||
|
#############################################################################
|
||
|
|
||
|
sub BackupExistingTemplates {
|
||
|
while (<$TMPL_DIR/*.sgml>) {
|
||
|
my $backup_file = $_ . ".bak";
|
||
|
# print "Backing up $_ to $backup_file\n";
|
||
|
if (-e $backup_file) {
|
||
|
unlink ($backup_file)
|
||
|
|| die "Can't delete old backup file: $backup_file";
|
||
|
}
|
||
|
rename ($_, $backup_file)
|
||
|
|| die "Can't move $_ to $backup_file";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : UpdateTemplates
|
||
|
# Description : This collects the output for each section of the docs, and
|
||
|
# outputs each file when the end of the section is found.
|
||
|
# Arguments : $file - the file containing the sections of the docs.
|
||
|
#############################################################################
|
||
|
|
||
|
sub UpdateTemplates {
|
||
|
my ($file) = @_;
|
||
|
# print "Reading: $file\n";
|
||
|
|
||
|
open (INPUT, $file)
|
||
|
|| die "Can't open $file";
|
||
|
|
||
|
# Create the top output directory if it doesn't exist.
|
||
|
if (! -e $TMPL_DIR) {
|
||
|
mkdir ("$TMPL_DIR", 0777)
|
||
|
|| die "Can't create directory: $TMPL_DIR";
|
||
|
}
|
||
|
|
||
|
my $title = "";
|
||
|
my $subsection = "";
|
||
|
my $output;
|
||
|
while (<INPUT>) {
|
||
|
if (m/^#/) {
|
||
|
next;
|
||
|
|
||
|
} elsif (m/^<SECTION>/) {
|
||
|
$output = "";
|
||
|
|
||
|
} elsif (m/^<SUBSECTION\s*(.*)>/i) {
|
||
|
$subsection = $1;
|
||
|
next;
|
||
|
|
||
|
} elsif (m/^<TITLE>(.*)<\/TITLE>/) {
|
||
|
$title = $1;
|
||
|
# print "Section: $title\n";
|
||
|
|
||
|
# We don't want warnings if object & class structs aren't used.
|
||
|
# $DeclarationOutput{$title} = 1;
|
||
|
$DeclarationOutput{"${title}Class"} = 1;
|
||
|
|
||
|
} elsif (m/^<FILE>(.*)<\/FILE>/) {
|
||
|
$file = $1;
|
||
|
|
||
|
} elsif (m/^<INCLUDE>(.*)<\/INCLUDE>/) {
|
||
|
next;
|
||
|
|
||
|
} elsif (m/^<\/SECTION>/) {
|
||
|
if ($title eq "") {
|
||
|
$title = $file;
|
||
|
}
|
||
|
# print "End of section: $title\n";
|
||
|
|
||
|
$file =~ s/\s/_/g;
|
||
|
$file .= ".sgml";
|
||
|
|
||
|
&OutputTemplateFile ($file, $title, \$output);
|
||
|
|
||
|
$title = "";
|
||
|
$subsection = "";
|
||
|
|
||
|
} elsif (m/^(\S+)/) {
|
||
|
my $symbol = $1;
|
||
|
# print " Symbol: $symbol\n";
|
||
|
|
||
|
my $declaration = $Declarations{$1};
|
||
|
if (defined ($declaration)) {
|
||
|
# We don't want templates for standard macros/functions of
|
||
|
# GtkObjects or private declarations.
|
||
|
if ($subsection ne "Standard" && $subsection ne "Private") {
|
||
|
$output .= &OutputDeclaration ($DeclarationTypes {$symbol},
|
||
|
$symbol, $declaration);
|
||
|
}
|
||
|
|
||
|
# Note that the declaration has been output.
|
||
|
$DeclarationOutput{$symbol} = 1;
|
||
|
|
||
|
if ($declaration eq '##conditional##') {
|
||
|
# print "Conditional $DeclarationTypes{$symbol}\n";
|
||
|
}
|
||
|
} else {
|
||
|
print "WARNING: No declaration for: $1\n";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
close (INPUT);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : CheckAllDeclarationsOutput
|
||
|
# Description : This steps through all the declarations that were loaded, and
|
||
|
# makes sure that each one has been output, by checking the
|
||
|
# corresponding flag in the %DeclarationOutput hash. It is
|
||
|
# intended to check that any new declarations in new versions
|
||
|
# of GTK/Gnome get added to the $MODULE-sections.txt file.
|
||
|
# Arguments : none
|
||
|
#############################################################################
|
||
|
|
||
|
sub CheckAllDeclarationsOutput {
|
||
|
my $num_unused = 0;
|
||
|
open (UNUSED, ">$ROOT_DIR/$MODULE-unused.txt")
|
||
|
|| die "Can't open $ROOT_DIR/$MODULE-unused.txt";
|
||
|
my ($symbol);
|
||
|
foreach $symbol (keys (%Declarations)) {
|
||
|
if (!defined ($DeclarationOutput{$symbol})) {
|
||
|
print (UNUSED "$symbol\n");
|
||
|
$num_unused++;
|
||
|
}
|
||
|
}
|
||
|
close (UNUSED);
|
||
|
if ($num_unused != 0) {
|
||
|
print <<EOF;
|
||
|
=============================================================================
|
||
|
WARNING: $num_unused unused declarations.
|
||
|
These can be found in $MODULE-unused.txt.
|
||
|
They should be added to $MODULE-sections.txt in the appropriate place.
|
||
|
=============================================================================
|
||
|
EOF
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : OutputDeclaration
|
||
|
# Description : This returns the template for one symbol & declaration.
|
||
|
# Note that it uses the global %SymbolDocs and %SymbolParams to
|
||
|
# lookup any existing documentation.
|
||
|
# Arguments : $type - the type of the symbol ('FUNCTION'/'MACRO' etc.)
|
||
|
# $symbol - the symbol name.
|
||
|
# $declaration - the declaration of the symbol.
|
||
|
#############################################################################
|
||
|
|
||
|
sub OutputDeclaration {
|
||
|
my ($type, $symbol, $declaration) = @_;
|
||
|
my ($output) = "";
|
||
|
|
||
|
# print "Outputting $type: $symbol\n";
|
||
|
|
||
|
# See if symbol already has a description.
|
||
|
my ($symbol_desc) = $SymbolDocs{$symbol};
|
||
|
my ($template_exists);
|
||
|
if (defined ($symbol_desc)) {
|
||
|
$template_exists = 1;
|
||
|
$symbol_desc =~ s/\s+$//;
|
||
|
} else {
|
||
|
$template_exists = 0;
|
||
|
$symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
|
||
|
}
|
||
|
|
||
|
$output .= <<EOF;
|
||
|
<!-- ##### $type $symbol ##### -->
|
||
|
$symbol_desc
|
||
|
|
||
|
EOF
|
||
|
|
||
|
# For functions, function typedefs and macros, we output the arguments.
|
||
|
# For functions and function typedefs we also output the return value.
|
||
|
if ($type eq "FUNCTION" || $type eq "USER_FUNCTION") {
|
||
|
# Take out the return type
|
||
|
$declaration =~ s/<RETURNS>\s*(const\s+|unsigned\s+)*(\w+)\s*(\**)\s*<\/RETURNS>\n//;
|
||
|
my ($ret_type) = $2;
|
||
|
|
||
|
my ($param_num) = 0;
|
||
|
my ($name);
|
||
|
while ($declaration ne "") {
|
||
|
if ($declaration =~ s/^[\s,]+//) {
|
||
|
# skip whitespace and commas
|
||
|
next;
|
||
|
|
||
|
} elsif ($declaration =~ s/^void\s*[,\n]//) {
|
||
|
if ($param_num != 0) {
|
||
|
print "WARNING: void used as parameter in function $symbol\n";
|
||
|
}
|
||
|
|
||
|
} elsif ($declaration =~ s/^...\s*[,\n]//) {
|
||
|
$output .= &OutputParam ($symbol, "Varargs",
|
||
|
$template_exists, 1, "");
|
||
|
|
||
|
# Try to match a standard parameter.
|
||
|
} elsif ($declaration =~ s/^(const\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(const\s+)?(\**)?\s*(\w+)?\s*(\[\d*\])?\s*[,\n]//) {
|
||
|
if (defined ($7)) {
|
||
|
$name = $7;
|
||
|
} else {
|
||
|
$name = "Param" . ($param_num + 1);
|
||
|
}
|
||
|
$output .= &OutputParam ($symbol, $name, $template_exists, 1,
|
||
|
"");
|
||
|
|
||
|
# Try to match parameters which are functions.
|
||
|
} elsif ($declaration =~ s/^(const\s+|unsigned\s+)*(struct\s+)?(\w+)\s*(\**)\s*(const\s+)?\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*[,\n]//) {
|
||
|
$name = $6;
|
||
|
$output .= &OutputParam ($symbol, $name, $template_exists, 1,
|
||
|
"");
|
||
|
|
||
|
} else {
|
||
|
print "###Can't parse args for function $symbol: $declaration\n";
|
||
|
last;
|
||
|
}
|
||
|
$param_num++;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ($ret_type ne "void") {
|
||
|
$output .= &OutputParam ($symbol, "Returns", $template_exists, 1,
|
||
|
"");
|
||
|
}
|
||
|
$output .= &OutputOldParams ($symbol);
|
||
|
$output .= "\n";
|
||
|
}
|
||
|
|
||
|
if ($type eq "MACRO") {
|
||
|
if ($declaration =~ m/^\s*#\s*define\s+\w+\(([^\)]*)\)/) {
|
||
|
my ($param);
|
||
|
foreach $param (split (/,/, $1)) {
|
||
|
$param =~ s/^\s+//;
|
||
|
$param =~ s/\s*$//;
|
||
|
if ($param =~ m/\S/) {
|
||
|
$output .= &OutputParam ($symbol, $param, $template_exists,
|
||
|
1, "");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$output .= &OutputParam ($symbol, "Returns", $template_exists, 0, "");
|
||
|
$output .= &OutputOldParams ($symbol);
|
||
|
$output .= "\n";
|
||
|
}
|
||
|
|
||
|
if ($type eq "STRUCT") {
|
||
|
my $is_object_struct = CheckIsObject ($symbol);
|
||
|
my @fields = ParseStructDeclaration($declaration, $is_object_struct);
|
||
|
|
||
|
for (my $i = 0; $i <= $#fields; $i += 2) {
|
||
|
my $field_name = $fields[$i];
|
||
|
$output .= &OutputParam ($symbol, $field_name, $template_exists, 1, "");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($type eq "ENUM") {
|
||
|
my @members = ParseEnumDeclaration($declaration);
|
||
|
|
||
|
for my $member (@members) {
|
||
|
$output .= &OutputParam ($symbol, $member, $template_exists, 1, "");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$output .= "\n";
|
||
|
|
||
|
# Remove the used docs from the hashes.
|
||
|
if ($template_exists) {
|
||
|
delete $SymbolDocs{$symbol};
|
||
|
delete $SymbolParams{$symbol};
|
||
|
}
|
||
|
|
||
|
return $output;
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : OutputParam
|
||
|
# Description : This outputs the part of a template for one parameter.
|
||
|
# It first checks if the parameter is already described, and if
|
||
|
# so it uses that description, and clears it so it isn't output
|
||
|
# as an old param.
|
||
|
# Arguments : $symbol - the symbol (function or macro) name.
|
||
|
# $param_to_output - the parameter to add.
|
||
|
# $template_exists - TRUE if the template already existed in
|
||
|
# template files. If it did, then we will flag any changes
|
||
|
# with 'FIXME'.
|
||
|
# $force_output - TRUE if the parameter should be output even
|
||
|
# if it didn't already exist in the template. (The return
|
||
|
# values of macros are added manually if required, and so we
|
||
|
# never add it here - we only copy it if it already exists.)
|
||
|
# $default_description - the default description of the
|
||
|
# parameter to be used if it doesn't already exist. (Signal
|
||
|
# handlers have a few common parameters.)
|
||
|
#############################################################################
|
||
|
|
||
|
sub OutputParam {
|
||
|
my ($symbol, $param_to_output, $template_exists,
|
||
|
$force_output, $default_description) = @_;
|
||
|
my ($j);
|
||
|
|
||
|
my ($params) = $SymbolParams{$symbol};
|
||
|
if (defined ($params)) {
|
||
|
for ($j = 0; $j <= $#$params; $j += 2) {
|
||
|
my $param_name = $$params[$j];
|
||
|
my $param_desc = $$params[$j + 1];
|
||
|
|
||
|
if ($param_name eq $param_to_output) {
|
||
|
$param_desc =~ s/\s+$//;
|
||
|
$$params[$j] = "";
|
||
|
$$params[$j + 1] = "";
|
||
|
return "\@$param_name: $param_desc\n";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# If the template was already in a file, flag the new parameter.
|
||
|
# If not, the template itself will be flagged, so we don't need to flag
|
||
|
# all the new parameters as well.
|
||
|
if ($force_output) {
|
||
|
if ($default_description ne "") {
|
||
|
$default_description =~ s/\s+$//;
|
||
|
return "\@$param_to_output: $default_description\n";
|
||
|
} else {
|
||
|
if ($template_exists) {
|
||
|
return "\@$param_to_output: $CHANGES_FLAG\n";
|
||
|
} else {
|
||
|
return "\@$param_to_output: \n";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : OutputOldParams
|
||
|
# Description : This returns all the existing documentation for parameters of
|
||
|
# the given function/macro/signal symbol which are unused, with
|
||
|
# a comment before them.
|
||
|
# Arguments : $symbol - the symbol (function/macro/signal) name.
|
||
|
#############################################################################
|
||
|
|
||
|
sub OutputOldParams {
|
||
|
my ($symbol) = @_;
|
||
|
my $output = "";
|
||
|
|
||
|
my ($params) = $SymbolParams{$symbol};
|
||
|
if (defined ($params)) {
|
||
|
my $j;
|
||
|
for ($j = 0; $j <= $#$params; $j += 2) {
|
||
|
my $param_name = $$params[$j];
|
||
|
my $param_desc = $$params[$j + 1];
|
||
|
|
||
|
if ($param_name ne "") {
|
||
|
$param_desc =~ s/\s+$//;
|
||
|
$output .= "\@$param_name: $param_desc\n";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ($output) {
|
||
|
$output = "<!-- # Unused Parameters # -->\n" . $output;
|
||
|
}
|
||
|
return $output;
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : OutputTemplateFile
|
||
|
# Description : This outputs one template file.
|
||
|
# Arguments : $file - the basename of the file to output.
|
||
|
# $title - the title from the $MODULE-sections.txt file. This
|
||
|
# will be overridden by any title given in the template file.
|
||
|
# $output - reference to the templates to output.
|
||
|
#############################################################################
|
||
|
|
||
|
sub OutputTemplateFile {
|
||
|
my ($file, $title, $output) = @_;
|
||
|
|
||
|
my ($short_desc, $long_desc, $see_also);
|
||
|
|
||
|
if (defined ($SymbolDocs{"$TMPL_DIR/$file:Title"})) {
|
||
|
$title = $SymbolDocs{"$TMPL_DIR/$file:Title"};
|
||
|
delete $SymbolDocs{"$TMPL_DIR/$file:Title"};
|
||
|
}
|
||
|
if (defined ($SymbolDocs{"$TMPL_DIR/$file:Short_Description"})) {
|
||
|
$short_desc = $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
|
||
|
delete $SymbolDocs{"$TMPL_DIR/$file:Short_Description"};
|
||
|
} else {
|
||
|
$short_desc = "";
|
||
|
}
|
||
|
if (defined ($SymbolDocs{"$TMPL_DIR/$file:Long_Description"})) {
|
||
|
$long_desc = $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
|
||
|
delete $SymbolDocs{"$TMPL_DIR/$file:Long_Description"};
|
||
|
} else {
|
||
|
$long_desc = "<para>\n\n</para>\n";
|
||
|
}
|
||
|
if (defined ($SymbolDocs{"$TMPL_DIR/$file:See_Also"})) {
|
||
|
$see_also = $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
|
||
|
delete $SymbolDocs{"$TMPL_DIR/$file:See_Also"};
|
||
|
} else {
|
||
|
$see_also = "<para>\n\n</para>\n";
|
||
|
}
|
||
|
|
||
|
open (OUTPUT, ">$TMPL_DIR/$file")
|
||
|
|| die "Can't create $TMPL_DIR/$file";
|
||
|
|
||
|
print (OUTPUT <<EOF);
|
||
|
<!-- ##### SECTION Title ##### -->
|
||
|
$title
|
||
|
|
||
|
<!-- ##### SECTION Short_Description ##### -->
|
||
|
$short_desc
|
||
|
|
||
|
<!-- ##### SECTION Long_Description ##### -->
|
||
|
$long_desc
|
||
|
|
||
|
<!-- ##### SECTION See_Also ##### -->
|
||
|
$see_also
|
||
|
|
||
|
EOF
|
||
|
|
||
|
print (OUTPUT $$output);
|
||
|
&OutputSignalTemplates ($title);
|
||
|
&OutputArgTemplates ($title);
|
||
|
close (OUTPUT);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : OutputSignalTemplates
|
||
|
# Description : Outputs templates for signal handlers.
|
||
|
# Arguments : $title - the title from the $MODULE-sections.txt file. If the
|
||
|
# file is describing a GtkObject subclass, the title should
|
||
|
# be the name of the class, e.g. 'GtkButton'.
|
||
|
#############################################################################
|
||
|
|
||
|
sub OutputSignalTemplates {
|
||
|
my ($title) = @_;
|
||
|
|
||
|
my $output = "";
|
||
|
my ($i, $template_exists);
|
||
|
for ($i = 0; $i <= $#SignalObjects; $i++) {
|
||
|
if ($SignalObjects[$i] eq $title) {
|
||
|
# print "Found signal: $SignalObjects[$i]\n";
|
||
|
my ($symbol) = "$SignalObjects[$i]::$SignalNames[$i]";
|
||
|
|
||
|
# See if symbol already has a description.
|
||
|
my ($symbol_desc) = $SymbolDocs{$symbol};
|
||
|
if (defined ($symbol_desc)) {
|
||
|
$template_exists = 1;
|
||
|
$symbol_desc =~ s/\s+$//;
|
||
|
delete $SymbolDocs{$symbol};
|
||
|
} else {
|
||
|
$template_exists = 0;
|
||
|
$symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
|
||
|
}
|
||
|
|
||
|
$output .= <<EOF;
|
||
|
<!-- ##### SIGNAL $symbol ##### -->
|
||
|
$symbol_desc
|
||
|
|
||
|
EOF
|
||
|
|
||
|
my @params = split ("[,\n]", $SignalPrototypes[$i]);
|
||
|
my ($j, $name);
|
||
|
for ($j = 0; $j <= $#params; $j++) {
|
||
|
my $param = $params[$j];
|
||
|
$param =~ s/^\s+//;
|
||
|
$param =~ s/\s*$//;
|
||
|
if ($param =~ m/^\s*$/) { next; }
|
||
|
if ($param =~ m/^void$/) { next; }
|
||
|
|
||
|
if ($param =~ m/^\s*(\w+)\s*(\**)\s*([\w\[\]]+)?\s*$/) {
|
||
|
if (defined($3)) {
|
||
|
$name = $3;
|
||
|
} else {
|
||
|
$name = "Param" . ($j + 1);
|
||
|
}
|
||
|
if ($j == 0) {
|
||
|
$output .= &OutputParam ($symbol, $name,
|
||
|
$template_exists, 1,
|
||
|
"the object which received the signal.");
|
||
|
} else {
|
||
|
$output .= &OutputParam ($symbol, $name,
|
||
|
$template_exists, 1, "");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($SignalReturns[$i] ne "void") {
|
||
|
$output .= &OutputParam ($symbol, "Returns", $template_exists,
|
||
|
1, "");
|
||
|
}
|
||
|
$output .= &OutputOldParams ($symbol);
|
||
|
$output .= "\n";
|
||
|
}
|
||
|
}
|
||
|
print (OUTPUT $output);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : OutputArgTemplates
|
||
|
# Description : Outputs templates for Args.
|
||
|
# Arguments : $title - the title from the $MODULE-sections.txt file. If the
|
||
|
# file is describing a GtkObject subclass, the title should
|
||
|
# be the name of the class, e.g. 'GtkButton'.
|
||
|
#############################################################################
|
||
|
|
||
|
sub OutputArgTemplates {
|
||
|
my ($title) = @_;
|
||
|
|
||
|
my $output = "";
|
||
|
my $i;
|
||
|
for ($i = 0; $i <= $#ArgObjects; $i++) {
|
||
|
if ($ArgObjects[$i] eq $title) {
|
||
|
# print "Found arg: $ArgObjects[$i]\n";
|
||
|
# I've only used one colon so we don't clash with signals.
|
||
|
my ($symbol) = "$ArgObjects[$i]:$ArgNames[$i]";
|
||
|
|
||
|
# See if symbol already has a description.
|
||
|
my ($symbol_desc) = $SymbolDocs{$symbol};
|
||
|
if (defined ($symbol_desc)) {
|
||
|
delete $SymbolDocs{$symbol};
|
||
|
$symbol_desc =~ s/\s+$//;
|
||
|
} else {
|
||
|
$symbol_desc = "<para>\n$CHANGES_FLAG\n</para>";
|
||
|
}
|
||
|
|
||
|
$output .= <<EOF;
|
||
|
<!-- ##### ARG $symbol ##### -->
|
||
|
$symbol_desc
|
||
|
|
||
|
EOF
|
||
|
}
|
||
|
}
|
||
|
print (OUTPUT $output);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : OutputUnusedTemplates
|
||
|
# Description : This saves any unused documentation into $MODULE-unused.sgml.
|
||
|
# Arguments : none
|
||
|
#############################################################################
|
||
|
|
||
|
sub OutputUnusedTemplates {
|
||
|
my ($unused_file) = "$TMPL_DIR/$MODULE-unused.sgml";
|
||
|
open (UNUSED, ">$unused_file")
|
||
|
|| die "Can't open file: $unused_file";
|
||
|
|
||
|
my $output = "";
|
||
|
my ($symbol, $symbol_desc);
|
||
|
while (($symbol, $symbol_desc) = each (%SymbolDocs)) {
|
||
|
# print "Unused: $symbol\n";
|
||
|
|
||
|
my $type = $SymbolTypes{$symbol};
|
||
|
if (!defined ($type)) {
|
||
|
$type = "UNKNOWN";
|
||
|
print "WARNING: Unused symbol $symbol has unknown type\n";
|
||
|
}
|
||
|
|
||
|
$output .= <<EOF;
|
||
|
<!-- ##### $type $symbol ##### -->
|
||
|
$symbol_desc
|
||
|
|
||
|
EOF
|
||
|
|
||
|
my ($params) = $SymbolParams{$symbol};
|
||
|
if (defined ($params)) {
|
||
|
my $j;
|
||
|
for ($j = 0; $j <= $#$params; $j += 2) {
|
||
|
my $param_name = $$params[$j];
|
||
|
my $param_desc = $$params[$j + 1];
|
||
|
$param_desc =~ s/\s+$//;
|
||
|
$output .= "\@$param_name: $param_desc\n";
|
||
|
}
|
||
|
}
|
||
|
$output .= "\n";
|
||
|
}
|
||
|
|
||
|
print UNUSED $output;
|
||
|
close (UNUSED);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# LIBRARY FUNCTIONS - These functions are used in both gtkdoc-mkdb and
|
||
|
# gtkdoc-mktmpl and should eventually be moved to a
|
||
|
# separate library.
|
||
|
#############################################################################
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ReadDeclarationsFile
|
||
|
# Description : This reads in a file containing the function/macro/enum etc.
|
||
|
# declarations.
|
||
|
#
|
||
|
# Note that in some cases there are several declarations with
|
||
|
# the same name, e.g. for conditional macros. In this case we
|
||
|
# set a flag in the %DeclarationConditional hash so the
|
||
|
# declaration is not shown in the docs.
|
||
|
#
|
||
|
# If a macro and a function have the same name, e.g. for
|
||
|
# gtk_object_ref, the function declaration takes precedence.
|
||
|
#
|
||
|
# Some opaque structs are just declared with 'typedef struct
|
||
|
# _name name;' in which case the declaration may be empty.
|
||
|
# The structure may have been found later in the header, so
|
||
|
# that overrides the empty declaration.
|
||
|
#
|
||
|
# Arguments : $file - the declarations file to read
|
||
|
# $override - if declarations in this file should override
|
||
|
# any current declaration.
|
||
|
#############################################################################
|
||
|
|
||
|
sub ReadDeclarationsFile {
|
||
|
my ($file, $override) = @_;
|
||
|
|
||
|
if ($override == 0) {
|
||
|
%Declarations = ();
|
||
|
%DeclarationTypes = ();
|
||
|
%DeclarationConditional = ();
|
||
|
%DeclarationOutput = ();
|
||
|
}
|
||
|
|
||
|
open (INPUT, $file)
|
||
|
|| die "Can't open $file";
|
||
|
my $declaration_type = "";
|
||
|
my $declaration_name;
|
||
|
my $declaration;
|
||
|
while (<INPUT>) {
|
||
|
if (!$declaration_type) {
|
||
|
if (m/^<([^>]+)>/) {
|
||
|
$declaration_type = $1;
|
||
|
$declaration_name = "";
|
||
|
# print "Found declaration: $declaration_type\n";
|
||
|
$declaration = "";
|
||
|
}
|
||
|
} else {
|
||
|
if (m%^<NAME>(.*)</NAME>%) {
|
||
|
$declaration_name = $1;
|
||
|
} elsif (m%^</$declaration_type>%) {
|
||
|
# print "Found end of declaration: $declaration_name\n";
|
||
|
# Check that the declaration has a name
|
||
|
if ($declaration_name eq "") {
|
||
|
print "ERROR: $declaration_type has no name $file:$.\n";
|
||
|
}
|
||
|
|
||
|
# Check if the symbol is already defined.
|
||
|
if (defined ($Declarations{$declaration_name})
|
||
|
&& $override == 0) {
|
||
|
# Function declarations take precedence.
|
||
|
if ($DeclarationTypes{$declaration_name} eq 'FUNCTION') {
|
||
|
# Ignore it.
|
||
|
} elsif ($declaration_type eq 'FUNCTION') {
|
||
|
$Declarations{$declaration_name} = $declaration;
|
||
|
$DeclarationTypes{$declaration_name} = $declaration_type;
|
||
|
} elsif ($DeclarationTypes{$declaration_name}
|
||
|
eq $declaration_type) {
|
||
|
# If the existing declaration is empty override it.
|
||
|
if ($declaration_type eq 'STRUCT') {
|
||
|
if ($Declarations{$declaration_name} =~ m/^\s*$/) {
|
||
|
$Declarations{$declaration_name} = $declaration;
|
||
|
} elsif ($declaration =~ m/^\s*$/) {
|
||
|
# Ignore an empty declaration.
|
||
|
} else {
|
||
|
print "WARNING: Structure has multiple definitions: $declaration_name\n";
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
# set flag in %DeclarationConditional hash for
|
||
|
# multiply defined macros/typedefs.
|
||
|
$DeclarationConditional{$declaration_name} = 1;
|
||
|
}
|
||
|
} else {
|
||
|
print "WARNING: $declaration_name has multiple definitions\n";
|
||
|
}
|
||
|
} else {
|
||
|
$Declarations{$declaration_name} = $declaration;
|
||
|
$DeclarationTypes{$declaration_name} = $declaration_type;
|
||
|
}
|
||
|
$declaration_type = "";
|
||
|
} else {
|
||
|
$declaration .= $_;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
close (INPUT);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ReadSignalsFile
|
||
|
# Description : This reads in an existing file which contains information on
|
||
|
# all GTK signals. It creates the arrays @SignalNames and
|
||
|
# @SignalPrototypes containing info on the signals. The first
|
||
|
# line of the SignalPrototype is the return type of the signal
|
||
|
# handler. The remaining lines are the parameters passed to it.
|
||
|
# The last parameter, "gpointer user_data" is always the same
|
||
|
# so is not included.
|
||
|
# Arguments : $file - the file containing the signal handler prototype
|
||
|
# information.
|
||
|
#############################################################################
|
||
|
|
||
|
sub ReadSignalsFile {
|
||
|
my ($file) = @_;
|
||
|
|
||
|
my $in_signal = 0;
|
||
|
my $signal_object;
|
||
|
my $signal_name;
|
||
|
my $signal_returns;
|
||
|
my $signal_prototype;
|
||
|
|
||
|
# Reset the signal info.
|
||
|
@SignalObjects = ();
|
||
|
@SignalNames = ();
|
||
|
@SignalReturns = ();
|
||
|
@SignalPrototypes = ();
|
||
|
|
||
|
if (! -f $file) {
|
||
|
return;
|
||
|
}
|
||
|
if (!open (INPUT, $file)) {
|
||
|
warn "Can't open $file - skipping signals\n";
|
||
|
return;
|
||
|
}
|
||
|
while (<INPUT>) {
|
||
|
if (!$in_signal) {
|
||
|
if (m/^<SIGNAL>/) {
|
||
|
$in_signal = 1;
|
||
|
$signal_object = "";
|
||
|
$signal_name = "";
|
||
|
$signal_returns = "";
|
||
|
$signal_prototype = "";
|
||
|
}
|
||
|
} else {
|
||
|
if (m/^<NAME>(.*)<\/NAME>/) {
|
||
|
$signal_name = $1;
|
||
|
if ($signal_name =~ m/^(.*)::(.*)$/) {
|
||
|
$signal_object = $1;
|
||
|
$signal_name = $2;
|
||
|
# print "Found signal: $signal_name\n";
|
||
|
} else {
|
||
|
print "Invalid signal name: $signal_name\n";
|
||
|
}
|
||
|
} elsif (m/^<RETURNS>(.*)<\/RETURNS>/) {
|
||
|
$signal_returns = $1;
|
||
|
} elsif (m%^</SIGNAL>%) {
|
||
|
# print "Found end of signal: ${signal_object}::${signal_name}\nReturns: ${signal_returns}\n${signal_prototype}";
|
||
|
push (@SignalObjects, $signal_object);
|
||
|
push (@SignalNames, $signal_name);
|
||
|
push (@SignalReturns, $signal_returns);
|
||
|
push (@SignalPrototypes, $signal_prototype);
|
||
|
$in_signal = 0;
|
||
|
} else {
|
||
|
$signal_prototype .= $_;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
close (INPUT);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ReadTemplateFile
|
||
|
# Description : This reads in the manually-edited documentation file
|
||
|
# corresponding to the file currently being created, so we can
|
||
|
# insert the documentation at the appropriate places.
|
||
|
# It outputs %SymbolTypes, %SymbolDocs and %SymbolParams, which
|
||
|
# is a hash of arrays.
|
||
|
# NOTE: This function is duplicated in gtkdoc-mkdb (but
|
||
|
# slightly different).
|
||
|
# Arguments : $docsfile - the template file to read in.
|
||
|
# $skip_unused_params - 1 if the unused parameters should be
|
||
|
# skipped.
|
||
|
#############################################################################
|
||
|
|
||
|
sub ReadTemplateFile {
|
||
|
my ($docsfile, $skip_unused_params) = @_;
|
||
|
|
||
|
# print "Reading $docsfile\n";
|
||
|
if (! -f $docsfile) {
|
||
|
print "File doesn't exist: $docsfile\n";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
my $CurrentType = ""; # Type of symbol being read.
|
||
|
my $CurrentSymbol = ""; # Name of symbol being read.
|
||
|
my $SymbolDoc = ""; # Description of symbol being read.
|
||
|
my @Params; # Parameter names and descriptions of current
|
||
|
# function/macro/function typedef.
|
||
|
my $CurrentParam = -1; # Index of parameter currently being read.
|
||
|
# Note that the param array contains pairs
|
||
|
# of param name & description.
|
||
|
my $InUnusedParameters = 0; # True if we are reading in the unused params.
|
||
|
|
||
|
open (DOCS, $docsfile)
|
||
|
|| die "Can't open file $docsfile: $!";
|
||
|
while (<DOCS>) {
|
||
|
if (m/^<!-- ##### ([A-Z_]+) (\S+) ##### -->/) {
|
||
|
my $type = $1;
|
||
|
my $symbol = $2;
|
||
|
if ($symbol eq "Title"
|
||
|
|| $symbol eq "Short_Description"
|
||
|
|| $symbol eq "Long_Description"
|
||
|
|| $symbol eq "See_Also") {
|
||
|
$symbol = $docsfile . ":" . $symbol;
|
||
|
# print "Found symbol: $symbol\n";
|
||
|
}
|
||
|
|
||
|
# Store previous symbol, but remove any trailing blank lines.
|
||
|
if ($CurrentSymbol ne "") {
|
||
|
$SymbolDoc =~ s/\s+$//;
|
||
|
$SymbolTypes{$CurrentSymbol} = $CurrentType;
|
||
|
$SymbolDocs{$CurrentSymbol} = $SymbolDoc;
|
||
|
if ($CurrentParam >= 0) {
|
||
|
$SymbolParams{$CurrentSymbol} = [ @Params ];
|
||
|
} else {
|
||
|
# Delete any existing params in case we are overriding a
|
||
|
# previously read template.
|
||
|
delete $SymbolParams{$CurrentSymbol};
|
||
|
}
|
||
|
}
|
||
|
$CurrentType = $type;
|
||
|
$CurrentSymbol = $symbol;
|
||
|
$CurrentParam = -1;
|
||
|
$InUnusedParameters = 0;
|
||
|
$SymbolDoc = "";
|
||
|
@Params = ();
|
||
|
|
||
|
} elsif (m/^<!-- # Unused Parameters # -->/) {
|
||
|
$InUnusedParameters = 1;
|
||
|
next;
|
||
|
|
||
|
} else {
|
||
|
# Check if param found
|
||
|
if (s/^\@(\S+):\s*//) {
|
||
|
my $param_name = $1;
|
||
|
# Allow variations of 'Returns'
|
||
|
if ($param_name =~ m/^[Rr]eturns?$/) {
|
||
|
$param_name = "Returns";
|
||
|
}
|
||
|
# print "Found param: $param_name\n";
|
||
|
push (@Params, $param_name);
|
||
|
push (@Params, $_);
|
||
|
$CurrentParam += 2;
|
||
|
next;
|
||
|
}
|
||
|
|
||
|
# When outputting the DocBook we skip unused parameters.
|
||
|
if (!$InUnusedParameters || !$skip_unused_params) {
|
||
|
if ($CurrentParam >= 0) {
|
||
|
$Params[$CurrentParam] .= $_;
|
||
|
} else {
|
||
|
$SymbolDoc .= $_;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Remember to finish the current symbol doccs.
|
||
|
if ($CurrentSymbol ne "") {
|
||
|
$SymbolDoc =~ s/\s+$//;
|
||
|
$SymbolTypes{$CurrentSymbol} = $CurrentType;
|
||
|
$SymbolDocs{$CurrentSymbol} = $SymbolDoc;
|
||
|
if ($CurrentParam >= 0) {
|
||
|
$SymbolParams{$CurrentSymbol} = [ @Params ];
|
||
|
} else {
|
||
|
delete $SymbolParams{$CurrentSymbol};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
close (DOCS);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ReadObjectHierarchy
|
||
|
# Description : This reads in the $MODULE-hierarchy.txt file containing all
|
||
|
# the GtkObject subclasses described in this module (and their
|
||
|
# ancestors).
|
||
|
# It places them in the @Objects array, and places their level
|
||
|
# in the widget hierarchy in the @ObjectLevels array, at the
|
||
|
# same index. GtkObject, the root object, has a level of 1.
|
||
|
#
|
||
|
# FIXME: the version in gtkdoc-mkdb also generates tree_index.sgml
|
||
|
# as it goes along, this should be split out into a separate
|
||
|
# function.
|
||
|
#
|
||
|
# Arguments : none
|
||
|
#############################################################################
|
||
|
|
||
|
sub ReadObjectHierarchy {
|
||
|
@Objects = ();
|
||
|
@ObjectLevels = ();
|
||
|
|
||
|
if (! -f $OBJECT_TREE_FILE) {
|
||
|
return;
|
||
|
}
|
||
|
if (!open (INPUT, $OBJECT_TREE_FILE)) {
|
||
|
warn "Can't open $OBJECT_TREE_FILE - skipping object tree\n";
|
||
|
return;
|
||
|
}
|
||
|
while (<INPUT>) {
|
||
|
if (m/\S+/) {
|
||
|
my $object = $&;
|
||
|
my $level = (length($`)) / 2 + 1;
|
||
|
# print ("Level: $level Object: $object\n");
|
||
|
|
||
|
push (@Objects, $object);
|
||
|
push (@ObjectLevels, $level);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
close (INPUT);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ReadArgsFile
|
||
|
# Description : This reads in an existing file which contains information on
|
||
|
# all GTK args. It creates the arrays @ArgObjects, @ArgNames,
|
||
|
# @ArgTypes and @ArgFlags containing info on the args.
|
||
|
# Arguments : $file - the file containing the arg information.
|
||
|
#############################################################################
|
||
|
|
||
|
sub ReadArgsFile {
|
||
|
my ($file) = @_;
|
||
|
|
||
|
my $in_arg = 0;
|
||
|
my $arg_object;
|
||
|
my $arg_name;
|
||
|
my $arg_type;
|
||
|
my $arg_flags;
|
||
|
|
||
|
# Reset the signal info.
|
||
|
@ArgObjects = ();
|
||
|
@ArgNames = ();
|
||
|
@ArgTypes = ();
|
||
|
@ArgFlags = ();
|
||
|
|
||
|
if (! -f $file) {
|
||
|
return;
|
||
|
}
|
||
|
if (!open (INPUT, $file)) {
|
||
|
warn "Can't open $file - skipping args\n";
|
||
|
return;
|
||
|
}
|
||
|
while (<INPUT>) {
|
||
|
if (!$in_arg) {
|
||
|
if (m/^<ARG>/) {
|
||
|
$in_arg = 1;
|
||
|
$arg_object = "";
|
||
|
$arg_name = "";
|
||
|
$arg_type = "";
|
||
|
$arg_flags = "";
|
||
|
}
|
||
|
} else {
|
||
|
if (m/^<NAME>(.*)<\/NAME>/) {
|
||
|
$arg_name = $1;
|
||
|
if ($arg_name =~ m/^(.*)::(.*)$/) {
|
||
|
$arg_object = $1;
|
||
|
$arg_name = $2;
|
||
|
# print "Found arg: $arg_name\n";
|
||
|
} else {
|
||
|
print "Invalid arg name: $arg_name\n";
|
||
|
}
|
||
|
} elsif (m/^<TYPE>(.*)<\/TYPE>/) {
|
||
|
$arg_type = $1;
|
||
|
} elsif (m/^<FLAGS>(.*)<\/FLAGS>/) {
|
||
|
$arg_flags = $1;
|
||
|
} elsif (m%^</ARG>%) {
|
||
|
# print "Found end of arg: ${arg_object}::${arg_name}\n${arg_type} : ${arg_flags}\n";
|
||
|
push (@ArgObjects, $arg_object);
|
||
|
push (@ArgNames, $arg_name);
|
||
|
push (@ArgTypes, $arg_type);
|
||
|
push (@ArgFlags, $arg_flags);
|
||
|
$in_arg = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
close (INPUT);
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : CheckIsObject
|
||
|
# Description : Returns 1 if the given name is a GtkObject or a subclass.
|
||
|
# It uses the global @Objects array.
|
||
|
# Note that the @Objects array only contains classes in the
|
||
|
# current module and their ancestors - not all GTK classes.
|
||
|
# Arguments : $name - the name to check.
|
||
|
#############################################################################
|
||
|
|
||
|
sub CheckIsObject {
|
||
|
my ($name) = @_;
|
||
|
|
||
|
my $object;
|
||
|
foreach $object (@Objects) {
|
||
|
if ($object eq $name) {
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ParseStructDeclaration
|
||
|
# Description : This function takes a structure declaration and
|
||
|
# breaks it into individual type declarations.
|
||
|
# Arguments : $declaration - the declaration to parse
|
||
|
# $is_object - true if this is an object structure
|
||
|
# $typefunc - function reference to apply to type
|
||
|
# $namefunc - function reference to apply to name
|
||
|
#############################################################################
|
||
|
|
||
|
sub ParseStructDeclaration {
|
||
|
my ($declaration, $is_object, $typefunc, $namefunc) = @_;
|
||
|
|
||
|
# Remove all private parts of the declaration
|
||
|
|
||
|
# For objects, assume private
|
||
|
if ($is_object) {
|
||
|
$declaration =~ s!(struct\s+\w*\s*\{)
|
||
|
.*?
|
||
|
(?:/\*\s*<\s*public\s*>\s*\*/|(?=\}))!$1!msgx;
|
||
|
}
|
||
|
|
||
|
$declaration =~ s!\n?[ \t]*/\*\s*<\s*private\s*>\s*\*/
|
||
|
.*?
|
||
|
(?:/\*\s*<\s*public\s*>\s*\*/|(?=\}))!!msgx;
|
||
|
|
||
|
# Remove all other comments;
|
||
|
$declaration =~ s@/\*([^*]+|\*(?!/))*\*/@ @g;
|
||
|
|
||
|
my @result = ();
|
||
|
|
||
|
if ($declaration =~ /^\s*$/) {
|
||
|
return @result;
|
||
|
}
|
||
|
|
||
|
# Prime match after "struct {" declaration
|
||
|
if (!scalar($declaration =~ m/struct\s+\w*\s*\{/msg)) {
|
||
|
die "Structure declaration '$declaration' does not begin with struct [NAME] {\n";
|
||
|
}
|
||
|
|
||
|
# Treat lines in sequence, allowing singly nested anonymous structs
|
||
|
# and unions.
|
||
|
while ($declaration =~ m/\s*([^{;]+(\{[^\}]*\}[^{;]+)?);/msg) {
|
||
|
my $line = $1;
|
||
|
|
||
|
last if $line =~ /^\s*\}\s*\w*\s*$/;
|
||
|
|
||
|
# FIXME: Just ignore nested structs and unions for now
|
||
|
next if $line =~ /{/;
|
||
|
|
||
|
# FIXME: The regexes here are the same as in OutputFunction;
|
||
|
# this functionality should be separated out.
|
||
|
|
||
|
if ($line =~ m/^
|
||
|
(const\s+|unsigned\s+)*(struct\s+)? # mod1
|
||
|
(\w+)\s* # type
|
||
|
(\**)\s* # ptr1
|
||
|
(const\s+)? # mod2
|
||
|
(\**)?\s* # ptr2
|
||
|
(\w+(?:\s*,\s*\w+)*)\s* # name
|
||
|
(?:((?:\[[^\]]*\]\s*)+) | # array
|
||
|
(:\s*\d+))?\s* # bits
|
||
|
$/x) {
|
||
|
my $mod1 = defined($1) ? $1 : "";
|
||
|
if (defined($2)) { $mod1 .= $2; }
|
||
|
my $type = $3;
|
||
|
my $ptr1 = $4;
|
||
|
my $mod2 = defined($5) ? $5 : "";
|
||
|
my $ptr2 = $6;
|
||
|
my $name = $7;
|
||
|
$ptr1 = " " . $ptr1;
|
||
|
my $array = defined($8) ? $8 : "";
|
||
|
my $bits = defined($9) ? " $9" : "";
|
||
|
my $ptype = defined $typefunc ? $typefunc->($type) : $type;
|
||
|
|
||
|
# FIXME:
|
||
|
# As a hack, we allow the "name" to be of the form
|
||
|
# "a, b, c". This isn't the correct C syntax, but
|
||
|
# at least we get "gint16 x, y" right. Such constructs
|
||
|
# should really be completely removed from the source.
|
||
|
# Or we should really try to understand the C syntax
|
||
|
# here...
|
||
|
|
||
|
my @names = split /\s*,\s*/, $name;
|
||
|
for my $n (@names) {
|
||
|
push @result, $n;
|
||
|
if (defined $namefunc) {
|
||
|
$n = $namefunc->($n);
|
||
|
}
|
||
|
push @result, "$mod1$ptype$ptr1$mod2$ptr2$n$array$bits";
|
||
|
}
|
||
|
|
||
|
# Try to match structure members which are functions
|
||
|
} elsif ($line =~ m/^
|
||
|
(const\s+|unsigned\s+)*(struct\s+)? # mod1
|
||
|
(\w+)\s* # type
|
||
|
(\**)\s* # ptr1
|
||
|
(const\s+)? # mod2
|
||
|
\(\s*\*\s*(\w+)\s*\)\s* # name
|
||
|
\(([^)]*)\)\s* # func_params
|
||
|
$/x) {
|
||
|
|
||
|
my $mod1 = defined($1) ? $1 : "";
|
||
|
if (defined($2)) { $mod1 .= $2; }
|
||
|
my $type = $3;
|
||
|
my $ptr1 = $4;
|
||
|
my $mod2 = defined($5) ? $5 : "";
|
||
|
my $name = $6;
|
||
|
my $func_params = $7;
|
||
|
my $ptype = defined $typefunc ? $typefunc->($type) : $type;
|
||
|
my $pname = defined $namefunc ? $namefunc->($name) : $name;
|
||
|
|
||
|
push @result, $name;
|
||
|
push @result, "$mod1$ptype$ptr1$mod2 (*$pname) ($func_params)";
|
||
|
|
||
|
} else {
|
||
|
warn "Cannot parse structure field $line";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return @result;
|
||
|
}
|
||
|
|
||
|
|
||
|
#############################################################################
|
||
|
# Function : ParseEnumDeclaration
|
||
|
# Description : This function takes a enumeration declaration and
|
||
|
# breaks it into individual enum member declarations.
|
||
|
# Arguments : $declaration - the declaration to parse
|
||
|
#############################################################################
|
||
|
|
||
|
sub ParseEnumDeclaration {
|
||
|
my ($declaration, $is_object) = @_;
|
||
|
|
||
|
# Remove comments;
|
||
|
$declaration =~ s@/\*([^*]+|\*(?!/))*\*/@ @g;
|
||
|
|
||
|
my @result = ();
|
||
|
|
||
|
if ($declaration =~ /^\s*$/) {
|
||
|
return @result;
|
||
|
}
|
||
|
|
||
|
# Remove parenthesized expressions (in macros like GTK_BLAH = BLAH(1,3))
|
||
|
# to avoid getting confused by commas they might contain. This
|
||
|
# doesn't handle nested parentheses correctly.
|
||
|
|
||
|
$declaration =~ s/\([^)]*\)//g;
|
||
|
|
||
|
# Prime match after "typedef enum {" declaration
|
||
|
if (!scalar($declaration =~ m/typedef\s+enum\s*\{/msg)) {
|
||
|
die "Enum declaration '$declaration' does not begin with typedef enum {\n";
|
||
|
}
|
||
|
|
||
|
# Treat lines in sequence.
|
||
|
while ($declaration =~ m/\s*([^,\}]+)([,\}])/msg) {
|
||
|
my $line = $1;
|
||
|
my $terminator = $2;
|
||
|
|
||
|
if ($line =~ m/^(\w+)\s*(=.*)?$/msg) {
|
||
|
push @result, $1;
|
||
|
|
||
|
# Special case for GIOCondition, where the values are specified by
|
||
|
# macros which expand to include the equal sign like '=1'.
|
||
|
} elsif ($line =~ m/^(\w+)\s*GLIB_SYSDEF_POLL/msg) {
|
||
|
push @result, $1;
|
||
|
|
||
|
# Special case include of <gdk/gdkcursors.h>, just ignore it
|
||
|
} elsif ($line =~ m/^#include/) {
|
||
|
last;
|
||
|
|
||
|
} else {
|
||
|
warn "Cannot parse enumeration member $line";
|
||
|
}
|
||
|
|
||
|
last if $terminator eq '}';
|
||
|
}
|
||
|
|
||
|
return @result;
|
||
|
}
|