| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 #!/usr/bin/perl -w |  | 
| 2 # |  | 
| 3 # Copyright (C) 2005 Apple Computer, Inc. |  | 
| 4 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com> |  | 
| 5 # |  | 
| 6 # This file is part of WebKit |  | 
| 7 # |  | 
| 8 # This library is free software; you can redistribute it and/or |  | 
| 9 # modify it under the terms of the GNU Library General Public |  | 
| 10 # License as published by the Free Software Foundation; either |  | 
| 11 # version 2 of the License, or (at your option) any later version. |  | 
| 12 # |  | 
| 13 # This library is distributed in the hope that it will be useful, |  | 
| 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of |  | 
| 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU |  | 
| 16 # Library General Public License for more details. |  | 
| 17 # |  | 
| 18 # You should have received a copy of the GNU Library General Public License |  | 
| 19 # along with this library; see the file COPYING.LIB.  If not, write to |  | 
| 20 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |  | 
| 21 # Boston, MA 02110-1301, USA. |  | 
| 22 # |  | 
| 23 |  | 
| 24 use strict; |  | 
| 25 |  | 
| 26 use File::Path; |  | 
| 27 use File::Basename; |  | 
| 28 use Getopt::Long; |  | 
| 29 use Text::ParseWords; |  | 
| 30 use Cwd; |  | 
| 31 |  | 
| 32 use deprecated_idl_parser; |  | 
| 33 use deprecated_code_generator_v8; |  | 
| 34 use deprecated_idl_serializer; |  | 
| 35 |  | 
| 36 my @idlDirectories; |  | 
| 37 my $outputDirectory; |  | 
| 38 my $preprocessor; |  | 
| 39 my $verbose; |  | 
| 40 my $interfaceDependenciesFile; |  | 
| 41 my $additionalIdlFiles; |  | 
| 42 my $idlAttributesFile; |  | 
| 43 my $writeFileOnlyIfChanged; |  | 
| 44 |  | 
| 45 GetOptions('include=s@' => \@idlDirectories, |  | 
| 46            'outputDir=s' => \$outputDirectory, |  | 
| 47            'preprocessor=s' => \$preprocessor, |  | 
| 48            'verbose' => \$verbose, |  | 
| 49            'interfaceDependenciesFile=s' => \$interfaceDependenciesFile, |  | 
| 50            'additionalIdlFiles=s' => \$additionalIdlFiles, |  | 
| 51            'idlAttributesFile=s' => \$idlAttributesFile, |  | 
| 52            'write-file-only-if-changed=s' => \$writeFileOnlyIfChanged); |  | 
| 53 |  | 
| 54 my $targetIdlFile = $ARGV[0]; |  | 
| 55 |  | 
| 56 die('Must specify input file.') unless defined($targetIdlFile); |  | 
| 57 die('Must specify output directory.') unless defined($outputDirectory); |  | 
| 58 |  | 
| 59 $targetIdlFile = Cwd::realpath($targetIdlFile); |  | 
| 60 if ($verbose) { |  | 
| 61     print "$targetIdlFile\n"; |  | 
| 62 } |  | 
| 63 my $targetInterfaceName = fileparse(basename($targetIdlFile), ".idl"); |  | 
| 64 |  | 
| 65 my $idlFound = 0; |  | 
| 66 my @dependencyIdlFiles; |  | 
| 67 if ($interfaceDependenciesFile) { |  | 
| 68     # The format of the interface dependencies file: |  | 
| 69     # |  | 
| 70     # Window.idl P.idl Q.idl R.idl |  | 
| 71     # Document.idl S.idl |  | 
| 72     # Event.idl |  | 
| 73     # ... |  | 
| 74     # |  | 
| 75     # The above indicates that Window.idl depends on P.idl, Q.idl, and R.idl, |  | 
| 76     # Document.idl depends on S.idl, and Event.idl depends on no IDLs. |  | 
| 77     # A dependency IDL file (one that is depended on by another IDL, e.g. P.idl |  | 
| 78     # in the above) does not have its own entry in the dependency file. |  | 
| 79     open FH, "< $interfaceDependenciesFile" or die "Cannot open $interfaceDepend
     enciesFile\n"; |  | 
| 80     while (my $line = <FH>) { |  | 
| 81         my ($idlFile, @followingIdlFiles) = split(/\s+/, $line); |  | 
| 82         if ($idlFile and basename($idlFile) eq basename($targetIdlFile)) { |  | 
| 83             $idlFound = 1; |  | 
| 84             # We sort the dependency IDL files so that the corresponding code is
      generated |  | 
| 85             # in a consistent order. This is important for the bindings tests. |  | 
| 86             @dependencyIdlFiles = sort @followingIdlFiles; |  | 
| 87         } |  | 
| 88     } |  | 
| 89     close FH; |  | 
| 90 |  | 
| 91     # $additionalIdlFiles is list of IDL files which should not be included in |  | 
| 92     # DerivedSources*.cpp (i.e. they are not described in the interface |  | 
| 93     # dependencies file) but should generate .h and .cpp files. |  | 
| 94     if (!$idlFound and $additionalIdlFiles) { |  | 
| 95         my @idlFiles = shellwords($additionalIdlFiles); |  | 
| 96         $idlFound = grep { $_ and basename($_) eq basename($targetIdlFile) } @id
     lFiles; |  | 
| 97     } |  | 
| 98 |  | 
| 99     if (!$idlFound) { |  | 
| 100         # We generate empty .h and .cpp files just to tell build scripts that .h
      and .cpp files are created. |  | 
| 101         generateEmptyHeaderAndCpp($targetInterfaceName, $outputDirectory); |  | 
| 102         exit 0; |  | 
| 103     } |  | 
| 104 } |  | 
| 105 |  | 
| 106 # Parse the target IDL file. |  | 
| 107 my $targetParser = deprecated_idl_parser->new(!$verbose); |  | 
| 108 my $targetDocument = $targetParser->Parse($targetIdlFile, $preprocessor); |  | 
| 109 |  | 
| 110 if ($idlAttributesFile) { |  | 
| 111     my $idlAttributes = loadIDLAttributes($idlAttributesFile); |  | 
| 112     checkIDLAttributes($idlAttributes, $targetDocument, basename($targetIdlFile)
     ); |  | 
| 113 } |  | 
| 114 |  | 
| 115 foreach my $idlFile (@dependencyIdlFiles) { |  | 
| 116     next if $idlFile eq $targetIdlFile; |  | 
| 117 |  | 
| 118     my $interfaceName = fileparse(basename($idlFile), ".idl"); |  | 
| 119     my $parser = deprecated_idl_parser->new(!$verbose); |  | 
| 120     my $document = $parser->Parse($idlFile, $preprocessor); |  | 
| 121 |  | 
| 122     foreach my $interface (@{$document->interfaces}) { |  | 
| 123         if (!$interface->isPartial || $interface->name eq $targetInterfaceName) 
     { |  | 
| 124             my $targetDataNode; |  | 
| 125             foreach my $interface (@{$targetDocument->interfaces}) { |  | 
| 126                 if ($interface->name eq $targetInterfaceName) { |  | 
| 127                     $targetDataNode = $interface; |  | 
| 128                     last; |  | 
| 129                 } |  | 
| 130             } |  | 
| 131             die "Not found an interface ${targetInterfaceName} in ${targetInterf
     aceName}.idl." unless defined $targetDataNode; |  | 
| 132 |  | 
| 133             # Support for attributes of partial interfaces. |  | 
| 134             foreach my $attribute (@{$interface->attributes}) { |  | 
| 135                 # Record that this attribute is implemented by $interfaceName. |  | 
| 136                 $attribute->extendedAttributes->{"ImplementedBy"} = $interfaceNa
     me unless $interface->extendedAttributes->{"LegacyImplementedInBaseClass"}; |  | 
| 137 |  | 
| 138                 # Add interface-wide extended attributes to each attribute. |  | 
| 139                 applyInterfaceExtendedAttributes($interface, $attribute->extende
     dAttributes); |  | 
| 140 |  | 
| 141                 push(@{$targetDataNode->attributes}, $attribute); |  | 
| 142             } |  | 
| 143 |  | 
| 144             # Support for methods of partial interfaces. |  | 
| 145             foreach my $function (@{$interface->functions}) { |  | 
| 146                 # Record that this method is implemented by $interfaceName. |  | 
| 147                 $function->extendedAttributes->{"ImplementedBy"} = $interfaceNam
     e unless $interface->extendedAttributes->{"LegacyImplementedInBaseClass"}; |  | 
| 148 |  | 
| 149                 # Add interface-wide extended attributes to each method. |  | 
| 150                 applyInterfaceExtendedAttributes($interface, $function->extended
     Attributes); |  | 
| 151 |  | 
| 152                 push(@{$targetDataNode->functions}, $function); |  | 
| 153             } |  | 
| 154 |  | 
| 155             # Support for constants of partial interfaces. |  | 
| 156             foreach my $constant (@{$interface->constants}) { |  | 
| 157                 # Record that this constant is implemented by $interfaceName. |  | 
| 158                 $constant->extendedAttributes->{"ImplementedBy"} = $interfaceNam
     e unless $interface->extendedAttributes->{"LegacyImplementedInBaseClass"}; |  | 
| 159 |  | 
| 160                 # Add interface-wide extended attributes to each constant. |  | 
| 161                 applyInterfaceExtendedAttributes($interface, $constant->extended
     Attributes); |  | 
| 162 |  | 
| 163                 push(@{$targetDataNode->constants}, $constant); |  | 
| 164             } |  | 
| 165         } else { |  | 
| 166             die "$idlFile is not a dependency of $targetIdlFile. There maybe a b
     ug in the dependency computer (compute_dependencies.py).\n"; |  | 
| 167         } |  | 
| 168     } |  | 
| 169 } |  | 
| 170 |  | 
| 171 # Serialize to and from JSON to ensure Perl and Python parsers are equivalent, |  | 
| 172 # as part of porting compiler to Python. See http://crbug.com/242795 |  | 
| 173 $targetDocument = deserializeJSON(serializeJSON($targetDocument)); |  | 
| 174 |  | 
| 175 # Generate desired output for the target IDL file. |  | 
| 176 my @interfaceIdlFiles = ($targetDocument->fileName(), @dependencyIdlFiles); |  | 
| 177 my $codeGenerator = deprecated_code_generator_v8->new($targetDocument, \@idlDire
     ctories, $preprocessor, $verbose, \@interfaceIdlFiles, $writeFileOnlyIfChanged); |  | 
