diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
commit | 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch) | |
tree | 11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/bindings/scripts/CodeGenerator.pm | |
parent | 648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff) | |
download | external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/bindings/scripts/CodeGenerator.pm')
-rw-r--r-- | WebCore/bindings/scripts/CodeGenerator.pm | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/WebCore/bindings/scripts/CodeGenerator.pm b/WebCore/bindings/scripts/CodeGenerator.pm new file mode 100644 index 0000000..7a4d095 --- /dev/null +++ b/WebCore/bindings/scripts/CodeGenerator.pm @@ -0,0 +1,393 @@ +# +# WebKit IDL parser +# +# Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org> +# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> +# Copyright (C) 2007 Apple 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 +# aint 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. +# + +package CodeGenerator; + +my $useDocument = ""; +my $useGenerator = ""; +my $useOutputDir = ""; +my $useDirectories = ""; +my $useLayerOnTop = 0; +my $preprocessor; + +my $codeGenerator = 0; + +my $verbose = 0; + +my %primitiveTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1, + "unsigned int" => 1, "unsigned short" => 1, + "unsigned long" => 1, "unsigned long long" => 1, + "float" => 1, "double" => 1, + "boolean" => 1, "void" => 1); + +my %podTypeHash = ("RGBColor" => 1, "SVGNumber" => 1, "SVGTransform" => 1); +my %podTypesWithWritablePropertiesHash = ("SVGLength" => 1, "SVGMatrix" => 1, "SVGPoint" => 1, "SVGRect" => 1); +my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1); + +my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1, "SVGPaintType" => 1); + +my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, + "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1, + "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1, + "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, + "SVGAnimatedPreserveAspectRatio" => 1, + "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1, + "SVGAnimatedTransformList" => 1); + +# Helpers for 'ScanDirectory' +my $endCondition = 0; +my $foundFilename = ""; +my @foundFilenames = (); +my $ignoreParent = 1; +my $defines = ""; + +# Default constructor +sub new +{ + my $object = shift; + my $reference = { }; + + $useDirectories = shift; + $useGenerator = shift; + $useOutputDir = shift; + $useLayerOnTop = shift; + $preprocessor = shift; + + bless($reference, $object); + return $reference; +} + +sub StripModule($) +{ + my $object = shift; + my $name = shift; + $name =~ s/[a-zA-Z0-9]*:://; + return $name; +} + +sub ProcessDocument +{ + my $object = shift; + $useDocument = shift; + $defines = shift; + + my $ifaceName = "CodeGenerator" . $useGenerator; + + # Dynamically load external code generation perl module + require $ifaceName . ".pm"; + $codeGenerator = $ifaceName->new($object, $useOutputDir, $useLayerOnTop, $preprocessor); + unless (defined($codeGenerator)) { + my $classes = $useDocument->classes; + foreach my $class (@$classes) { + print "Skipping $useGenerator code generation for IDL interface \"" . $class->name . "\".\n" if $verbose; + } + return; + } + + # Start the actual code generation! + $codeGenerator->GenerateModule($useDocument, $defines); + + my $classes = $useDocument->classes; + foreach my $class (@$classes) { + print "Generating $useGenerator bindings code for IDL interface \"" . $class->name . "\"...\n" if $verbose; + $codeGenerator->GenerateInterface($class, $defines); + } + + $codeGenerator->finish(); +} + +sub AddMethodsConstantsAndAttributesFromParentClasses +{ + # For the passed interface, recursively parse all parent + # IDLs in order to find out all inherited properties/methods. + + my $object = shift; + my $dataNode = shift; + + my @parents = @{$dataNode->parents}; + my $parentsMax = @{$dataNode->parents}; + + my $constantsRef = $dataNode->constants; + my $functionsRef = $dataNode->functions; + my $attributesRef = $dataNode->attributes; + + # Exception: For the DOM 'Node' is our topmost baseclass, not EventTargetNode. + return if $parentsMax eq 1 and $parents[0] eq "EventTargetNode"; + + foreach (@{$dataNode->parents}) { + if ($ignoreParent) { + # Ignore first parent class, already handled by the generation itself. + $ignoreParent = 0; + next; + } + + my $interface = $object->StripModule($_); + + # Step #1: Find the IDL file associated with 'interface' + $endCondition = 0; + $foundFilename = ""; + + foreach (@{$useDirectories}) { + $object->ScanDirectory("$interface.idl", $_, $_, 0) if ($foundFilename eq ""); + } + + if ($foundFilename ne "") { + print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interface\"\n" if $verbose; + + # Step #2: Parse the found IDL file (in quiet mode). + my $parser = IDLParser->new(1); + my $document = $parser->Parse($foundFilename, $defines, $preprocessor); + + foreach my $class (@{$document->classes}) { + # Step #3: Enter recursive parent search + AddMethodsConstantsAndAttributesFromParentClasses($object, $class); + + # Step #4: Collect constants & functions & attributes of this parent-class + my $constantsMax = @{$class->constants}; + my $functionsMax = @{$class->functions}; + my $attributesMax = @{$class->attributes}; + + print " | |> -> Inheriting $constantsMax constants, $functionsMax functions, $attributesMax attributes...\n | |>\n" if $verbose; + + # Step #5: Concatenate data + push(@$constantsRef, $_) foreach (@{$class->constants}); + push(@$functionsRef, $_) foreach (@{$class->functions}); + push(@$attributesRef, $_) foreach (@{$class->attributes}); + } + } else { + die("Could NOT find specified parent interface \"$interface\"!\n"); + } + } +} + +sub GetMethodsAndAttributesFromParentClasses +{ + # For the passed interface, recursively parse all parent + # IDLs in order to find out all inherited properties/methods. + + my $object = shift; + my $dataNode = shift; + + my @parents = @{$dataNode->parents}; + + return if @{$dataNode->parents} == 0; + + my @parentList = (); + + foreach (@{$dataNode->parents}) { + my $interface = $object->StripModule($_); + if ($interface eq "EventTargetNode") { + $interface = "Node"; + } + + # Step #1: Find the IDL file associated with 'interface' + $endCondition = 0; + $foundFilename = ""; + + foreach (@{$useDirectories}) { + $object->ScanDirectory("${interface}.idl", $_, $_, 0) if $foundFilename eq ""; + } + + die("Could NOT find specified parent interface \"$interface\"!\n") if $foundFilename eq ""; + + print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interface\"\n" if $verbose; + + # Step #2: Parse the found IDL file (in quiet mode). + my $parser = IDLParser->new(1); + my $document = $parser->Parse($foundFilename, $defines); + + foreach my $class (@{$document->classes}) { + # Step #3: Enter recursive parent search + push(@parentList, GetMethodsAndAttributesFromParentClasses($object, $class)); + + # Step #4: Collect constants & functions & attributes of this parent-class + + # print " | |> -> Inheriting $functionsMax functions amd $attributesMax attributes...\n | |>\n" if $verbose; + my $hash = { + "name" => $class->name, + "functions" => $class->functions, + "attributes" => $class->attributes + }; + + # Step #5: Concatenate data + unshift(@parentList, $hash); + } + } + + return @parentList; +} + +sub ParseInterface +{ + my ($object, $interfaceName) = @_; + + # Step #1: Find the IDL file associated with 'interface' + $endCondition = 0; + $foundFilename = ""; + + foreach (@{$useDirectories}) { + $object->ScanDirectory("${interfaceName}.idl", $_, $_, 0) if $foundFilename eq ""; + } + die "Could NOT find specified parent interface \"$interfaceName\"!\n" if $foundFilename eq ""; + + print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interfaceName\"\n" if $verbose; + + # Step #2: Parse the found IDL file (in quiet mode). + my $parser = IDLParser->new(1); + my $document = $parser->Parse($foundFilename, $defines); + + foreach my $interface (@{$document->classes}) { + return $interface if $interface->name eq $interfaceName; + } + + die "Interface definition not found"; +} + +# Helpers for all CodeGenerator***.pm modules +sub IsPodType +{ + my $object = shift; + my $type = shift; + + return 1 if $podTypeHash{$type}; + return 1 if $podTypesWithWritablePropertiesHash{$type}; + return 0; +} + +sub IsPodTypeWithWriteableProperties +{ + my $object = shift; + my $type = shift; + + return 1 if $podTypesWithWritablePropertiesHash{$type}; + return 0; +} + +sub IsPrimitiveType +{ + my $object = shift; + my $type = shift; + + return 1 if $primitiveTypeHash{$type}; + return 0; +} + +sub IsStringType +{ + my $object = shift; + my $type = shift; + + return 1 if $stringTypeHash{$type}; + return 0; +} + +sub IsNonPointerType +{ + my $object = shift; + my $type = shift; + + return 1 if $nonPointerTypeHash{$type} or $primitiveTypeHash{$type}; + return 0; +} + +sub IsSVGAnimatedType +{ + my $object = shift; + my $type = shift; + + return 1 if $svgAnimatedTypeHash{$type}; + return 0; +} + +# Internal Helper +sub ScanDirectory +{ + my $object = shift; + + my $interface = shift; + my $directory = shift; + my $useDirectory = shift; + my $reportAllFiles = shift; + + return if ($endCondition eq 1) and ($reportAllFiles eq 0); + + my $sourceRoot = $ENV{SOURCE_ROOT}; + my $thisDir = $sourceRoot ? "$sourceRoot/$directory" : $directory; + + if (!opendir(DIR, $thisDir)) { + opendir(DIR, $directory) or die "[ERROR] Can't open directory $thisDir or $directory: \"$!\"\n"; + $thisDir = $directory; + } + + my @names = readdir(DIR) or die "[ERROR] Cant't read directory $thisDir \"$!\"\n"; + closedir(DIR); + + foreach my $name (@names) { + # Skip if we already found the right file or + # if we encounter 'exotic' stuff (ie. '.', '..', '.svn') + next if ($endCondition eq 1) or ($name =~ /^\./); + + # Recurisvely enter directory + if (-d "$thisDir/$name") { + $object->ScanDirectory($interface, "$directory/$name", $useDirectory, $reportAllFiles); + next; + } + + # Check wheter we found the desired file + my $condition = ($name eq $interface); + $condition = 1 if ($interface eq "allidls") and ($name =~ /\.idl$/); + + if ($condition) { + $foundFilename = "$thisDir/$name"; + + if ($reportAllFiles eq 0) { + $endCondition = 1; + } else { + push(@foundFilenames, $foundFilename); + } + } + } +} + +# Uppercase the first letter while respecting WebKit style guidelines. +# E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang. +sub WK_ucfirst +{ + my ($object, $param) = @_; + my $ret = ucfirst($param); + $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/; + return $ret; +} + +# Lowercase the first letter while respecting WebKit style guidelines. +# URL becomes url, but SetURL becomes setURL. +sub WK_lcfirst +{ + my ($object, $param) = @_; + my $ret = lcfirst($param); + $ret =~ s/uRL/url/ if $ret =~ /^uRL/; + $ret =~ s/jS/js/ if $ret =~ /^jS/; + return $ret; +} + +1; |