#!/usr/bin/perl -w # # Copyright (C) 2011 Google Inc. All rights reserved. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License # along with this library; see the file COPYING.LIB. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. # use strict; use File::Basename; use Getopt::Long; use Cwd; use IDLParser; my $defines; my $preprocessor; my $verbose; my $idlFilesList; my $idlAttributesFile; my $supplementalDependencyFile; my $supplementalMakefileDeps; GetOptions('defines=s' => \$defines, 'preprocessor=s' => \$preprocessor, 'verbose' => \$verbose, 'idlFilesList=s' => \$idlFilesList, 'idlAttributesFile=s' => \$idlAttributesFile, 'supplementalDependencyFile=s' => \$supplementalDependencyFile, 'supplementalMakefileDeps=s' => \$supplementalMakefileDeps); die('Must specify #define macros using --defines.') unless defined($defines); die('Must specify an output file using --supplementalDependencyFile.') unless defined($supplementalDependencyFile); die('Must specify the file listing all IDLs using --idlFilesList.') unless defined($idlFilesList); if ($verbose) { print "Resolving [Supplemental=XXX] dependencies in all IDL files.\n"; } open FH, "< $idlFilesList" or die "Cannot open $idlFilesList\n"; my @idlFiles = ; chomp(@idlFiles); close FH; # Parse all IDL files. my %documents; my %interfaceNameToIdlFile; my %idlFileToInterfaceName; foreach my $idlFile (@idlFiles) { my $fullPath = Cwd::realpath($idlFile); my $parser = IDLParser->new(!$verbose); $documents{$fullPath} = $parser->Parse($idlFile, $defines, $preprocessor); my $interfaceName = fileparse(basename($idlFile), ".idl"); $interfaceNameToIdlFile{$interfaceName} = $fullPath; $idlFileToInterfaceName{$fullPath} = $interfaceName; } # Runs the IDL attribute checker. my $idlAttributes = loadIDLAttributes($idlAttributesFile); foreach my $idlFile (keys %documents) { checkIDLAttributes($idlAttributes, $documents{$idlFile}, basename($idlFile)); } # Resolves [Supplemental=XXX] dependencies. my %supplementals; foreach my $idlFile (keys %documents) { $supplementals{$idlFile} = []; } foreach my $idlFile (keys %documents) { foreach my $interface (@{$documents{$idlFile}->interfaces}) { if ($interface->extendedAttributes->{"Supplemental"}) { my $targetIdlFile = $interfaceNameToIdlFile{$interface->extendedAttributes->{"Supplemental"}}; push(@{$supplementals{$targetIdlFile}}, $idlFile); # Treats as if this IDL file does not exist. delete $supplementals{$idlFile}; } } } # Outputs the dependency. # The format of a supplemental dependency file: # # DOMWindow.idl P.idl Q.idl R.idl # Document.idl S.idl # Event.idl # ... # # The above indicates that DOMWindow.idl is supplemented by P.idl, Q.idl and R.idl, # Document.idl is supplemented by S.idl, and Event.idl is supplemented by no IDLs. # The IDL that supplements another IDL (e.g. P.idl) never appears in the dependency file. open FH, "> $supplementalDependencyFile" or die "Cannot open $supplementalDependencyFile\n"; foreach my $idlFile (sort keys %supplementals) { print FH $idlFile, " @{$supplementals{$idlFile}}\n"; } close FH; if ($supplementalMakefileDeps) { open MAKE_FH, "> $supplementalMakefileDeps" or die "Cannot open $supplementalMakefileDeps\n"; my @all_dependencies = []; foreach my $idlFile (sort keys %supplementals) { my $basename = $idlFileToInterfaceName{$idlFile}; my @dependencies = map { basename($_) } @{$supplementals{$idlFile}}; print MAKE_FH "JS${basename}.h: @{dependencies}\n"; print MAKE_FH "DOM${basename}.h: @{dependencies}\n"; print MAKE_FH "WebDOM${basename}.h: @{dependencies}\n"; foreach my $dependency (@dependencies) { print MAKE_FH "${dependency}:\n"; } } close MAKE_FH; } sub loadIDLAttributes { my $idlAttributesFile = shift; my %idlAttributes; open FH, "<", $idlAttributesFile or die "Couldn't open $idlAttributesFile: $!"; while (my $line = ) { chomp $line; next if $line =~ /^\s*#/; next if $line =~ /^\s*$/; if ($line =~ /^\s*([^=\s]*)\s*=?\s*(.*)/) { my $name = $1; $idlAttributes{$name} = {}; if ($2) { foreach my $rightValue (split /\|/, $2) { $rightValue =~ s/^\s*|\s*$//g; $rightValue = "VALUE_IS_MISSING" unless $rightValue; $idlAttributes{$name}{$rightValue} = 1; } } else { $idlAttributes{$name}{"VALUE_IS_MISSING"} = 1; } } else { die "The format of " . basename($idlAttributesFile) . " is wrong: line $.\n"; } } close FH; return \%idlAttributes; } sub checkIDLAttributes { my $idlAttributes = shift; my $document = shift; my $idlFile = shift; foreach my $interface (@{$document->interfaces}) { checkIfIDLAttributesExists($idlAttributes, $interface->extendedAttributes, $idlFile); foreach my $attribute (@{$interface->attributes}) { checkIfIDLAttributesExists($idlAttributes, $attribute->signature->extendedAttributes, $idlFile); } foreach my $function (@{$interface->functions}) { checkIfIDLAttributesExists($idlAttributes, $function->signature->extendedAttributes, $idlFile); foreach my $parameter (@{$function->parameters}) { checkIfIDLAttributesExists($idlAttributes, $parameter->extendedAttributes, $idlFile); } } } } sub checkIfIDLAttributesExists { my $idlAttributes = shift; my $extendedAttributes = shift; my $idlFile = shift; my $error; OUTER: for my $name (keys %$extendedAttributes) { if (!exists $idlAttributes->{$name}) { $error = "Unknown IDL attribute [$name] is found at $idlFile."; last OUTER; } if ($idlAttributes->{$name}{"*"}) { next; } for my $rightValue (split /\s*\|\s*/, $extendedAttributes->{$name}) { if (!exists $idlAttributes->{$name}{$rightValue}) { $error = "Unknown IDL attribute [$name=" . $extendedAttributes->{$name} . "] is found at $idlFile."; last OUTER; } } } if ($error) { die "IDL ATTRIBUTE CHECKER ERROR: $error If you want to add a new IDL attribute, you need to add it to WebCore/bindings/scripts/IDLAttributes.txt and add explanations to the WebKit IDL document (https://trac.webkit.org/wiki/WebKitIDL). "; } }