| 178 my $interfaces = $targetDocument->interfaces; |  | 
| 179 foreach my $interface (@$interfaces) { |  | 
| 180     print "Generating bindings code for IDL interface \"" . $interface->name . "
     \"...\n" if $verbose; |  | 
| 181     $codeGenerator->GenerateInterface($interface); |  | 
| 182     $codeGenerator->WriteData($interface, $outputDirectory); |  | 
| 183 } |  | 
| 184 |  | 
| 185 sub generateEmptyHeaderAndCpp |  | 
| 186 { |  | 
| 187     my ($targetInterfaceName, $outputDirectory) = @_; |  | 
| 188 |  | 
| 189     my $headerName = "V8${targetInterfaceName}.h"; |  | 
| 190     my $cppName = "V8${targetInterfaceName}.cpp"; |  | 
| 191     my $contents = "/* |  | 
| 192     This file is generated just to tell build scripts that $headerName and |  | 
| 193     $cppName are created for ${targetInterfaceName}.idl, and thus |  | 
| 194     prevent the build scripts from trying to generate $headerName and |  | 
| 195     $cppName at every build. This file must not be tried to compile. |  | 
| 196 */ |  | 
| 197 "; |  | 
| 198     open FH, "> ${outputDirectory}/${headerName}" or die "Cannot open $headerNam
     e\n"; |  | 
| 199     print FH $contents; |  | 
| 200     close FH; |  | 
| 201 |  | 
| 202     open FH, "> ${outputDirectory}/${cppName}" or die "Cannot open $cppName\n"; |  | 
| 203     print FH $contents; |  | 
| 204     close FH; |  | 
| 205 } |  | 
| 206 |  | 
| 207 sub loadIDLAttributes |  | 
| 208 { |  | 
| 209     my $idlAttributesFile = shift; |  | 
| 210 |  | 
| 211     my %idlAttributes; |  | 
| 212     open FH, "<", $idlAttributesFile or die "Couldn't open $idlAttributesFile: $
     !"; |  | 
| 213     while (my $line = <FH>) { |  | 
| 214         chomp $line; |  | 
| 215         next if $line =~ /^\s*#/; |  | 
| 216         next if $line =~ /^\s*$/; |  | 
| 217 |  | 
| 218         if ($line =~ /^\s*([^=\s]*)\s*=?\s*(.*)/) { |  | 
| 219             my $name = $1; |  | 
| 220             $idlAttributes{$name} = {}; |  | 
| 221             if ($2) { |  | 
| 222                 foreach my $rightValue (split /\|/, $2) { |  | 
| 223                     $rightValue =~ s/^\s*|\s*$//g; |  | 
| 224                     $rightValue = "VALUE_IS_MISSING" unless $rightValue; |  | 
| 225                     $idlAttributes{$name}{$rightValue} = 1; |  | 
| 226                 } |  | 
| 227             } else { |  | 
| 228                 $idlAttributes{$name}{"VALUE_IS_MISSING"} = 1; |  | 
| 229             } |  | 
| 230         } else { |  | 
| 231             die "The format of " . basename($idlAttributesFile) . " is wrong: li
     ne $.\n"; |  | 
| 232         } |  | 
| 233     } |  | 
| 234     close FH; |  | 
| 235 |  | 
| 236     return \%idlAttributes; |  | 
| 237 } |  | 
| 238 |  | 
| 239 sub checkIDLAttributes |  | 
| 240 { |  | 
| 241     my $idlAttributes = shift; |  | 
| 242     my $document = shift; |  | 
| 243     my $idlFile = shift; |  | 
| 244 |  | 
| 245     foreach my $interface (@{$document->interfaces}) { |  | 
| 246         checkIfIDLAttributesExists($idlAttributes, $interface->extendedAttribute
     s, $idlFile); |  | 
| 247 |  | 
| 248         foreach my $attribute (@{$interface->attributes}) { |  | 
| 249             checkIfIDLAttributesExists($idlAttributes, $attribute->extendedAttri
     butes, $idlFile); |  | 
| 250         } |  | 
| 251 |  | 
| 252         foreach my $function (@{$interface->functions}) { |  | 
| 253             checkIfIDLAttributesExists($idlAttributes, $function->extendedAttrib
     utes, $idlFile); |  | 
| 254             foreach my $parameter (@{$function->parameters}) { |  | 
| 255                 checkIfIDLAttributesExists($idlAttributes, $parameter->extendedA
     ttributes, $idlFile); |  | 
| 256             } |  | 
| 257         } |  | 
| 258     } |  | 
| 259 } |  | 
| 260 |  | 
| 261 sub applyInterfaceExtendedAttributes |  | 
| 262 { |  | 
| 263     my $interface = shift; |  | 
| 264     my $extendedAttributes = shift; |  | 
| 265 |  | 
| 266     foreach my $extendedAttributeName (keys %{$interface->extendedAttributes}) { |  | 
| 267         next if $extendedAttributeName eq "ImplementedAs"; |  | 
| 268         $extendedAttributes->{$extendedAttributeName} = $interface->extendedAttr
     ibutes->{$extendedAttributeName}; |  | 
| 269     } |  | 
| 270 } |  | 
| 271 |  | 
| 272 sub checkIfIDLAttributesExists |  | 
| 273 { |  | 
| 274     my $idlAttributes = shift; |  | 
| 275     my $extendedAttributes = shift; |  | 
| 276     my $idlFile = shift; |  | 
| 277 |  | 
| 278     my $error; |  | 
| 279     OUTER: for my $name (keys %$extendedAttributes) { |  | 
| 280         if (!exists $idlAttributes->{$name}) { |  | 
| 281             $error = "Invalid IDL attribute [$name] found in $idlFile."; |  | 
| 282             last; |  | 
| 283         } |  | 
| 284         # Check no argument first, since "*" means "some argument (not missing)"
     . |  | 
| 285         if ($extendedAttributes->{$name} eq "VALUE_IS_MISSING" and not exists $i
     dlAttributes->{$name}{"VALUE_IS_MISSING"}) { |  | 
| 286             $error = "Missing required argument for IDL attribute [$name] in fil
     e $idlFile."; |  | 
| 287             last; |  | 
| 288         } |  | 
| 289         if (exists $idlAttributes->{$name}{"*"}) { |  | 
| 290             next; |  | 
| 291         } |  | 
| 292         for my $rightValue (split /\s*[|&]\s*/, $extendedAttributes->{$name}) { |  | 
| 293             if (!(exists $idlAttributes->{$name}{$rightValue})) { |  | 
| 294                 $error = "Invalid IDL attribute value [$name=" . $extendedAttrib
     utes->{$name} . "] found in $idlFile."; |  | 
| 295                 last OUTER; |  | 
| 296             } |  | 
| 297         } |  | 
| 298     } |  | 
| 299     if ($error) { |  | 
| 300         die "IDL ATTRIBUTE CHECKER ERROR: $error |  | 
| 301 If you want to add a new IDL attribute, you need to add it to bindings/scripts/I
     DLAttributes.txt and add explanations to the Blink IDL document (http://chromium
     .org/blink/webidl). |  | 
| 302 "; |  | 
| 303     } |  | 
| 304 } |  | 
| OLD | NEW | 
|---|