summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/scripts
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
commit8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch)
tree11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/bindings/scripts
parent648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff)
downloadexternal_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')
-rw-r--r--WebCore/bindings/scripts/CodeGenerator.pm393
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorCOM.pm1313
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorJS.pm1947
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorObjC.pm1731
-rw-r--r--WebCore/bindings/scripts/IDLParser.pm416
-rw-r--r--WebCore/bindings/scripts/IDLStructure.pm107
-rw-r--r--WebCore/bindings/scripts/InFilesParser.pm140
-rwxr-xr-xWebCore/bindings/scripts/generate-bindings.pl69
8 files changed, 6116 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;
diff --git a/WebCore/bindings/scripts/CodeGeneratorCOM.pm b/WebCore/bindings/scripts/CodeGeneratorCOM.pm
new file mode 100644
index 0000000..0c86ef2
--- /dev/null
+++ b/WebCore/bindings/scripts/CodeGeneratorCOM.pm
@@ -0,0 +1,1313 @@
+#
+# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
+# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
+# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
+# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
+# Copyright (C) 2006, 2007, 2008 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+package CodeGeneratorCOM;
+
+use File::stat;
+
+# Global Variables
+my $module = "";
+my $outputDir = "";
+
+my @IDLHeader = ();
+my @IDLContent = ();
+my %IDLIncludes = ();
+my %IDLForwardDeclarations = ();
+my %IDLDontForwardDeclare = ();
+my %IDLImports = ();
+my %IDLDontImport = ();
+
+my @CPPInterfaceHeader = ();
+
+my @CPPHeaderHeader = ();
+my @CPPHeaderContent = ();
+my %CPPHeaderIncludes = ();
+my %CPPHeaderIncludesAngle = ();
+my %CPPHeaderForwardDeclarations = ();
+my %CPPHeaderDontForwardDeclarations = ();
+
+my @CPPImplementationHeader = ();
+my @CPPImplementationContent = ();
+my %CPPImplementationIncludes = ();
+my %CPPImplementationWebCoreIncludes = ();
+my %CPPImplementationIncludesAngle = ();
+my %CPPImplementationDontIncludes = ();
+
+my @additionalInterfaceDefinitions = ();
+
+my $DASHES = "----------------------------------------";
+my $TEMP_PREFIX = "GEN_";
+
+# Hashes
+
+my %includeCorrector = map {($_, 1)} qw{UIEvent KeyboardEvent MouseEvent
+ MutationEvent OverflowEvent WheelEvent};
+
+my %conflictMethod = (
+ # FIXME: Add C language keywords?
+);
+
+# Default License Templates
+my @licenseTemplate = split(/\r/, << "EOF");
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+EOF
+
+# Default constructor
+sub new
+{
+ my $object = shift;
+ my $reference = { };
+
+ $codeGenerator = shift;
+ $outputDir = shift;
+
+ bless($reference, $object);
+ return $reference;
+}
+
+sub finish
+{
+ my $object = shift;
+}
+
+# Params: 'domClass' struct
+sub GenerateInterface
+{
+ my $object = shift;
+ my $dataNode = shift;
+ my $defines = shift;
+
+ my $name = $dataNode->name;
+
+ my $pureInterface = $dataNode->extendedAttributes->{"PureInterface"};
+
+ # Start actual generation..
+ $object->GenerateIDL($dataNode, $pureInterface);
+ if ($pureInterface) {
+ $object->GenerateInterfaceHeader($dataNode);
+ } else {
+ $object->GenerateCPPHeader($dataNode);
+ $object->GenerateCPPImplementation($dataNode);
+ }
+
+ # Write changes.
+ $object->WriteData($name, $pureInterface);
+}
+
+# Params: 'idlDocument' struct
+sub GenerateModule
+{
+ my $object = shift;
+ my $dataNode = shift;
+
+ $module = $dataNode->module;
+}
+
+sub GetInterfaceName
+{
+ my $name = $codeGenerator->StripModule(shift);
+
+ die "GetInterfaceName should only be used on interfaces." if ($codeGenerator->IsStringType($name) or $codeGenerator->IsPrimitiveType($name));
+
+ # special cases
+ return "I" . $TEMP_PREFIX . "DOMAbstractView" if $name eq "DOMWindow";
+ return "I" . $TEMP_PREFIX . $name if $name eq "DOMImplementation" or $name eq "DOMTimeStamp";
+
+ # Default, assume COM type has the same type name as
+ # idl type prefixed with "IDOM".
+ return "I" . $TEMP_PREFIX . "DOM" . $name;
+}
+
+sub GetClassName
+{
+ my $name = $codeGenerator->StripModule(shift);
+
+ # special cases
+ return "BSTR" if $codeGenerator->IsStringType($name);
+ return "BOOL" if $name eq "boolean";
+ return "unsigned" if $name eq "unsigned long";
+ return "int" if $name eq "long";
+ return $name if $codeGenerator->IsPrimitiveType($name);
+ return $TEMP_PREFIX . "DOMAbstractView" if $name eq "DOMWindow";
+ return $TEMP_PREFIX . $name if $name eq "DOMImplementation" or $name eq "DOMTimeStamp";
+
+ # Default, assume COM type has the same type name as
+ # idl type prefixed with "DOM".
+ return $TEMP_PREFIX . "DOM" . $name;
+}
+
+sub GetCOMType
+{
+ my ($type) = @_;
+
+ die "Don't use GetCOMType for string types, use one of In/Out variants instead." if $codeGenerator->IsStringType($type);
+
+ return "BOOL" if $type eq "boolean";
+ return "UINT" if $type eq "unsigned long";
+ return "INT" if $type eq "long";
+ return $type if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp";
+ # return "unsigned short" if $type eq "CompareHow" or $type eq "SVGPaintType";
+
+ return GetInterfaceName($type) . "*";
+}
+
+sub GetCOMTypeIn
+{
+ my ($type) = @_;
+ return "LPCTSTR" if $codeGenerator->IsStringType($type);
+ return GetCOMType($type);
+}
+
+sub GetCOMTypeOut
+{
+ my ($type) = @_;
+ return "BSTR" if $codeGenerator->IsStringType($type);
+ return GetCOMType($type);
+}
+
+sub IDLTypeToImplementationType
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ return "bool" if $type eq "boolean";
+ return "unsigned" if $type eq "unsigned long";
+ return "int" if $type eq "long";
+ return $type if $codeGenerator->IsPrimitiveType($type);
+
+ return "WebCore::String" if $codeGenerator->IsStringType($type);
+ return "WebCore::${type}";
+}
+
+sub StripNamespace
+{
+ my ($type) = @_;
+
+ $type =~ s/^WebCore:://;
+
+ return $type;
+}
+
+sub GetParentInterface
+{
+ my ($dataNode) = @_;
+ return "I" . $TEMP_PREFIX . "DOMObject" if (@{$dataNode->parents} == 0);
+ return "I" . $TEMP_PREFIX . "DOMNode" if $codeGenerator->StripModule($dataNode->parents(0)) eq "EventTargetNode";
+ return GetInterfaceName($codeGenerator->StripModule($dataNode->parents(0)));
+}
+
+sub GetParentClass
+{
+ my ($dataNode) = @_;
+ return $TEMP_PREFIX . "DOMObject" if (@{$dataNode->parents} == 0);
+ return $TEMP_PREFIX . "DOMNode" if $codeGenerator->StripModule($dataNode->parents(0)) eq "EventTargetNode";
+ return GetClassName($codeGenerator->StripModule($dataNode->parents(0)));
+}
+
+sub AddForwardDeclarationsForTypeInIDL
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ return if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type);
+
+ my $interface = GetInterfaceName($type);
+ $IDLForwardDeclarations{$interface} = 1;
+ $IDLImports{$interface} = 1;
+}
+
+sub AddIncludesForTypeInCPPHeader
+{
+ my $type = $codeGenerator->StripModule(shift);
+ my $useAngleBrackets = shift;
+
+ return if $codeGenerator->IsNonPointerType($type);
+
+ # Add special Cases HERE
+
+ if ($type =~ m/^I/) {
+ $type = "WebKit";
+ }
+
+ if ($useAngleBrackets) {
+ $CPPHeaderIncludesAngle{"$type.h"} = 1;
+ return;
+ }
+
+ if ($type eq "GEN_DOMImplementation") {
+ $CPPHeaderIncludes{"GEN_DOMDOMImplementation.h"} = 1;
+ return;
+ }
+
+ if ($type eq "IGEN_DOMImplementation") {
+ $CPPHeaderIncludes{"IGEN_DOMDOMImplementation.h"} = 1;
+ return;
+ }
+
+ $CPPHeaderIncludes{"$type.h"} = 1;
+}
+
+sub AddForwardDeclarationsForTypeInCPPHeader
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ return if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type);
+
+ my $interface = GetInterfaceName($type);
+ $CPPHeaderForwardDeclarations{$interface} = 1;
+}
+
+sub AddIncludesForTypeInCPPImplementation
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ die "Include type not supported!" if $includeCorrector{$type};
+
+ return if $codeGenerator->IsNonPointerType($type);
+
+ if ($codeGenerator->IsStringType($type)) {
+ $CPPImplementationWebCoreIncludes{"AtomicString.h"} = 1;
+ $CPPImplementationWebCoreIncludes{"BString.h"} = 1;
+ $CPPImplementationWebCoreIncludes{"KURL.h"} = 1;
+ return;
+ }
+
+ # Special casing
+ $CPPImplementationWebCoreIncludes{"EventTargetNode.h"} = 1 if $type eq "Node";
+ $CPPImplementationWebCoreIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList";
+ $CPPImplementationWebCoreIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration";
+
+ # Add implementation type
+ $CPPImplementationWebCoreIncludes{StripNamespace(IDLTypeToImplementationType($type)) . ".h"} = 1;
+
+ my $COMClassName = GetClassName($type);
+ $CPPImplementationIncludes{"${COMClassName}.h"} = 1;
+}
+
+sub GetAdditionalInterfaces
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ return ("EventTarget") if $type eq "Node";
+ return ();
+}
+
+sub GenerateIDL
+{
+ my ($object, $dataNode, $pureInterface) = @_;
+
+ my $inInterfaceName = $dataNode->name;
+ my $outInterfaceName = GetInterfaceName($inInterfaceName);
+ my $uuid = $dataNode->extendedAttributes->{"InterfaceUUID"} || die "All classes require an InterfaceUUID extended attribute.";
+
+ my $parentInterfaceName = ($pureInterface) ? "IUnknown" : GetParentInterface($dataNode);
+
+ my $numConstants = @{$dataNode->constants};
+ my $numAttributes = @{$dataNode->attributes};
+ my $numFunctions = @{$dataNode->functions};
+
+ # - Add default header template
+ @IDLHeader = @licenseTemplate;
+ push(@IDLHeader, "\n");
+
+ # - INCLUDES -
+ push(@IDLHeader, "#ifndef DO_NO_IMPORTS\n");
+ push(@IDLHeader, "import \"oaidl.idl\";\n");
+ push(@IDLHeader, "import \"ocidl.idl\";\n");
+ push(@IDLHeader, "#endif\n\n");
+
+ unless ($pureInterface) {
+ push(@IDLHeader, "#ifndef DO_NO_IMPORTS\n");
+ push(@IDLHeader, "import \"${parentInterfaceName}.idl\";\n");
+ push(@IDLHeader, "#endif\n\n");
+
+ $IDLDontForwardDeclare{$outInterfaceName} = 1;
+ $IDLDontImport{$outInterfaceName} = 1;
+ $IDLDontForwardDeclare{$parentInterfaceName} = 1;
+ $IDLDontImport{$parentInterfaceName} = 1;
+ }
+
+ # - Begin
+ # -- Attributes
+ push(@IDLContent, "[\n");
+ push(@IDLContent, " object,\n");
+ push(@IDLContent, " oleautomation,\n");
+ push(@IDLContent, " uuid(" . $uuid . "),\n");
+ push(@IDLContent, " pointer_default(unique)\n");
+ push(@IDLContent, "]\n");
+
+ # -- Interface
+ push(@IDLContent, "interface " . $outInterfaceName . " : " . $parentInterfaceName . "\n");
+ push(@IDLContent, "{\n");
+
+
+ # - FIXME: Add constants.
+
+
+ # - Add attribute getters/setters.
+ if ($numAttributes > 0) {
+ foreach my $attribute (@{$dataNode->attributes}) {
+ my $attributeName = $attribute->signature->name;
+ my $attributeIDLType = $attribute->signature->type;
+ my $attributeTypeIn = GetCOMTypeIn($attributeIDLType);
+ my $attributeTypeOut = GetCOMTypeOut($attributeIDLType);
+ my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
+
+ AddForwardDeclarationsForTypeInIDL($attributeIDLType);
+
+ unless ($attributeIsReadonly) {
+ # Setter
+ my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName);
+ my $setter = " HRESULT " . $setterName . "([in] " . $attributeTypeIn . ");\n";
+ push(@IDLContent, $setter);
+ }
+
+ # Getter
+ my $getter = " HRESULT " . $attributeName . "([out, retval] " . $attributeTypeOut . "*);\n\n";
+ push(@IDLContent, $getter);
+ }
+ }
+
+ # - Add functions.
+ if ($numFunctions > 0) {
+ foreach my $function (@{$dataNode->functions}) {
+ my $functionName = $function->signature->name;
+ my $returnIDLType = $function->signature->type;
+ my $returnType = GetCOMTypeOut($returnIDLType);
+ my $noReturn = ($returnType eq "void");
+
+ AddForwardDeclarationsForTypeInIDL($returnIDLType);
+
+ my @paramArgList = ();
+ foreach my $param (@{$function->parameters}) {
+ my $paramName = $param->name;
+ my $paramIDLType = $param->type;
+ my $paramType = GetCOMTypeIn($param->type);
+
+ AddForwardDeclarationsForTypeInIDL($paramIDLType);
+
+ # Form parameter
+ my $parameter = "[in] ${paramType} ${paramName}";
+
+ # Add parameter to function signature
+ push(@paramArgList, $parameter);
+ }
+
+ unless ($noReturn) {
+ my $resultParameter = "[out, retval] " . $returnType . "* result";
+ push(@paramArgList, $resultParameter);
+ }
+
+ my $functionSig = " HRESULT " . $functionName . "(";
+ $functionSig .= join(", ", @paramArgList);
+ $functionSig .= ");\n\n";
+ push(@IDLContent, $functionSig);
+ }
+ }
+
+ # - End
+ push(@IDLContent, "}\n\n");
+}
+
+sub GenerateInterfaceHeader
+{
+ my ($object, $dataNode) = @_;
+
+ my $IDLType = $dataNode->name;
+ my $implementationClass = IDLTypeToImplementationType($IDLType);
+ my $implementationClassWithoutNamespace = StripNamespace($implementationClass);
+ my $className = GetClassName($IDLType);
+ my $interfaceName = GetInterfaceName($IDLType);
+
+ # - Add default header template
+ @CPPInterfaceHeader = @licenseTemplate;
+ push(@CPPInterfaceHeader, "\n");
+
+ # - Header guards -
+ push(@CPPInterfaceHeader, "#ifndef " . $className . "_h\n");
+ push(@CPPInterfaceHeader, "#define " . $className . "_h\n\n");
+
+ # - Forward Declarations -
+ push(@CPPInterfaceHeader, "interface ${interfaceName};\n\n");
+ push(@CPPInterfaceHeader, "namespace WebCore {\n");
+ push(@CPPInterfaceHeader, " class ${implementationClassWithoutNamespace};\n");
+ push(@CPPInterfaceHeader, "}\n\n");
+
+ # - Default Interface Creator -
+ push(@CPPInterfaceHeader, "${interfaceName}* to${interfaceName}(${implementationClass}*) { return 0; }\n\n");
+
+ push(@CPPInterfaceHeader, "#endif // " . $className . "_h\n");
+}
+
+# -----------------------------------------------------------------------------
+# CPP Helper Functions
+# -----------------------------------------------------------------------------
+
+sub GenerateCPPAttributeSignature
+{
+ my ($attribute, $className, $options) = @_;
+
+ my $attributeName = $attribute->signature->name;
+ my $isReadonly = ($attribute->type =~ /^readonly/);
+
+ my $newline = $$options{"NewLines"} ? "\n" : "";
+ my $indent = $$options{"Indent"} ? " " x $$options{"Indent"} : "";
+ my $semicolon = $$options{"IncludeSemiColon"} ? ";" : "";
+ my $virtual = $$options{"AddVirtualKeyword"} ? "virtual " : "";
+ my $class = $$options{"UseClassName"} ? "${className}::" : "";
+ my $forwarder = $$options{"Forwarder"} ? 1 : 0;
+ my $joiner = ($$options{"NewLines"} ? "\n" . $indent . " " : "");
+
+ my %attributeSignatures = ();
+
+ unless ($isReadonly) {
+ my $attributeTypeIn = GetCOMTypeIn($attribute->signature->type);
+ my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName);
+ my $setter = $indent . $virtual . "HRESULT STDMETHODCALLTYPE ". $class . $setterName . "(";
+ $setter .= $joiner . "/* [in] */ ${attributeTypeIn} ${attributeName})" . $semicolon . $newline;
+ if ($forwarder) {
+ $setter .= " { return " . $$options{"Forwarder"} . "::" . $setterName . "(${attributeName}); }\n";
+ }
+ $attributeSignatures{"Setter"} = $setter;
+ }
+
+ my $attributeTypeOut = GetCOMTypeOut($attribute->signature->type);
+ my $getter = $indent . $virtual . "HRESULT STDMETHODCALLTYPE " . $class . $attributeName . "(";
+ $getter .= $joiner . "/* [retval][out] */ ${attributeTypeOut}* result)" . $semicolon . $newline;
+ if ($forwarder) {
+ $getter .= " { return " . $$options{"Forwarder"} . "::" . $attributeName . "(result); }\n";
+ }
+ $attributeSignatures{"Getter"} = $getter;
+
+ return %attributeSignatures;
+}
+
+
+sub GenerateCPPAttribute
+{
+ my ($attribute, $className, $implementationClass) = @_;
+
+ my $implementationClassWithoutNamespace = StripNamespace($implementationClass);
+
+ my $attributeName = $attribute->signature->name;
+ my $attributeIDLType = $attribute->signature->type;
+ my $hasSetterException = @{$attribute->setterExceptions};
+ my $hasGetterException = @{$attribute->getterExceptions};
+ my $isReadonly = ($attribute->type =~ /^readonly/);
+ my $attributeTypeIsPrimitive = $codeGenerator->IsPrimitiveType($attributeIDLType);
+ my $attributeTypeIsString = $codeGenerator->IsStringType($attributeIDLType);
+ my $attributeImplementationType = IDLTypeToImplementationType($attributeIDLType);
+ my $attributeImplementationTypeWithoutNamespace = StripNamespace($attributeImplementationType);
+ my $attributeTypeCOMClassName = GetClassName($attributeIDLType);
+
+ $CPPImplementationWebCoreIncludes{"ExceptionCode.h"} = 1 if $hasSetterException or $hasGetterException;
+
+ my %signatures = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1,
+ "Indent" => 0,
+ "IncludeSemiColon" => 0,
+ "UseClassName" => 1,
+ "AddVirtualKeyword" => 0 });
+
+ my %attrbutesToReturn = ();
+
+ unless ($isReadonly) {
+ my @setterImplementation = ();
+ push(@setterImplementation, $signatures{"Setter"});
+ push(@setterImplementation, "{\n");
+
+ my $setterName = "set" . $codeGenerator->WK_ucfirst($attributeName);
+
+ my @setterParams = ();
+ if ($attributeTypeIsString) {
+ push(@setterParams, $attributeName);
+ if ($hasSetterException) {
+ push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n");
+ push(@setterParams, "ec");
+ }
+ } elsif ($attributeTypeIsPrimitive) {
+ if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
+ push(@setterParams, "WebCore::String::number(${attributeName})");
+ } elsif ($attributeIDLType eq "boolean") {
+ push(@setterParams, "!!${attributeName}");
+ } else {
+ my $primitiveImplementationType = IDLTypeToImplementationType($attributeIDLType);
+ push(@setterParams, "static_cast<${primitiveImplementationType}>(${attributeName})");
+ }
+
+ if ($hasSetterException) {
+ push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n");
+ push(@setterParams, "ec");
+ }
+ } else {
+ $CPPImplementationWebCoreIncludes{"COMPtr.h"} = 1;
+
+ push(@setterImplementation, " if (!${attributeName})\n");
+ push(@setterImplementation, " return E_POINTER;\n\n");
+ push(@setterImplementation, " COMPtr<${attributeTypeCOMClassName}> ptr(Query, ${attributeName});\n");
+ push(@setterImplementation, " if (!ptr)\n");
+ push(@setterImplementation, " return E_NOINTERFACE;\n");
+
+ push(@setterParams, "ptr->impl${attributeImplementationTypeWithoutNamespace}()");
+ if ($hasSetterException) {
+ push(@setterImplementation, " WebCore::ExceptionCode ec = 0;\n");
+ push(@setterParams, "ec");
+ }
+ }
+
+ # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT
+
+ my $setterCall = " impl${implementationClassWithoutNamespace}()->${setterName}(" . join(", ", @setterParams) . ");\n";
+
+ push(@setterImplementation, $setterCall);
+ push(@setterImplementation, " return S_OK;\n");
+ push(@setterImplementation, "}\n\n");
+
+ $attrbutesToReturn{"Setter"} = join("", @setterImplementation);
+ }
+
+ my @getterImplementation = ();
+ push(@getterImplementation, $signatures{"Getter"});
+ push(@getterImplementation, "{\n");
+ push(@getterImplementation, " if (!result)\n");
+ push(@getterImplementation, " return E_POINTER;\n\n");
+
+ my $implementationGetter = "impl${implementationClassWithoutNamespace}()->" . $codeGenerator->WK_lcfirst($attributeName) . "(" . ($hasGetterException ? "ec" : ""). ")";
+
+ push(@getterImplementation, " WebCore::ExceptionCode ec = 0;\n") if $hasGetterException;
+
+ if ($attributeTypeIsString) {
+ push(@getterImplementation, " *result = WebCore::BString(${implementationGetter}).release();\n");
+ } elsif ($attributeTypeIsPrimitive) {
+ if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
+ push(@getterImplementation, " *result = static_cast<${attributeTypeCOMClassName}>(${implementationGetter}.toInt());\n");
+ } else {
+ push(@getterImplementation, " *result = static_cast<${attributeTypeCOMClassName}>(${implementationGetter});\n");
+ }
+ } else {
+ $CPPImplementationIncludesAngle{"wtf/GetPtr.h"} = 1;
+ my $attributeTypeCOMInterfaceName = GetInterfaceName($attributeIDLType);
+ push(@getterImplementation, " *result = 0;\n");
+ push(@getterImplementation, " ${attributeImplementationType}* resultImpl = WTF::getPtr(${implementationGetter});\n");
+ push(@getterImplementation, " if (!resultImpl)\n");
+ push(@getterImplementation, " return E_POINTER;\n\n");
+ push(@getterImplementation, " *result = to${attributeTypeCOMInterfaceName}(resultImpl);\n");
+ }
+
+ # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT
+
+ push(@getterImplementation, " return S_OK;\n");
+ push(@getterImplementation, "}\n\n");
+
+ $attrbutesToReturn{"Getter"} = join("", @getterImplementation);
+
+ return %attrbutesToReturn;
+}
+
+sub GenerateCPPFunctionSignature
+{
+ my ($function, $className, $options) = @_;
+
+ my $functionName = $function->signature->name;
+ my $returnIDLType = $function->signature->type;
+ my $returnType = GetCOMTypeOut($returnIDLType);
+ my $noReturn = ($returnType eq "void");
+
+ my $newline = $$options{"NewLines"} ? "\n" : "";
+ my $indent = $$options{"Indent"} ? " " x $$options{"Indent"} : "";
+ my $semicolon = $$options{"IncludeSemiColon"} ? ";" : "";
+ my $virtual = $$options{"AddVirtualKeyword"} ? "virtual " : "";
+ my $class = $$options{"UseClassName"} ? "${className}::" : "";
+ my $forwarder = $$options{"Forwarder"} ? 1 : 0;
+ my $joiner = ($$options{"NewLines"} ? "\n" . $indent . " " : " ");
+
+ my @paramArgList = ();
+ foreach my $param (@{$function->parameters}) {
+ my $paramName = $param->name;
+ my $paramType = GetCOMTypeIn($param->type);
+ my $parameter = "/* [in] */ ${paramType} ${paramName}";
+ push(@paramArgList, $parameter);
+ }
+
+ unless ($noReturn) {
+ my $resultParameter .= "/* [out, retval] */ ${returnType}* result";
+ push(@paramArgList, $resultParameter);
+ }
+
+ my $functionSig = $indent . $virtual . "HRESULT STDMETHODCALLTYPE " . $class . $functionName . "(";
+ $functionSig .= $joiner . join("," . $joiner, @paramArgList) if @paramArgList > 0;
+ $functionSig .= ")" . $semicolon . $newline;
+ if ($forwarder) {
+ my @paramNameList = ();
+ push(@paramNameList, $_->name) foreach (@{$function->parameters});
+ push(@paramNameList, "result") unless $noReturn;
+ $functionSig .= " { return " . $$options{"Forwarder"} . "::" . $functionName . "(" . join(", ", @paramNameList) . "); }\n";
+ }
+
+ return $functionSig
+}
+
+sub GenerateCPPFunction
+{
+ my ($function, $className, $implementationClass) = @_;
+
+ my @functionImplementation = ();
+
+ my $signature = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1,
+ "Indent" => 0,
+ "IncludeSemiColon" => 0,
+ "UseClassName" => 1,
+ "AddVirtualKeyword" => 0 });
+
+ my $implementationClassWithoutNamespace = StripNamespace($implementationClass);
+
+ my $functionName = $function->signature->name;
+ my $returnIDLType = $function->signature->type;
+ my $noReturn = ($returnIDLType eq "void");
+ my $requiresEventTargetNodeCast = $function->signature->extendedAttributes->{"EventTargetNodeCast"};
+ my $raisesExceptions = @{$function->raisesExceptions};
+
+ AddIncludesForTypeInCPPImplementation($returnIDLType);
+ $CPPImplementationWebCoreIncludes{"ExceptionCode.h"} = 1 if $raisesExceptions;
+
+ my %needsCustom = ();
+ my @parameterInitialization = ();
+ my @parameterList = ();
+ foreach my $param (@{$function->parameters}) {
+ my $paramName = $param->name;
+ my $paramIDLType = $param->type;
+
+ my $paramTypeIsPrimitive = $codeGenerator->IsPrimitiveType($paramIDLType);
+ my $paramTypeIsString = $codeGenerator->IsStringType($paramIDLType);
+
+ $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"};
+
+ AddIncludesForTypeInCPPImplementation($paramIDLType);
+
+ # FIXME: We may need to null check the arguments as well
+
+ if ($paramTypeIsString) {
+ push(@parameterList, $paramName);
+ } elsif ($paramTypeIsPrimitive) {
+ if ($paramIDLType eq "boolean") {
+ push(@parameterList, "!!${paramName}");
+ } else {
+ my $primitiveImplementationType = IDLTypeToImplementationType($paramIDLType);
+ push(@parameterList, "static_cast<${primitiveImplementationType}>(${paramName})");
+ }
+ } else {
+ $CPPImplementationWebCoreIncludes{"COMPtr.h"} = 1;
+
+ $needsCustom{"CanReturnEarly"} = 1;
+
+ my $paramTypeCOMClassName = GetClassName($paramIDLType);
+ my $paramTypeImplementationWithoutNamespace = StripNamespace(IDLTypeToImplementationType($paramIDLType));
+ my $ptrName = "ptrFor" . $codeGenerator->WK_ucfirst($paramName);
+ my $paramInit = " COMPtr<${paramTypeCOMClassName}> ${ptrName}(Query, ${paramName});\n";
+ $paramInit .= " if (!${ptrName})\n";
+ $paramInit .= " return E_NOINTERFACE;";
+ push(@parameterInitialization, $paramInit);
+ push(@parameterList, "${ptrName}->impl${paramTypeImplementationWithoutNamespace}()");
+ }
+ }
+
+ push(@parameterList, "ec") if $raisesExceptions;
+
+ my $implementationGetter = "impl${implementationClassWithoutNamespace}()";
+ if ($requiresEventTargetNodeCast) {
+ $implementationGetter = "WebCore::EventTargetNodeCast(${implementationGetter})";
+ }
+
+ my $callSigBegin = " ";
+ my $callSigMiddle = "${implementationGetter}->" . $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterList) . ")";
+ my $callSigEnd = ";\n";
+
+ if (defined $needsCustom{"NodeToReturn"}) {
+ my $nodeToReturn = $needsCustom{"NodeToReturn"};
+ $callSigBegin .= "if (";
+ $callSigEnd = ")\n";
+ $callSigEnd .= " *result = ${nodeToReturn};";
+ } elsif (!$noReturn) {
+ my $returnTypeIsString = $codeGenerator->IsStringType($returnIDLType);
+ my $returnTypeIsPrimitive = $codeGenerator->IsPrimitiveType($returnIDLType);
+
+ if ($returnTypeIsString) {
+ $callSigBegin .= "*result = WebCore::BString(";
+ $callSigEnd = ").release();\n";
+ } elsif ($returnTypeIsPrimitive) {
+ my $primitiveCOMType = GetClassName($returnIDLType);
+ $callSigBegin .= "*result = static_cast<${primitiveCOMType}>(";
+ $callSigEnd = ");";
+ } else {
+ $CPPImplementationIncludesAngle{"wtf/GetPtr.h"} = 1;
+ my $returnImplementationType = IDLTypeToImplementationType($returnIDLType);
+ my $returnTypeCOMInterfaceName = GetInterfaceName($returnIDLType);
+ $callSigBegin .= "${returnImplementationType}* resultImpl = WTF::getPtr(";
+ $callSigEnd = ");\n";
+ $callSigEnd .= " if (!resultImpl)\n";
+ $callSigEnd .= " return E_POINTER;\n\n";
+ $callSigEnd .= " *result = to${returnTypeCOMInterfaceName}(resultImpl);";
+ }
+ }
+
+ push(@functionImplementation, $signature);
+ push(@functionImplementation, "{\n");
+ unless ($noReturn) {
+ push(@functionImplementation, " if (!result)\n");
+ push(@functionImplementation, " return E_POINTER;\n\n");
+ push(@functionImplementation, " *result = 0;\n\n") if $needsCustom{"CanReturnEarly"};
+ }
+ push(@functionImplementation, " WebCore::ExceptionCode ec = 0;\n") if $raisesExceptions; # FIXME: CHECK EXCEPTION AND DO SOMETHING WITH IT
+ push(@functionImplementation, join("\n", @parameterInitialization) . (@parameterInitialization > 0 ? "\n" : ""));
+ if ($requiresEventTargetNodeCast) {
+ push(@functionImplementation, " if (!impl${implementationClassWithoutNamespace}()->isEventTargetNode())\n");
+ push(@functionImplementation, " return E_FAIL;\n");
+ }
+ push(@functionImplementation, $callSigBegin . $callSigMiddle . $callSigEnd . "\n");
+ push(@functionImplementation, " return S_OK;\n");
+ push(@functionImplementation, "}\n\n");
+
+ return join("", @functionImplementation);
+}
+
+
+# -----------------------------------------------------------------------------
+# CPP Header
+# -----------------------------------------------------------------------------
+
+sub GenerateCPPHeader
+{
+ my ($object, $dataNode) = @_;
+
+ my $IDLType = $dataNode->name;
+ my $implementationClass = IDLTypeToImplementationType($IDLType);
+ my $implementationClassWithoutNamespace = StripNamespace($implementationClass);
+ my $className = GetClassName($IDLType);
+ my $interfaceName = GetInterfaceName($IDLType);
+
+ my $parentClassName = GetParentClass($dataNode);
+ my @otherInterfacesImplemented = GetAdditionalInterfaces($IDLType);
+ foreach my $otherInterface (@otherInterfacesImplemented) {
+ push(@additionalInterfaceDefinitions, $codeGenerator->ParseInterface($otherInterface));
+ }
+
+ # FIXME: strip whitespace from UUID
+ my $uuid = $dataNode->extendedAttributes->{"ImplementationUUID"} || die "All classes require an ImplementationUUID extended attribute.";
+
+ my $numAttributes = @{$dataNode->attributes};
+ my $numFunctions = @{$dataNode->functions};
+
+ # - Add default header template
+ @CPPHeaderHeader = @licenseTemplate;
+ push(@CPPHeaderHeader, "\n");
+
+ # - Header guards -
+ push(@CPPHeaderHeader, "#ifndef " . $className . "_h\n");
+ push(@CPPHeaderHeader, "#define " . $className . "_h\n\n");
+
+ AddIncludesForTypeInCPPHeader($interfaceName);
+ AddIncludesForTypeInCPPHeader($parentClassName);
+ $CPPHeaderDontForwardDeclarations{$className} = 1;
+ $CPPHeaderDontForwardDeclarations{$interfaceName} = 1;
+ $CPPHeaderDontForwardDeclarations{$parentClassName} = 1;
+
+ # -- Forward declare implementation type
+ push(@CPPHeaderContent, "namespace WebCore {\n");
+ push(@CPPHeaderContent, " class ". StripNamespace($implementationClass) . ";\n");
+ push(@CPPHeaderContent, "}\n\n");
+
+ # -- Start Class --
+ my @parentsClasses = ($parentClassName, $interfaceName);
+ push(@parentsClasses, map { GetInterfaceName($_) } @otherInterfacesImplemented);
+ push(@CPPHeaderContent, "class __declspec(uuid(\"$uuid\")) ${className} : " . join(", ", map { "public $_" } @parentsClasses) . " {\n");
+
+ # Add includes for all additional interfaces to implement
+ map { AddIncludesForTypeInCPPHeader(GetInterfaceName($_)) } @otherInterfacesImplemented;
+
+ # -- BASICS --
+ # FIXME: The constructor and destructor should be protected, but the current design of
+ # createInstance requires them to be public. One solution is to friend the constructor
+ # of the top-level-class with every one of its child classes, but that requires information
+ # this script currently does not have, though possibly could determine.
+ push(@CPPHeaderContent, "public:\n");
+ push(@CPPHeaderContent, " ${className}(${implementationClass}*);\n");
+ push(@CPPHeaderContent, " virtual ~${className}();\n\n");
+
+ push(@CPPHeaderContent, "public:\n");
+ push(@CPPHeaderContent, " static ${className}* createInstance(${implementationClass}*);\n\n");
+
+ push(@CPPHeaderContent, " // IUnknown\n");
+ push(@CPPHeaderContent, " virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void** ppvObject);\n");
+ push(@CPPHeaderContent, " virtual ULONG STDMETHODCALLTYPE AddRef() { return ${parentClassName}::AddRef(); }\n");
+ push(@CPPHeaderContent, " virtual ULONG STDMETHODCALLTYPE Release() { return ${parentClassName}::Release(); }\n\n");
+
+
+ # -- Parent Class Forwards --
+ if (@{$dataNode->parents}) {
+ my %attributeNameSet = map {($_->signature->name, 1)} @{$dataNode->attributes};
+ my %functionNameSet = map {($_->signature->name, 1)} @{$dataNode->functions};
+
+ my @parentLists = $codeGenerator->GetMethodsAndAttributesFromParentClasses($dataNode);
+ push(@CPPHeaderContent, "\n");
+ foreach my $parentHash (@parentLists) {
+
+ push(@CPPHeaderContent, " // " . GetInterfaceName($parentHash->{'name'}) . $DASHES . "\n");
+
+ my @attributeList = @{$parentHash->{'attributes'}};
+ push(@CPPHeaderContent, " // Attributes\n");
+ foreach my $attribute (@attributeList) {
+ # Don't forward an attribute that this class redefines.
+ next if $attributeNameSet{$attribute->signature->name};
+
+ AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type);
+
+ my %attributes = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 0,
+ "Indent" => 4,
+ "IncludeSemiColon" => 0,
+ "AddVirtualKeyword" => 1,
+ "UseClassName" => 0,
+ "Forwarder" => $parentClassName });
+ push(@CPPHeaderContent, values(%attributes));
+ }
+
+ # Add attribute names to attribute names set in case other ancestors
+ # also define them.
+ $attributeNameSet{$_->signature->name} = 1 foreach @attributeList;
+
+ push(@CPPHeaderContent, "\n");
+
+ my @functionList = @{$parentHash->{'functions'}};
+ push(@CPPHeaderContent, " // Functions\n");
+ foreach my $function (@functionList) {
+ # Don't forward a function that this class redefines.
+ next if $functionNameSet{$function->signature->name};
+
+ AddForwardDeclarationsForTypeInCPPHeader($function->signature->type);
+ AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters});
+
+ my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 0,
+ "Indent" => 4,
+ "IncludeSemiColon" => 0,
+ "AddVirtualKeyword" => 1,
+ "UseClassName" => 0,
+ "Forwarder" => $parentClassName });
+
+ push(@CPPHeaderContent, $functionSig);
+ }
+ # Add functions names to functions names set in case other ancestors
+ # also define them.
+ $functionNameSet{$_->signature->name} = 1 foreach @functionList;
+
+ push(@CPPHeaderContent, "\n");
+ }
+ }
+
+ # - Additional interfaces to implement -
+ foreach my $interfaceToImplement (@additionalInterfaceDefinitions) {
+ my $IDLTypeOfInterfaceToImplement = $interfaceToImplement->name;
+ my $nameOfInterfaceToImplement = GetInterfaceName($IDLTypeOfInterfaceToImplement);
+ my $numAttributesInInterface = @{$interfaceToImplement->attributes};
+ my $numFunctionsInInterface = @{$interfaceToImplement->functions};
+
+ push(@CPPHeaderContent, " // ${nameOfInterfaceToImplement} ${DASHES}\n\n");
+
+ # - Add attribute getters/setters.
+ if ($numAttributesInInterface > 0) {
+ push(@CPPHeaderContent, " // Attributes\n\n");
+ foreach my $attribute (@{$interfaceToImplement->attributes}) {
+ AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type);
+
+ my %attributeSigs = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1,
+ "Indent" => 4,
+ "IncludeSemiColon" => 1,
+ "AddVirtualKeyword" => 1,
+ "UseClassName" => 0 });
+
+ push(@CPPHeaderContent, values(%attributeSigs));
+ push(@CPPHeaderContent, "\n");
+ }
+ }
+
+ # - Add functions.
+ if ($numFunctionsInInterface > 0) {
+ push(@CPPHeaderContent, " // Functions\n\n");
+ foreach my $function (@{$interfaceToImplement->functions}) {
+ AddForwardDeclarationsForTypeInCPPHeader($function->signature->type);
+ AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters});
+
+ my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1,
+ "Indent" => 4,
+ "IncludeSemiColon" => 1,
+ "AddVirtualKeyword" => 1,
+ "UseClassName" => 0 });
+
+ push(@CPPHeaderContent, $functionSig);
+ push(@CPPHeaderContent, "\n");
+ }
+ }
+ }
+
+ if ($numAttributes > 0 || $numFunctions > 0) {
+ push(@CPPHeaderContent, " // ${interfaceName} ${DASHES}\n\n");
+ }
+
+ # - Add constants COMING SOON
+
+ # - Add attribute getters/setters.
+ if ($numAttributes > 0) {
+ push(@CPPHeaderContent, " // Attributes\n\n");
+ foreach my $attribute (@{$dataNode->attributes}) {
+ AddForwardDeclarationsForTypeInCPPHeader($attribute->signature->type);
+
+ my %attributeSigs = GenerateCPPAttributeSignature($attribute, $className, { "NewLines" => 1,
+ "Indent" => 4,
+ "IncludeSemiColon" => 1,
+ "AddVirtualKeyword" => 1,
+ "UseClassName" => 0 });
+
+ push(@CPPHeaderContent, values(%attributeSigs));
+ push(@CPPHeaderContent, "\n");
+ }
+ }
+
+ # - Add functions.
+ if ($numFunctions > 0) {
+ push(@CPPHeaderContent, " // Functions\n\n");
+ foreach my $function (@{$dataNode->functions}) {
+ AddForwardDeclarationsForTypeInCPPHeader($function->signature->type);
+ AddForwardDeclarationsForTypeInCPPHeader($_->type) foreach (@{$function->parameters});
+
+ my $functionSig = GenerateCPPFunctionSignature($function, $className, { "NewLines" => 1,
+ "Indent" => 4,
+ "IncludeSemiColon" => 1,
+ "AddVirtualKeyword" => 1,
+ "UseClassName" => 0 });
+
+ push(@CPPHeaderContent, $functionSig);
+ push(@CPPHeaderContent, "\n");
+ }
+ }
+
+ push(@CPPHeaderContent, " ${implementationClass}* impl${implementationClassWithoutNamespace}() const;\n");
+
+ if (@{$dataNode->parents} == 0) {
+ AddIncludesForTypeInCPPHeader("wtf/RefPtr", 1);
+ push(@CPPHeaderContent, "\n");
+ push(@CPPHeaderContent, " ${implementationClass}* impl() const { return m_impl.get(); }\n\n");
+ push(@CPPHeaderContent, "private:\n");
+ push(@CPPHeaderContent, " RefPtr<${implementationClass}> m_impl;\n");
+ }
+
+ # -- End Class --
+ push(@CPPHeaderContent, "};\n\n");
+
+ # -- Default Interface Creator --
+ push(@CPPHeaderContent, "${interfaceName}* to${interfaceName}(${implementationClass}*);\n\n");
+
+ push(@CPPHeaderContent, "#endif // " . $className . "_h\n");
+}
+
+
+# -----------------------------------------------------------------------------
+# CPP Implementation
+# -----------------------------------------------------------------------------
+
+sub GenerateCPPImplementation
+{
+ my ($object, $dataNode) = @_;
+
+ my $IDLType = $dataNode->name;
+ my $implementationClass = IDLTypeToImplementationType($IDLType);
+ my $implementationClassWithoutNamespace = StripNamespace($implementationClass);
+ my $className = GetClassName($IDLType);
+ my $interfaceName = GetInterfaceName($IDLType);
+
+ my $parentClassName = GetParentClass($dataNode);
+ my $isBaseClass = (@{$dataNode->parents} == 0);
+
+ my $uuid = $dataNode->extendedAttributes->{"ImplementationUUID"} || die "All classes require an ImplementationUUID extended attribute.";
+
+ my $numAttributes = @{$dataNode->attributes};
+ my $numFunctions = @{$dataNode->functions};
+
+ # - Add default header template
+ @CPPImplementationHeader = @licenseTemplate;
+ push(@CPPImplementationHeader, "\n");
+
+ push(@CPPImplementationHeader, "#include \"config.h\"\n");
+ push(@CPPImplementationHeader, "#include \"WebKitDLL.h\"\n");
+ push(@CPPImplementationHeader, "#include " . ($className eq "GEN_DOMImplementation" ? "\"GEN_DOMDOMImplementation.h\"" : "\"${className}.h\"") . "\n");
+ $CPPImplementationDontIncludes{"${className}.h"} = 1;
+ $CPPImplementationWebCoreIncludes{"${implementationClassWithoutNamespace}.h"} = 1;
+
+ # -- Constructor --
+ push(@CPPImplementationContent, "${className}::${className}(${implementationClass}* impl)\n");
+ if ($isBaseClass) {
+ push(@CPPImplementationContent, " : m_impl(impl)\n");
+ push(@CPPImplementationContent, "{\n");
+ push(@CPPImplementationContent, " ASSERT_ARG(impl, impl);\n");
+ push(@CPPImplementationContent, "}\n\n");
+ } else {
+ push(@CPPImplementationContent, " : ${parentClassName}(impl)\n");
+ push(@CPPImplementationContent, "{\n");
+ push(@CPPImplementationContent, "}\n\n");
+ }
+
+ # -- Destructor --
+ push(@CPPImplementationContent, "${className}::~${className}()\n");
+ push(@CPPImplementationContent, "{\n");
+ if ($isBaseClass) {
+ $CPPImplementationIncludes{"DOMCreateInstance.h"} = 1;
+ push(@CPPImplementationContent, " removeDOMWrapper(impl());\n");
+ }
+ push(@CPPImplementationContent, "}\n\n");
+
+ push(@CPPImplementationContent, "${implementationClass}* ${className}::impl${implementationClassWithoutNamespace}() const\n");
+ push(@CPPImplementationContent, "{\n");
+ push(@CPPImplementationContent, " return static_cast<${implementationClass}*>(impl());\n");
+ push(@CPPImplementationContent, "}\n\n");
+
+ # Base classes must implement the createInstance method externally.
+ if (@{$dataNode->parents} != 0) {
+ push(@CPPImplementationContent, "${className}* ${className}::createInstance(${implementationClass}* impl)\n");
+ push(@CPPImplementationContent, "{\n");
+ push(@CPPImplementationContent, " return static_cast<${className}*>(${parentClassName}::createInstance(impl));\n");
+ push(@CPPImplementationContent, "}\n");
+ }
+
+ push(@CPPImplementationContent, "// IUnknown $DASHES\n\n");
+
+ # -- QueryInterface --
+ push(@CPPImplementationContent, "HRESULT STDMETHODCALLTYPE ${className}::QueryInterface(REFIID riid, void** ppvObject)\n");
+ push(@CPPImplementationContent, "{\n");
+ push(@CPPImplementationContent, " *ppvObject = 0;\n");
+ push(@CPPImplementationContent, " if (IsEqualGUID(riid, IID_${interfaceName}))\n");
+ push(@CPPImplementationContent, " *ppvObject = reinterpret_cast<${interfaceName}*>(this);\n");
+ push(@CPPImplementationContent, " else if (IsEqualGUID(riid, __uuidof(${className})))\n");
+ push(@CPPImplementationContent, " *ppvObject = reinterpret_cast<${className}*>(this);\n");
+ push(@CPPImplementationContent, " else\n");
+ push(@CPPImplementationContent, " return ${parentClassName}::QueryInterface(riid, ppvObject);\n\n");
+ push(@CPPImplementationContent, " AddRef();\n");
+ push(@CPPImplementationContent, " return S_OK;\n");
+ push(@CPPImplementationContent, "}\n\n");
+
+ # - Additional interfaces to implement -
+ foreach my $interfaceToImplement (@additionalInterfaceDefinitions) {
+ my $IDLTypeOfInterfaceToImplement = $interfaceToImplement->name;
+ my $nameOfInterfaceToImplement = GetInterfaceName($IDLTypeOfInterfaceToImplement);
+ my $numAttributesInInterface = @{$interfaceToImplement->attributes};
+ my $numFunctionsInInterface = @{$interfaceToImplement->functions};
+
+ push(@CPPImplementationContent, " // ${nameOfInterfaceToImplement} ${DASHES}\n\n");
+
+ if ($numAttributesInInterface > 0) {
+ push(@CPPImplementationContent, "// Attributes\n\n");
+ foreach my $attribute (@{$interfaceToImplement->attributes}) {
+ # FIXME: Do this in one step.
+ # FIXME: Implement exception handling.
+
+ AddIncludesForTypeInCPPImplementation($attribute->signature->type);
+
+ my %attributes = GenerateCPPAttribute($attribute, $className, $implementationClass);
+ push(@CPPImplementationContent, values(%attributes));
+ }
+ }
+
+ # - Add functions.
+ if ($numFunctionsInInterface > 0) {
+ push(@CPPImplementationContent, "// Functions\n\n");
+
+ foreach my $function (@{$interfaceToImplement->functions}) {
+ my $functionImplementation = GenerateCPPFunction($function, $className, $implementationClass);
+ push(@CPPImplementationContent, $functionImplementation);
+ }
+ }
+ }
+
+ push(@CPPImplementationContent, "// ${interfaceName} $DASHES\n\n");
+
+ # - Add attribute getters/setters.
+ if ($numAttributes > 0) {
+ push(@CPPImplementationContent, "// Attributes\n\n");
+ foreach my $attribute (@{$dataNode->attributes}) {
+ # FIXME: do this in one step
+ my $hasSetterException = @{$attribute->setterExceptions};
+ my $hasGetterException = @{$attribute->getterExceptions};
+
+ AddIncludesForTypeInCPPImplementation($attribute->signature->type);
+
+ my %attributes = GenerateCPPAttribute($attribute, $className, $implementationClass);
+ push(@CPPImplementationContent, values(%attributes));
+ }
+ }
+
+ # - Add functions.
+ if ($numFunctions > 0) {
+ push(@CPPImplementationContent, "// Functions\n\n");
+
+ foreach my $function (@{$dataNode->functions}) {
+ my $functionImplementation = GenerateCPPFunction($function, $className, $implementationClass);
+ push(@CPPImplementationContent, $functionImplementation);
+ }
+ }
+
+ # - Default implementation for interface creator.
+ # FIXME: add extended attribute to add custom implementation if necessary.
+ push(@CPPImplementationContent, "${interfaceName}* to${interfaceName}(${implementationClass}* impl)\n");
+ push(@CPPImplementationContent, "{\n");
+ push(@CPPImplementationContent, " return ${className}::createInstance(impl);\n");
+ push(@CPPImplementationContent, "}\n");
+}
+
+sub WriteData
+{
+ my ($object, $name, $pureInterface) = @_;
+
+ # -- IDL --
+ my $IDLFileName = "$outputDir/I" . $TEMP_PREFIX . "DOM" . $name . ".idl";
+ unlink($IDLFileName);
+
+ # Write to output IDL.
+ open(OUTPUTIDL, ">$IDLFileName") or die "Couldn't open file $IDLFileName";
+
+ # Add header
+ print OUTPUTIDL @IDLHeader;
+
+ # Add forward declarations and imorts
+ delete $IDLForwardDeclarations{keys(%IDLDontForwardDeclare)};
+ delete $IDLImports{keys(%IDLDontImport)};
+
+ print OUTPUTIDL map { "cpp_quote(\"interface $_;\")\n" } sort keys(%IDLForwardDeclarations);
+ print OUTPUTIDL "\n";
+
+ print OUTPUTIDL map { "interface $_;\n" } sort keys(%IDLForwardDeclarations);
+ print OUTPUTIDL "\n";
+ print OUTPUTIDL "#ifndef DO_NO_IMPORTS\n";
+ print OUTPUTIDL map { ($_ eq "IGEN_DOMImplementation") ? "import \"IGEN_DOMDOMImplementation.idl\";\n" : "import \"$_.idl\";\n" } sort keys(%IDLImports);
+ print OUTPUTIDL "#endif\n";
+ print OUTPUTIDL "\n";
+
+ # Add content
+ print OUTPUTIDL @IDLContent;
+
+ close(OUTPUTIDL);
+
+ @IDLHeader = ();
+ @IDLContent = ();
+
+ if ($pureInterface) {
+ my $CPPInterfaceHeaderFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".h";
+ unlink($CPPInterfaceHeaderFileName);
+
+ open(OUTPUTCPPInterfaceHeader, ">$CPPInterfaceHeaderFileName") or die "Couldn't open file $CPPInterfaceHeaderFileName";
+
+ print OUTPUTCPPInterfaceHeader @CPPInterfaceHeader;
+
+ close(OUTPUTCPPInterfaceHeader);
+
+ @CPPInterfaceHeader = ();
+ } else {
+ my $CPPHeaderFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".h";
+ unlink($CPPHeaderFileName);
+
+ # -- CPP Header --
+ open(OUTPUTCPPHeader, ">$CPPHeaderFileName") or die "Couldn't open file $CPPHeaderFileName";
+
+ # Add header
+ print OUTPUTCPPHeader @CPPHeaderHeader;
+
+ # Add includes
+ print OUTPUTCPPHeader map { ($_ eq "GEN_DOMImplementation.h") ? "#include \"GEN_DOMDOMImplementation.h\"\n" : "#include \"$_\"\n" } sort keys(%CPPHeaderIncludes);
+ print OUTPUTCPPHeader map { "#include <$_>\n" } sort keys(%CPPHeaderIncludesAngle);
+
+ foreach my $dontDeclare (keys(%CPPHeaderDontForwardDeclarations)) {
+ delete $CPPHeaderForwardDeclarations{$dontDeclare} if ($CPPHeaderForwardDeclarations{$dontDeclare});
+ }
+ print OUTPUTCPPHeader "\n";
+ print OUTPUTCPPHeader map { "interface $_;\n" } sort keys(%CPPHeaderForwardDeclarations);
+ print OUTPUTCPPHeader "\n";
+
+ # Add content
+ print OUTPUTCPPHeader @CPPHeaderContent;
+
+ close(OUTPUTCPPHeader);
+
+ @CPPHeaderHeader = ();
+ @CPPHeaderContent = ();
+
+
+ # -- CPP Implementation --
+ my $CPPImplementationFileName = "$outputDir/" . $TEMP_PREFIX . "DOM" . $name . ".cpp";
+ unlink($CPPImplementationFileName);
+
+ open(OUTPUTCPPImplementation, ">$CPPImplementationFileName") or die "Couldn't open file $CPPImplementationFileName";
+
+ # Add header
+ print OUTPUTCPPImplementation @CPPImplementationHeader;
+ print OUTPUTCPPImplementation "\n";
+
+ # Add includes
+ foreach my $dontInclude (keys(%CPPImplementationDontIncludes)) {
+ delete $CPPImplementationIncludes{$dontInclude} if ($CPPImplementationIncludes{$dontInclude});
+ }
+ print OUTPUTCPPImplementation map { ($_ eq "GEN_DOMImplementation.h") ? "#include \"GEN_DOMDOMImplementation.h\"\n" : "#include \"$_\"\n" } sort keys(%CPPImplementationIncludes);
+ print OUTPUTCPPImplementation map { "#include <$_>\n" } sort keys(%CPPImplementationIncludesAngle);
+ print OUTPUTCPPImplementation "\n";
+
+ print OUTPUTCPPImplementation "#pragma warning(push, 0)\n";
+ print OUTPUTCPPImplementation map { "#include <WebCore/$_>\n" } sort keys(%CPPImplementationWebCoreIncludes);
+ print OUTPUTCPPImplementation "#pragma warning(pop)\n";
+
+ # Add content
+ print OUTPUTCPPImplementation @CPPImplementationContent;
+
+ close(OUTPUTCPPImplementation);
+
+ @CPPImplementationHeader = ();
+ @CPPImplementationContent = ();
+ }
+}
+
+1;
diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm
new file mode 100644
index 0000000..a095fc7
--- /dev/null
+++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -0,0 +1,1947 @@
+#
+# Copyright (C) 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
+# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
+# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
+# Copyright (C) 2006, 2007, 2008 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 CodeGeneratorJS;
+
+use File::stat;
+
+my $module = "";
+my $outputDir = "";
+
+my @headerContentHeader = ();
+my @headerContent = ();
+my %headerIncludes = ();
+
+my @implContentHeader = ();
+my @implContent = ();
+my %implIncludes = ();
+my %implKJSIncludes = ();
+
+# Default .h template
+my $headerTemplate = << "EOF";
+/*
+ This file is part of the WebKit open source project.
+ This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+ 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.
+*/
+EOF
+
+# Default constructor
+sub new
+{
+ my $object = shift;
+ my $reference = { };
+
+ $codeGenerator = shift;
+ $outputDir = shift;
+
+ bless($reference, $object);
+ return $reference;
+}
+
+sub finish
+{
+ my $object = shift;
+
+ # Commit changes!
+ $object->WriteData();
+}
+
+sub leftShift($$) {
+ my ($value, $distance) = @_;
+ return (($value << $distance) & 0xFFFFFFFF);
+}
+
+# Params: 'domClass' struct
+sub GenerateInterface
+{
+ my $object = shift;
+ my $dataNode = shift;
+ my $defines = shift;
+
+ # Start actual generation
+ $object->GenerateHeader($dataNode);
+ $object->GenerateImplementation($dataNode);
+
+ my $name = $dataNode->name;
+
+ # Open files for writing
+ my $headerFileName = "$outputDir/JS$name.h";
+ my $implFileName = "$outputDir/JS$name.cpp";
+
+ open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
+ open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
+}
+
+# Params: 'idlDocument' struct
+sub GenerateModule
+{
+ my $object = shift;
+ my $dataNode = shift;
+
+ $module = $dataNode->module;
+}
+
+sub GetParentClassName
+{
+ my $dataNode = shift;
+
+ return $dataNode->extendedAttributes->{"LegacyParent"} if $dataNode->extendedAttributes->{"LegacyParent"};
+ return "DOMObject" if @{$dataNode->parents} eq 0;
+ return "JS" . $codeGenerator->StripModule($dataNode->parents(0));
+}
+
+sub GetVisibleClassName
+{
+ my $className = shift;
+
+ return "DOMException" if $className eq "DOMCoreException";
+ return $className;
+}
+
+sub AvoidInclusionOfType
+{
+ my $type = shift;
+
+ # Special case: SVGRect.h / SVGPoint.h / SVGNumber.h / SVGMatrix.h do not exist.
+ return 1 if $type eq "SVGRect" or $type eq "SVGPoint" or $type eq "SVGNumber" or $type eq "SVGMatrix";
+ return 0;
+}
+
+sub UsesManualToJSImplementation
+{
+ my $type = shift;
+
+ return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event" or $type eq "ImageData" or $type eq "Element" or $type eq "Text";
+ return 0;
+}
+
+sub IndexGetterReturnsStrings
+{
+ my $type = shift;
+
+ return 1 if $type eq "CSSStyleDeclaration" or $type eq "MediaList" or $type eq "CSSVariablesDeclaration";
+ return 0;
+}
+
+sub CreateSVGContextInterfaceName
+{
+ my $type = shift;
+
+ return $type if $codeGenerator->IsSVGAnimatedType($type);
+ return "SVGPathSeg" if $type =~ /^SVGPathSeg/ and $type ne "SVGPathSegList";
+
+ return "";
+}
+
+sub AddIncludesForType
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ # When we're finished with the one-file-per-class
+ # reorganization, we won't need these special cases.
+ if ($codeGenerator->IsPrimitiveType($type) or AvoidInclusionOfType($type)
+ or $type eq "DOMString" or $type eq "DOMObject" or $type eq "RGBColor") {
+ } elsif ($type =~ /SVGPathSeg/) {
+ $joinedName = $type;
+ $joinedName =~ s/Abs|Rel//;
+ $implIncludes{"${joinedName}.h"} = 1;
+ } elsif ($type eq "XPathNSResolver") {
+ $implIncludes{"JSXPathNSResolver.h"} = 1;
+ $implIncludes{"JSCustomXPathNSResolver.h"} = 1;
+ } else {
+ # default, include the same named file
+ $implIncludes{"${type}.h"} = 1;
+ }
+
+ # additional includes (things needed to compile the bindings but not the header)
+
+ if ($type eq "CanvasRenderingContext2D") {
+ $implIncludes{"CanvasGradient.h"} = 1;
+ $implIncludes{"CanvasPattern.h"} = 1;
+ $implIncludes{"CanvasStyle.h"} = 1;
+ }
+
+ if ($type eq "CanvasGradient" or $type eq "XPathNSResolver" or $type eq "MessagePort") {
+ $implIncludes{"PlatformString.h"} = 1;
+ }
+
+ if ($type eq "Document") {
+ $implIncludes{"NodeFilter.h"} = 1;
+ }
+}
+
+sub AddIncludesForSVGAnimatedType
+{
+ my $type = shift;
+ $type =~ s/SVGAnimated//;
+
+ if ($type eq "Point" or $type eq "Rect") {
+ $implIncludes{"Float$type.h"} = 1;
+ } elsif ($type eq "String") {
+ $implIncludes{"PlatformString.h"} = 1;
+ }
+}
+
+sub AddClassForwardIfNeeded
+{
+ my $implClassName = shift;
+
+ # SVGAnimatedLength/Number/etc.. are typedefs to SVGAnimtatedTemplate, so don't use class forwards for them!
+ push(@headerContent, "class $implClassName;\n\n") unless $codeGenerator->IsSVGAnimatedType($implClassName);
+}
+
+sub IsSVGTypeNeedingContextParameter
+{
+ my $implClassName = shift;
+
+ if ($implClassName =~ /SVG/ and not $implClassName =~ /Element/) {
+ return 1 unless $implClassName =~ /SVGPaint/ or $implClassName =~ /SVGColor/ or $implClassName =~ /SVGDocument/;
+ }
+
+ return 0;
+}
+
+sub HashValueForClassAndName
+{
+ my $class = shift;
+ my $name = shift;
+
+ # SVG Filter enums live in WebCore namespace (platform/graphics/)
+ if ($class =~ /^SVGFE*/ or $class =~ /^SVGComponentTransferFunctionElement$/) {
+ return "WebCore::$name";
+ }
+
+ return "${class}::$name";
+}
+
+sub hashTableAccessor
+{
+ my $noStaticTables = shift;
+ my $className = shift;
+ if ($noStaticTables) {
+ return "get${className}Table(exec)";
+ } else {
+ return "&${className}Table";
+ }
+}
+
+sub prototypeHashTableAccessor
+{
+ my $noStaticTables = shift;
+ my $className = shift;
+ if ($noStaticTables) {
+ return "get${className}PrototypeTable(exec)";
+ } else {
+ return "&${className}PrototypeTable";
+ }
+}
+
+sub GenerateGetOwnPropertySlotBody
+{
+ my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
+
+ my $namespaceMaybe = ($inlined ? "JSC::" : "");
+
+ my @getOwnPropertySlotImpl = ();
+
+ if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection") {
+ push(@getOwnPropertySlotImpl, " ${namespaceMaybe}JSValue* proto = prototype();\n");
+ push(@getOwnPropertySlotImpl, " if (proto->isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
+ push(@getOwnPropertySlotImpl, " return false;\n\n");
+ }
+
+ my $hasNameGetterGeneration = sub {
+ push(@getOwnPropertySlotImpl, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
+ push(@getOwnPropertySlotImpl, " slot.setCustom(this, nameGetter);\n");
+ push(@getOwnPropertySlotImpl, " return true;\n");
+ push(@getOwnPropertySlotImpl, " }\n");
+ if ($inlined) {
+ $headerIncludes{"AtomicString.h"} = 1;
+ } else {
+ $implIncludes{"AtomicString.h"} = 1;
+ }
+ };
+
+ if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
+ &$hasNameGetterGeneration();
+ }
+
+ my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
+ if ($requiresManualLookup) {
+ push(@getOwnPropertySlotImpl, " const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
+ push(@getOwnPropertySlotImpl, " if (entry) {\n");
+ push(@getOwnPropertySlotImpl, " slot.setCustom(this, entry->propertyGetter());\n");
+ push(@getOwnPropertySlotImpl, " return true;\n");
+ push(@getOwnPropertySlotImpl, " }\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ push(@getOwnPropertySlotImpl, " bool ok;\n");
+ push(@getOwnPropertySlotImpl, " unsigned index = propertyName.toUInt32(&ok, false);\n");
+ push(@getOwnPropertySlotImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
+ if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ push(@getOwnPropertySlotImpl, " slot.setValue(getByIndex(exec, index));\n");
+ } else {
+ push(@getOwnPropertySlotImpl, " slot.setCustomIndex(this, index, indexGetter);\n");
+ }
+ push(@getOwnPropertySlotImpl, " return true;\n");
+ push(@getOwnPropertySlotImpl, " }\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"HasNameGetter"}) {
+ &$hasNameGetterGeneration();
+ }
+
+ if ($dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}) {
+ push(@getOwnPropertySlotImpl, " if (customGetOwnPropertySlot(exec, propertyName, slot))\n");
+ push(@getOwnPropertySlotImpl, " return true;\n");
+ }
+
+ if ($hasAttributes) {
+ if ($inlined) {
+ die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
+ push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, slot);\n");
+ } else {
+ push(@getOwnPropertySlotImpl, " return ${namespaceMaybe}getStaticValueSlot<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
+ }
+ } else {
+ push(@getOwnPropertySlotImpl, " return Base::getOwnPropertySlot(exec, propertyName, slot);\n");
+ }
+
+ return @getOwnPropertySlotImpl;
+}
+
+sub GenerateHeader
+{
+ my $object = shift;
+ my $dataNode = shift;
+
+ my $interfaceName = $dataNode->name;
+ my $className = "JS$interfaceName";
+ my $implClassName = $interfaceName;
+
+ # We only support multiple parents with SVG (for now).
+ if (@{$dataNode->parents} > 1) {
+ die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
+ $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode);
+ }
+
+ my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
+ my $hasRealParent = @{$dataNode->parents} > 0;
+ my $hasParent = $hasLegacyParent || $hasRealParent;
+ my $parentClassName = GetParentClassName($dataNode);
+ my $conditional = $dataNode->extendedAttributes->{"Conditional"};
+
+ # - Add default header template
+ @headerContentHeader = split("\r", $headerTemplate);
+
+ # - Add header protection
+ push(@headerContentHeader, "\n#ifndef $className" . "_h");
+ push(@headerContentHeader, "\n#define $className" . "_h\n\n");
+
+ my $conditionalString;
+ if ($conditional) {
+ $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
+ push(@headerContentHeader, "\n#if ${conditionalString}\n\n");
+ }
+
+ if ($hasParent) {
+ push(@headerContentHeader, "#include \"$parentClassName.h\"\n");
+ } else {
+ push(@headerContentHeader, "#include \"JSDOMBinding.h\"\n");
+ push(@headerContentHeader, "#include <runtime/JSGlobalObject.h>\n");
+ push(@headerContentHeader, "#include <runtime/ObjectPrototype.h>\n");
+ }
+ if ($interfaceName eq "Node") {
+ push(@headerContentHeader, "#include \"EventTargetNode.h\"\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"CustomCall"}) {
+ push(@headerContentHeader, "#include <runtime/CallData.h>\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
+ push(@headerContentHeader, "#include <kjs/lookup.h>\n");
+ push(@headerContentHeader, "#include <wtf/AlwaysInline.h>\n");
+ }
+
+ if ($hasParent && $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
+ push(@headerContentHeader, "#include \"${implClassName}.h\"");
+ }
+
+ # Get correct pass/store types respecting PODType flag
+ my $podType = $dataNode->extendedAttributes->{"PODType"};
+ my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
+ push(@headerContentHeader, "#include \"$podType.h\"\n") if $podType and $podType ne "float";
+
+ push(@headerContentHeader, "#include \"JSSVGPODTypeWrapper.h\"\n") if $podType;
+
+ my $numConstants = @{$dataNode->constants};
+ my $numAttributes = @{$dataNode->attributes};
+ my $numFunctions = @{$dataNode->functions};
+
+ push(@headerContent, "\nnamespace WebCore {\n\n");
+
+ # Implementation class forward declaration
+ AddClassForwardIfNeeded($implClassName) unless $podType;
+ AddClassForwardIfNeeded("JSDOMWindowShell") if $interfaceName eq "DOMWindow";
+
+ # Class declaration
+ push(@headerContent, "class $className : public $parentClassName {\n");
+ push(@headerContent, " typedef $parentClassName Base;\n");
+ push(@headerContent, "public:\n");
+
+ # Constructor
+ if ($interfaceName eq "DOMWindow") {
+ push(@headerContent, " $className(PassRefPtr<JSC::StructureID>, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
+ } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
+ push(@headerContent, " $className(PassRefPtr<JSC::StructureID>, PassRefPtr<$implType>, SVGElement* context);\n");
+ } else {
+ push(@headerContent, " $className(PassRefPtr<JSC::StructureID>, PassRefPtr<$implType>);\n");
+ }
+
+ # Destructor
+ push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $interfaceName eq "Document");
+
+ # Prototype
+ push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*);\n") if $interfaceName ne "DOMWindow";
+
+ $implIncludes{"${className}Custom.h"} = 1 if $dataNode->extendedAttributes->{"CustomHeader"} || $dataNode->extendedAttributes->{"CustomPutFunction"};
+
+ my $hasGetter = $numAttributes > 0
+ || $dataNode->extendedAttributes->{"GenerateConstructor"}
+ || $dataNode->extendedAttributes->{"HasIndexGetter"}
+ || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
+ || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
+ || $dataNode->extendedAttributes->{"HasNameGetter"}
+ || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
+
+ # Getters
+ if ($hasGetter) {
+ push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
+ push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
+ push(@headerContent, " bool customGetOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
+ }
+
+ # Check if we have any writable properties
+ my $hasReadWriteProperties = 0;
+ foreach (@{$dataNode->attributes}) {
+ if ($_->type !~ /^readonly\ attribute$/) {
+ $hasReadWriteProperties = 1;
+ }
+ }
+
+ my $hasSetter = $hasReadWriteProperties
+ || $dataNode->extendedAttributes->{"CustomPutFunction"}
+ || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
+
+ # Getters
+ if ($hasSetter) {
+ push(@headerContent, " virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue*, JSC::PutPropertySlot&);\n");
+ push(@headerContent, " virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue*);\n") if $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
+ push(@headerContent, " bool customPut(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue*, JSC::PutPropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomPutFunction"};
+ }
+
+ # Class info
+ push(@headerContent, " virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
+ push(@headerContent, " static const JSC::ClassInfo s_info;\n\n");
+
+ # Structure ID
+ if ($interfaceName eq "DOMWindow") {
+ push(@headerContent,
+ " static PassRefPtr<JSC::StructureID> createStructureID(JSC::JSValue* prototype)\n" .
+ " {\n" .
+ " return JSC::StructureID::create(prototype, JSC::TypeInfo(JSC::ObjectType, JSC::ImplementsHasInstance | JSC::NeedsThisConversion));\n" .
+ " }\n\n");
+ } elsif ($hasGetter) {
+ push(@headerContent,
+ " static PassRefPtr<JSC::StructureID> createStructureID(JSC::JSValue* prototype)\n" .
+ " {\n" .
+ " return JSC::StructureID::create(prototype, JSC::TypeInfo(JSC::ObjectType));\n" .
+ " }\n\n");
+ }
+
+ # Custom mark function
+ push(@headerContent, " virtual void mark();\n\n") if $dataNode->extendedAttributes->{"CustomMarkFunction"};
+
+ # Custom pushEventHandlerScope function
+ push(@headerContent, " virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
+
+ # Custom call functions
+ push(@headerContent, " virtual JSC::CallType getCallData(JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};
+
+ # Custom deleteProperty function
+ push(@headerContent, " virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
+
+ # Custom getPropertyNames function
+ push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"});
+ push(@headerContent, " bool customGetPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
+
+ # Custom getPropertyAttributes function
+ push(@headerContent, " virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned& attributes) const;\n") if $dataNode->extendedAttributes->{"CustomGetPropertyAttributes"};
+
+ # Custom defineGetter function
+ push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
+
+ # Custom defineSetter function
+ push(@headerContent, " virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
+
+ # Custom lookupGetter function
+ push(@headerContent, " virtual JSC::JSValue* lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"};
+
+ # Custom lookupSetter function
+ push(@headerContent, " virtual JSC::JSValue* lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupSetter"};
+
+ # Constructor object getter
+ push(@headerContent, " static JSC::JSValue* getConstructor(JSC::ExecState*);\n") if $dataNode->extendedAttributes->{"GenerateConstructor"};
+
+ my $numCustomFunctions = 0;
+ my $numCustomAttributes = 0;
+
+ # Attribute and function enums
+ if ($numAttributes > 0) {
+ foreach (@{$dataNode->attributes}) {
+ my $attribute = $_;
+ $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"Custom"};
+ $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomGetter"};
+ $numCustomAttributes++ if $attribute->signature->extendedAttributes->{"CustomSetter"};
+ }
+ }
+
+ if ($numCustomAttributes > 0) {
+ push(@headerContent, "\n // Custom attributes\n");
+
+ foreach my $attribute (@{$dataNode->attributes}) {
+ if ($attribute->signature->extendedAttributes->{"Custom"}) {
+ push(@headerContent, " JSC::JSValue* " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
+ if ($attribute->type !~ /^readonly/) {
+ push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue*);\n");
+ }
+ } elsif ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
+ push(@headerContent, " JSC::JSValue* " . $codeGenerator->WK_lcfirst($attribute->signature->name) . "(JSC::ExecState*) const;\n");
+ } elsif ($attribute->signature->extendedAttributes->{"CustomSetter"}) {
+ if ($attribute->type !~ /^readonly/) {
+ push(@headerContent, " void set" . $codeGenerator->WK_ucfirst($attribute->signature->name) . "(JSC::ExecState*, JSC::JSValue*);\n");
+ }
+ }
+ }
+ }
+
+ foreach my $function (@{$dataNode->functions}) {
+ $numCustomFunctions++ if $function->signature->extendedAttributes->{"Custom"};
+ }
+
+ if ($numCustomFunctions > 0) {
+ push(@headerContent, "\n // Custom functions\n");
+ foreach my $function (@{$dataNode->functions}) {
+ if ($function->signature->extendedAttributes->{"Custom"}) {
+ my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
+ push(@headerContent, " JSC::JSValue* " . $functionImplementationName . "(JSC::ExecState*, const JSC::ArgList&);\n");
+ }
+ }
+ }
+
+ if (!$hasParent) {
+ if ($podType) {
+ push(@headerContent, " JSSVGPODTypeWrapper<$podType>* impl() const { return m_impl.get(); }\n");
+ push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n");
+ push(@headerContent, "private:\n");
+ push(@headerContent, " RefPtr<SVGElement> m_context;\n");
+ push(@headerContent, " RefPtr<JSSVGPODTypeWrapper<$podType> > m_impl;\n");
+ } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
+ push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n");
+ push(@headerContent, " SVGElement* context() const { return m_context.get(); }\n\n");
+ push(@headerContent, "private:\n");
+ push(@headerContent, " RefPtr<SVGElement> m_context;\n");
+ push(@headerContent, " RefPtr<$implClassName > m_impl;\n");
+ } else {
+ push(@headerContent, " $implClassName* impl() const { return m_impl.get(); }\n\n");
+ push(@headerContent, "private:\n");
+ push(@headerContent, " RefPtr<$implClassName> m_impl;\n");
+ }
+ } elsif ($dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
+ push(@headerContent, " $implClassName* impl() const\n");
+ push(@headerContent, " {\n");
+ push(@headerContent, " return static_cast<$implClassName*>(Base::impl());\n");
+ push(@headerContent, " }\n");
+ }
+
+ # Index getter
+ if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
+ push(@headerContent, " static JSC::JSValue* indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
+ }
+ if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ push(@headerContent, " JSC::JSValue* getByIndex(JSC::ExecState*, unsigned index);\n");
+ }
+
+ # Index setter
+ if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+ push(@headerContent, " void indexSetter(JSC::ExecState*, unsigned index, JSC::JSValue*);\n");
+ }
+ # Name getter
+ if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
+ push(@headerContent, "private:\n");
+ push(@headerContent, " static bool canGetItemsForName(JSC::ExecState*, $implClassName*, const JSC::Identifier&);\n");
+ push(@headerContent, " static JSC::JSValue* nameGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
+ }
+
+ push(@headerContent, "};\n\n");
+
+ if ($dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
+ push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertySlot(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertySlot& slot)\n");
+ push(@headerContent, "{\n");
+ push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
+ push(@headerContent, "}\n\n");
+ }
+
+ if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"}) {
+ if ($podType) {
+ push(@headerContent, "JSC::JSValue* toJS(JSC::ExecState*, JSSVGPODTypeWrapper<$podType>*, SVGElement* context);\n");
+ } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
+ push(@headerContent, "JSC::JSValue* toJS(JSC::ExecState*, $implType*, SVGElement* context);\n");
+ } else {
+ push(@headerContent, "JSC::JSValue* toJS(JSC::ExecState*, $implType*);\n");
+ }
+
+ # Resolve ambiguity with EventTarget that otherwise exists.
+ if ($interfaceName eq "Node") {
+ push(@headerContent, "inline JSC::JSValue* toJS(JSC::ExecState* exec, EventTargetNode* node) { return toJS(exec, static_cast<Node*>(node)); }\n");
+ }
+ }
+ if (!$hasParent || $dataNode->extendedAttributes->{"GenerateNativeConverter"}) {
+ if ($podType) {
+ push(@headerContent, "$podType to${interfaceName}(JSC::JSValue*);\n");
+ } elsif ($interfaceName eq "NodeFilter") {
+ push(@headerContent, "PassRefPtr<NodeFilter> toNodeFilter(JSC::JSValue*);\n");
+ } else {
+ push(@headerContent, "$implClassName* to${interfaceName}(JSC::JSValue*);\n");
+ }
+ if ($interfaceName eq "Node" or $interfaceName eq "Element" or $interfaceName eq "Text") {
+ push(@headerContent, "JSC::JSValue* toJSNewlyCreated(JSC::ExecState*, $interfaceName*);\n");
+ }
+ }
+ push(@headerContent, "\n");
+
+ # Add prototype declaration.
+ push(@headerContent, "class ${className}Prototype : public JSC::JSObject {\n");
+ push(@headerContent, "public:\n");
+ if ($interfaceName eq "DOMWindow") {
+ push(@headerContent, " void* operator new(size_t);\n");
+ } else {
+ push(@headerContent, " static JSC::JSObject* self(JSC::ExecState*);\n");
+ }
+ push(@headerContent, " virtual const JSC::ClassInfo* classInfo() const { return &s_info; }\n");
+ push(@headerContent, " static const JSC::ClassInfo s_info;\n");
+ if ($numFunctions > 0 || $numConstants > 0) {
+ push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
+ push(@headerContent,
+ " static PassRefPtr<JSC::StructureID> createStructureID(JSC::JSValue* prototype)\n" .
+ " {\n" .
+ " return JSC::StructureID::create(prototype, JSC::TypeInfo(JSC::ObjectType));\n" .
+ " }\n");
+ }
+ push(@headerContent, " ${className}Prototype(PassRefPtr<JSC::StructureID> structure) : JSC::JSObject(structure) { }\n");
+
+ push(@headerContent, "};\n\n");
+
+ if ($numFunctions > 0) {
+ push(@headerContent,"// Functions\n\n");
+ foreach my $function (@{$dataNode->functions}) {
+ my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
+ push(@headerContent, "JSC::JSValue* ${functionName}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue*, const JSC::ArgList&);\n");
+ }
+ }
+
+ if ($numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"}) {
+ push(@headerContent,"// Attributes\n\n");
+ foreach my $attribute (@{$dataNode->attributes}) {
+ my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
+ push(@headerContent, "JSC::JSValue* ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
+ unless ($attribute->type =~ /readonly/) {
+ my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
+ push(@headerContent, "void ${setter}(JSC::ExecState*, JSC::JSObject*, JSC::JSValue*);\n");
+ }
+ }
+
+ if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
+ my $getter = "js" . $interfaceName . "Constructor";
+ push(@headerContent, "JSC::JSValue* ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
+ }
+ }
+
+ if ($numConstants > 0) {
+ push(@headerContent,"// Constants\n\n");
+ foreach my $constant (@{$dataNode->constants}) {
+ my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
+ push(@headerContent, "JSC::JSValue* ${getter}(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
+ }
+ }
+
+ push(@headerContent, "\n} // namespace WebCore\n\n");
+ push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional;
+ push(@headerContent, "#endif\n");
+}
+
+sub GenerateImplementation
+{
+ my ($object, $dataNode) = @_;
+
+ my $interfaceName = $dataNode->name;
+ my $className = "JS$interfaceName";
+ my $implClassName = $interfaceName;
+
+ my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
+ my $hasRealParent = @{$dataNode->parents} > 0;
+ my $hasParent = $hasLegacyParent || $hasRealParent;
+ my $parentClassName = GetParentClassName($dataNode);
+ my $conditional = $dataNode->extendedAttributes->{"Conditional"};
+ my $visibleClassName = GetVisibleClassName($interfaceName);
+
+ # - Add default header template
+ @implContentHeader = split("\r", $headerTemplate);
+ push(@implContentHeader, "\n#include \"config.h\"\n\n");
+ my $conditionalString;
+ if ($conditional) {
+ $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
+ push(@implContentHeader, "\n#if ${conditionalString}\n\n");
+ }
+
+ if ($className =~ /^JSSVG/) {
+ push(@implContentHeader, "#include \"SVGElement.h\"\n");
+
+ if ($className =~ /^JSSVGAnimated/) {
+ AddIncludesForSVGAnimatedType($interfaceName);
+ }
+ }
+
+ push(@implContentHeader, "#include \"$className.h\"\n\n");
+ push(@implContentHeader, "#include <wtf/GetPtr.h>\n\n");
+
+ push(@implContentHeader, "#include <runtime/PropertyNameArray.h>\n") if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"};
+
+ AddIncludesForType($interfaceName);
+
+ @implContent = ();
+
+ push(@implContent, "\nusing namespace JSC;\n\n");
+ push(@implContent, "namespace WebCore {\n\n");
+
+ push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className)\n\n");
+
+ # - Add all attributes in a hashtable definition
+ my $numAttributes = @{$dataNode->attributes};
+ $numAttributes++ if $dataNode->extendedAttributes->{"GenerateConstructor"};
+
+ if ($numAttributes > 0) {
+ my $hashName = $className . "Table";
+
+ my @hashKeys = ();
+ my @hashSpecials = ();
+ my @hashValue1 = ();
+ my @hashValue2 = ();
+
+ my @entries = ();
+
+ foreach my $attribute (@{$dataNode->attributes}) {
+ my $name = $attribute->signature->name;
+ push(@hashKeys, $name);
+
+ my @specials = ();
+ push(@specials, "DontDelete") unless $attribute->signature->extendedAttributes->{"Deletable"};
+ push(@specials, "DontEnum") if $attribute->signature->extendedAttributes->{"DontEnum"};
+ push(@specials, "ReadOnly") if $attribute->type =~ /readonly/;
+ my $special = (@specials > 0) ? join("|", @specials) : "0";
+ push(@hashSpecials, $special);
+
+ my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
+ push(@hashValue1, $getter);
+
+ if ($attribute->type =~ /readonly/) {
+ push(@hashValue2, "0");
+ } else {
+ my $setter = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
+ push(@hashValue2, $setter);
+ }
+ }
+
+ if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
+ push(@hashKeys, "constructor");
+ my $getter = "js" . $interfaceName . "Constructor";
+ push(@hashValue1, $getter);
+ push(@hashValue2, "0");
+ push(@hashSpecials, "DontEnum|ReadOnly"); # FIXME: Setting the constructor should be possible.
+ }
+
+ $object->GenerateHashTable($hashName,
+ \@hashKeys, \@hashSpecials,
+ \@hashValue1, \@hashValue2);
+ }
+
+ my $numConstants = @{$dataNode->constants};
+ my $numFunctions = @{$dataNode->functions};
+
+ # - Add all constants
+ if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
+ $hashName = $className . "ConstructorTable";
+
+ @hashKeys = ();
+ @hashValue1 = ();
+ @hashValue2 = ();
+ @hashSpecials = ();
+
+ # FIXME: we should not need a function for every constant.
+ foreach my $constant (@{$dataNode->constants}) {
+ push(@hashKeys, $constant->name);
+ my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
+ push(@hashValue1, $getter);
+ push(@hashValue2, "0");
+ push(@hashSpecials, "DontDelete|ReadOnly");
+ }
+
+ $object->GenerateHashTable($hashName,
+ \@hashKeys, \@hashSpecials,
+ \@hashValue1, \@hashValue2);
+
+ my $protoClassName;
+ $protoClassName = "${className}Prototype";
+
+ push(@implContent, constructorFor($className, $protoClassName, $interfaceName, $visibleClassName, $dataNode->extendedAttributes->{"CanBeConstructed"}));
+ }
+
+ # - Add functions and constants to a hashtable definition
+ $hashName = $className . "PrototypeTable";
+
+ @hashKeys = ();
+ @hashValue1 = ();
+ @hashValue2 = ();
+ @hashSpecials = ();
+
+ # FIXME: we should not need a function for every constant.
+ foreach my $constant (@{$dataNode->constants}) {
+ push(@hashKeys, $constant->name);
+ my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
+ push(@hashValue1, $getter);
+ push(@hashValue2, "0");
+ push(@hashSpecials, "DontDelete|ReadOnly");
+ }
+
+ foreach my $function (@{$dataNode->functions}) {
+ my $name = $function->signature->name;
+ push(@hashKeys, $name);
+
+ my $value = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($name);
+ push(@hashValue1, $value);
+
+ my $numParameters = @{$function->parameters};
+ push(@hashValue2, $numParameters);
+
+ my @specials = ();
+ push(@specials, "DontDelete") unless $function->signature->extendedAttributes->{"Deletable"};
+ push(@specials, "DontEnum") if $function->signature->extendedAttributes->{"DontEnum"};
+ push(@specials, "Function");
+ my $special = (@specials > 0) ? join("|", @specials) : "0";
+ push(@hashSpecials, $special);
+ }
+
+ $object->GenerateHashTable($hashName,
+ \@hashKeys, \@hashSpecials,
+ \@hashValue1, \@hashValue2);
+
+ if ($dataNode->extendedAttributes->{"NoStaticTables"}) {
+ push(@implContent, "static const HashTable* get${className}PrototypeTable(ExecState* exec)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");
+ push(@implContent, "}\n");
+ push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, 0, get${className}PrototypeTable };\n\n");
+ } else {
+ push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", 0, &${className}PrototypeTable, 0 };\n\n");
+ }
+ if ($interfaceName ne "DOMWindow") {
+ push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " return getDOMPrototype<${className}>(exec);\n");
+ push(@implContent, "}\n\n");
+ }
+ if ($interfaceName eq "DOMWindow") {
+ push(@implContent, "void* ${className}Prototype::operator new(size_t size)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " return JSDOMWindow::commonJSGlobalData()->heap.allocate(size);\n");
+ push(@implContent, "}\n\n");
+ }
+ if ($numConstants > 0 || $numFunctions > 0) {
+ push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
+ push(@implContent, "{\n");
+ if ($numConstants eq 0) {
+ push(@implContent, " return getStaticFunctionSlot<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
+ } elsif ($numFunctions eq 0) {
+ push(@implContent, " return getStaticValueSlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
+ } else {
+ push(@implContent, " return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
+ }
+ push(@implContent, "}\n\n");
+ }
+
+ # - Initialize static ClassInfo object
+ if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
+ push(@implContent, "static const HashTable* get${className}Table(ExecState* exec)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}Table);\n");
+ push(@implContent, "}\n");
+ }
+ push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", ");
+ if ($hasParent) {
+ push(@implContent, "&" . $parentClassName . "::s_info, ");
+ } else {
+ push(@implContent, "0, ");
+ }
+
+ if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) {
+ push(@implContent, "&${className}Table");
+ } else {
+ push(@implContent, "0");
+ }
+ if ($numAttributes > 0 && $dataNode->extendedAttributes->{"NoStaticTables"}) {
+ push(@implContent, ", get${className}Table ");
+ } else {
+ push(@implContent, ", 0 ");
+ }
+ push(@implContent, "};\n\n");
+
+ # Get correct pass/store types respecting PODType flag
+ my $podType = $dataNode->extendedAttributes->{"PODType"};
+ my $implType = $podType ? "JSSVGPODTypeWrapper<$podType> " : $implClassName;
+
+ my $needsSVGContext = IsSVGTypeNeedingContextParameter($implClassName);
+ my $parentNeedsSVGContext = ($needsSVGContext and $parentClassName =~ /SVG/);
+
+ # Constructor
+ if ($interfaceName eq "DOMWindow") {
+ AddIncludesForType("JSDOMWindowShell");
+ push(@implContent, "${className}::$className(PassRefPtr<StructureID> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
+ push(@implContent, " : $parentClassName(structure, impl, shell)\n");
+ } else {
+ push(@implContent, "${className}::$className(PassRefPtr<StructureID> structure, PassRefPtr<$implType> impl" . ($needsSVGContext ? ", SVGElement* context" : "") . ")\n");
+ if ($hasParent) {
+ push(@implContent, " : $parentClassName(structure, impl" . ($parentNeedsSVGContext ? ", context" : "") . ")\n");
+ } else {
+ push(@implContent, " : $parentClassName(structure)\n");
+ push(@implContent, " , m_context(context)\n") if $needsSVGContext;
+ push(@implContent, " , m_impl(impl)\n");
+ }
+ }
+ push(@implContent, "{\n");
+ push(@implContent, "}\n\n");
+
+ # Destructor
+ if (!$hasParent) {
+ push(@implContent, "${className}::~$className()\n");
+ push(@implContent, "{\n");
+
+ if ($interfaceName eq "Node") {
+ push(@implContent, " forgetDOMNode(m_impl->document(), m_impl.get());\n");
+ } else {
+ if ($podType) {
+ my $animatedType = $implClassName;
+ $animatedType =~ s/SVG/SVGAnimated/;
+
+ # Special case for JSSVGNumber
+ if ($codeGenerator->IsSVGAnimatedType($animatedType) and $podType ne "float") {
+ push(@implContent, " JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n");
+ }
+ }
+ push(@implContent, " forgetDOMObject(*Heap::heap(this)->globalData(), m_impl.get());\n");
+ }
+
+ push(@implContent, "\n}\n\n");
+ }
+
+ # Document needs a special destructor because it's a special case for caching. It needs
+ # its own special handling rather than relying on the caching that Node normally does.
+ if ($interfaceName eq "Document") {
+ push(@implContent, "${className}::~$className()\n");
+ push(@implContent, "{\n forgetDOMObject(*Heap::heap(this)->globalData(), static_cast<${implClassName}*>(impl()));\n}\n\n");
+ }
+
+ if ($interfaceName ne "DOMWindow") {
+ push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec)\n");
+ push(@implContent, "{\n");
+ if ($hasParent && $parentClassName ne "JSC::DOMNodeFilter") {
+ push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructureID(${parentClassName}Prototype::self(exec)));\n");
+ } else {
+ push(@implContent, " return new (exec) ${className}Prototype(${className}Prototype::createStructureID(exec->lexicalGlobalObject()->objectPrototype()));\n");
+ }
+ push(@implContent, "}\n\n");
+ }
+
+ my $hasGetter = $numAttributes > 0
+ || $dataNode->extendedAttributes->{"GenerateConstructor"}
+ || $dataNode->extendedAttributes->{"HasIndexGetter"}
+ || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
+ || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
+ || $dataNode->extendedAttributes->{"HasNameGetter"}
+ || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
+
+ # Attributes
+ if ($hasGetter) {
+ if (!$dataNode->extendedAttributes->{"InlineGetOwnPropertySlot"}) {
+ push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
+ push(@implContent, "{\n");
+ push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
+ push(@implContent, "}\n\n");
+ }
+
+ if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"})
+ && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
+ push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");
+ if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ push(@implContent, " slot.setValue(getByIndex(exec, propertyName));\n");
+ } else {
+ push(@implContent, " slot.setCustomIndex(this, propertyName, indexGetter);\n");
+ }
+ push(@implContent, " return true;\n");
+ push(@implContent, " }\n");
+ push(@implContent, " return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);\n");
+ push(@implContent, "}\n\n");
+ }
+
+ if ($numAttributes > 0) {
+ foreach my $attribute (@{$dataNode->attributes}) {
+ my $name = $attribute->signature->name;
+ my $type = $codeGenerator->StripModule($attribute->signature->type);
+ my $getFunctionName = "js" . $interfaceName . $codeGenerator->WK_ucfirst($attribute->signature->name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
+ my $implGetterFunctionName = $codeGenerator->WK_lcfirst($name);
+
+ push(@implContent, "JSValue* ${getFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
+ push(@implContent, "{\n");
+
+ my $implClassNameForValueConversion = "";
+ if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
+ $implClassNameForValueConversion = $implClassName;
+ }
+
+ if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} &&
+ !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
+ !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
+ push(@implContent, " if (!static_cast<$className*>(asObject(slot.slotBase()))->allowsAccessFrom(exec))\n");
+ push(@implContent, " return jsUndefined();\n");
+ }
+
+ if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomGetter"}) {
+ push(@implContent, " return static_cast<$className*>(asObject(slot.slotBase()))->$implGetterFunctionName(exec);\n");
+ } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
+ $implIncludes{"JSDOMBinding.h"} = 1;
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n");
+ push(@implContent, " return checkNodeSecurity(exec, imp->$implGetterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))") . " : jsUndefined();\n");
+ } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
+ $implIncludes{"Document.h"} = 1;
+ $implIncludes{"JSDOMBinding.h"} = 1;
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n");
+ push(@implContent, " return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))") . " : jsUndefined();\n");
+ } elsif ($type eq "EventListener") {
+ $implIncludes{"JSEventListener.h"} = 1;
+ $implIncludes{"EventListener.h"} = 1;
+ my $listenerType;
+ if ($attribute->signature->extendedAttributes->{"ProtectedListener"}) {
+ $listenerType = "JSEventListener";
+ } else {
+ $listenerType = "JSUnprotectedEventListener";
+ }
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n");
+ push(@implContent, " if (${listenerType}* listener = static_cast<${listenerType}*>(imp->$implGetterFunctionName())) {\n");
+ push(@implContent, " if (JSObject* listenerObj = listener->listenerObj())\n");
+ push(@implContent, " return listenerObj;\n");
+ push(@implContent, " }\n");
+ push(@implContent, " return jsNull();\n");
+ } elsif ($attribute->signature->type =~ /Constructor$/) {
+ my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
+ $constructorType =~ s/Constructor$//;
+ push(@implContent, " return JS" . $constructorType . "::getConstructor(exec);\n");
+ } elsif (!@{$attribute->getterExceptions}) {
+ if ($podType) {
+ push(@implContent, " $podType imp(*static_cast<$className*>(asObject(slot.slotBase()))->impl());\n");
+ if ($podType eq "float") { # Special case for JSSVGNumber
+ push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n");
+ } else {
+ push(@implContent, " return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n");
+ }
+ } else {
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n");
+ my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName()", "static_cast<$className*>(asObject(slot.slotBase()))");
+ if ($codeGenerator->IsSVGAnimatedType($type)) {
+ push(@implContent, " RefPtr<$type> obj = $jsType;\n");
+ push(@implContent, " return toJS(exec, obj.get(), imp);\n");
+ } else {
+ push(@implContent, " return $jsType;\n");
+ }
+ }
+ } else {
+ push(@implContent, " ExceptionCode ec = 0;\n");
+
+ if ($podType) {
+ push(@implContent, " $podType imp(*static_cast<$className*>(asObject(slot.slotBase()))->impl());\n");
+ push(@implContent, " JSC::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$implGetterFunctionName(ec)", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n");
+ } else {
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(asObject(slot.slotBase()))->impl());\n");
+ push(@implContent, " JSC::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$implGetterFunctionName(ec)", "static_cast<$className*>(asObject(slot.slotBase()))") . ";\n");
+ }
+
+ push(@implContent, " setDOMException(exec, ec);\n");
+ push(@implContent, " return result;\n");
+ }
+
+ push(@implContent, "}\n\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
+ my $constructorFunctionName = "js" . $interfaceName . "Constructor";
+
+ push(@implContent, "JSValue* ${constructorFunctionName}(ExecState* exec, const Identifier&, const PropertySlot& slot)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " return static_cast<$className*>(asObject(slot.slotBase()))->getConstructor(exec);\n");
+ push(@implContent, "}\n");
+ }
+ }
+
+ # Check if we have any writable attributes
+ my $hasReadWriteProperties = 0;
+ foreach my $attribute (@{$dataNode->attributes}) {
+ $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;
+ }
+
+ my $hasSetter = $hasReadWriteProperties
+ || $dataNode->extendedAttributes->{"CustomPutFunction"}
+ || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
+
+ if ($hasSetter) {
+ push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)\n");
+ push(@implContent, "{\n");
+ if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+ push(@implContent, " bool ok;\n");
+ push(@implContent, " unsigned index = propertyName.toUInt32(&ok, false);\n");
+ push(@implContent, " if (ok) {\n");
+ push(@implContent, " indexSetter(exec, index, value);\n");
+ push(@implContent, " return;\n");
+ push(@implContent, " }\n");
+ }
+ if ($dataNode->extendedAttributes->{"CustomPutFunction"}) {
+ push(@implContent, " if (customPut(exec, propertyName, value, slot))\n");
+ push(@implContent, " return;\n");
+ }
+
+ if ($hasReadWriteProperties) {
+ push(@implContent, " lookupPut<$className, Base>(exec, propertyName, value, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, slot);\n");
+ } else {
+ push(@implContent, " Base::put(exec, propertyName, value, slot);\n");
+ }
+ push(@implContent, "}\n\n");
+
+ if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+ push(@implContent, "void ${className}::put(ExecState* exec, unsigned propertyName, JSValue* value)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " indexSetter(exec, propertyName, value);\n");
+ push(@implContent, " return;\n");
+ push(@implContent, "}\n\n");
+ }
+
+ if ($hasReadWriteProperties) {
+ foreach my $attribute (@{$dataNode->attributes}) {
+ if ($attribute->type !~ /^readonly/) {
+ my $name = $attribute->signature->name;
+ my $type = $codeGenerator->StripModule($attribute->signature->type);
+ my $putFunctionName = "setJS" . $interfaceName . $codeGenerator->WK_ucfirst($name) . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "");
+ my $implSetterFunctionName = $codeGenerator->WK_ucfirst($name);
+
+ push(@implContent, "void ${putFunctionName}(ExecState* exec, JSObject* thisObject, JSValue* value)\n");
+ push(@implContent, "{\n");
+
+ if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
+ if ($interfaceName eq "DOMWindow") {
+ push(@implContent, " if (!static_cast<$className*>(thisObject)->allowsAccessFrom(exec))\n");
+ } else {
+ push(@implContent, " if (!allowsAccessFromFrame(exec, static_cast<$className*>(thisObject)->impl()->frame()))\n");
+ }
+ push(@implContent, " return;\n");
+ }
+
+ if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomSetter"}) {
+ push(@implContent, " static_cast<$className*>(thisObject)->set$implSetterFunctionName(exec, value);\n");
+ } elsif ($type eq "EventListener") {
+ $implIncludes{"JSEventListener.h"} = 1;
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n");
+ my $listenerType;
+ if ($attribute->signature->extendedAttributes->{"ProtectedListener"}) {
+ $listenerType = "JSEventListener";
+ } else {
+ $listenerType = "JSUnprotectedEventListener";
+ }
+ if ($interfaceName eq "DOMWindow") {
+ push(@implContent, " JSDOMGlobalObject* globalObject = static_cast<JSDOMWindow*>(thisObject);\n");
+ } else {
+ $implIncludes{"Frame.h"} = 1;
+ $implIncludes{"JSDOMGlobalObject.h"} = 1;
+ push(@implContent, " JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(imp->scriptExecutionContext());\n");
+ push(@implContent, " if (!globalObject)\n");
+ push(@implContent, " return;\n");
+ }
+ push(@implContent, " imp->set$implSetterFunctionName(globalObject->findOrCreate${listenerType}(exec, value, true));\n");
+ } elsif ($attribute->signature->type =~ /Constructor$/) {
+ my $constructorType = $attribute->signature->type;
+ $constructorType =~ s/Constructor$//;
+ $implIncludes{"JS" . $constructorType . ".h"} = 1;
+ push(@implContent, " // Shadowing a built-in constructor\n");
+ push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n");
+ } elsif ($attribute->signature->extendedAttributes->{"Replaceable"}) {
+ push(@implContent, " static_cast<$className*>(thisObject)->putDirect(Identifier(exec, \"$name\"), value);\n");
+ } else {
+ if ($podType) {
+ push(@implContent, " $podType imp(*static_cast<$className*>(thisObject)->impl());\n");
+ if ($podType eq "float") { # Special case for JSSVGNumber
+ push(@implContent, " imp = " . JSValueToNative($attribute->signature, "value") . ";\n");
+ } else {
+ push(@implContent, " imp.set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value") . ");\n");
+ }
+ push(@implContent, " static_cast<$className*>(thisObject)->impl()->commitChange(imp, static_cast<$className*>(thisObject)->context());\n");
+ } else {
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObject)->impl());\n");
+ push(@implContent, " ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
+ push(@implContent, " imp->set$implSetterFunctionName(" . JSValueToNative($attribute->signature, "value"));
+ push(@implContent, ", ec") if @{$attribute->setterExceptions};
+ push(@implContent, ");\n");
+ push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
+
+ if (IsSVGTypeNeedingContextParameter($implClassName)) {
+ push(@implContent, " if (static_cast<$className*>(thisObject)->context())\n");
+ push(@implContent, " static_cast<$className*>(thisObject)->context()->svgAttributeChanged(static_cast<$className*>(thisObject)->impl()->associatedAttributeName());\n");
+ }
+ }
+ }
+
+ push(@implContent, "}\n\n");
+ }
+ }
+ }
+ }
+ }
+
+ if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ push(@implContent, "void ${className}::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n");
+ push(@implContent, "{\n");
+ if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
+ push(@implContent, " if (customGetPropertyNames(exec, propertyNames))\n");
+ push(@implContent, " return;\n");
+ }
+ if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
+ push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n");
+ }
+ push(@implContent, " Base::getPropertyNames(exec, propertyNames);\n");
+ push(@implContent, "}\n\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
+ push(@implContent, "JSValue* ${className}::getConstructor(ExecState* exec)\n{\n");
+ push(@implContent, " return getDOMConstructor<${className}Constructor>(exec);\n");
+ push(@implContent, "}\n\n");
+ }
+
+ # Functions
+ if ($numFunctions > 0) {
+ foreach my $function (@{$dataNode->functions}) {
+ AddIncludesForType($function->signature->type);
+
+ my $functionName = $codeGenerator->WK_lcfirst($className) . "PrototypeFunction" . $codeGenerator->WK_ucfirst($function->signature->name);
+ my $functionImplementationName = $function->signature->extendedAttributes->{"ImplementationFunction"} || $codeGenerator->WK_lcfirst($function->signature->name);
+
+ push(@implContent, "JSValue* ${functionName}(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)\n");
+ push(@implContent, "{\n");
+
+ $implKJSInclude{"Error.h"} = 1;
+
+ if ($interfaceName eq "DOMWindow") {
+ push(@implContent, " $className* castedThisObj = toJSDOMWindow(thisValue);\n");
+ push(@implContent, " if (!castedThisObj)\n");
+ push(@implContent, " return throwError(exec, TypeError);\n");
+ } else {
+ push(@implContent, " if (!thisValue->isObject(&${className}::s_info))\n");
+ push(@implContent, " return throwError(exec, TypeError);\n");
+ push(@implContent, " $className* castedThisObj = static_cast<$className*>(asObject(thisValue));\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} &&
+ !$function->signature->extendedAttributes->{"DoNotCheckDomainSecurity"}) {
+ push(@implContent, " if (!castedThisObj->allowsAccessFrom(exec))\n");
+ push(@implContent, " return jsUndefined();\n");
+ }
+
+ if ($function->signature->extendedAttributes->{"Custom"}) {
+ push(@implContent, " return castedThisObj->" . $functionImplementationName . "(exec, args);\n");
+ } else {
+ if ($podType) {
+ push(@implContent, " JSSVGPODTypeWrapper<$podType>* wrapper = castedThisObj->impl();\n");
+ push(@implContent, " $podType imp(*wrapper);\n");
+ } else {
+ push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThisObj->impl());\n");
+ }
+
+ my $numParameters = @{$function->parameters};
+
+ if ($function->signature->extendedAttributes->{"RequiresAllArguments"}) {
+ push(@implContent, " if (args.size() < $numParameters)\n");
+ push(@implContent, " return jsUndefined();\n");
+ }
+
+ if (@{$function->raisesExceptions}) {
+ push(@implContent, " ExceptionCode ec = 0;\n");
+ }
+
+ if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
+ push(@implContent, " if (!checkNodeSecurity(exec, imp->getSVGDocument(" . (@{$function->raisesExceptions} ? "ec" : "") .")))\n");
+ push(@implContent, " return jsUndefined();\n");
+ $implIncludes{"JSDOMBinding.h"} = 1;
+ }
+
+ my $paramIndex = 0;
+ my $functionString = "imp" . ($podType ? "." : "->") . $functionImplementationName . "(";
+
+ my $hasOptionalArguments = 0;
+
+ foreach my $parameter (@{$function->parameters}) {
+ if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
+ push(@implContent, "\n int argsCount = args.size();\n");
+ $hasOptionalArguments = 1;
+ }
+
+ if ($hasOptionalArguments) {
+ push(@implContent, " if (argsCount < " . ($paramIndex + 1) . ") {\n");
+ GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " " x 2, $podType, $implClassName);
+ push(@implContent, " }\n\n");
+ }
+
+ my $name = $parameter->name;
+
+ if ($parameter->type eq "XPathNSResolver") {
+ push(@implContent, " RefPtr<XPathNSResolver> customResolver;\n");
+ push(@implContent, " XPathNSResolver* resolver = toXPathNSResolver(args.at(exec, $paramIndex));\n");
+ push(@implContent, " if (!resolver) {\n");
+ push(@implContent, " customResolver = JSCustomXPathNSResolver::create(exec, args.at(exec, $paramIndex));\n");
+ push(@implContent, " if (exec->hadException())\n");
+ push(@implContent, " return jsUndefined();\n");
+ push(@implContent, " resolver = customResolver.get();\n");
+ push(@implContent, " }\n");
+ } else {
+ push(@implContent, " " . GetNativeTypeFromSignature($parameter) . " $name = " . JSValueToNative($parameter, "args.at(exec, $paramIndex)") . ";\n");
+
+ # If a parameter is "an index" and it's negative it should throw an INDEX_SIZE_ERR exception.
+ # But this needs to be done in the bindings, because the type is unsigned and the fact that it
+ # was negative will be lost by the time we're inside the DOM.
+ if ($parameter->extendedAttributes->{"IsIndex"}) {
+ $implIncludes{"ExceptionCode.h"} = 1;
+ push(@implContent, " if ($name < 0) {\n");
+ push(@implContent, " setDOMException(exec, INDEX_SIZE_ERR);\n");
+ push(@implContent, " return jsUndefined();\n");
+ push(@implContent, " }\n");
+ }
+ }
+
+ $functionString .= ", " if $paramIndex;
+
+ if ($parameter->type eq "NodeFilter") {
+ $functionString .= "$name.get()";
+ } else {
+ $functionString .= $name;
+ }
+
+ $paramIndex++;
+ }
+
+ push(@implContent, "\n");
+ GenerateImplementationFunctionCall($function, $functionString, $paramIndex, " ", $podType, $implClassName);
+ }
+ push(@implContent, "}\n\n");
+ }
+ }
+
+ if ($numConstants > 0) {
+ push(@implContent, "// Constant getters\n\n");
+
+ foreach my $constant (@{$dataNode->constants}) {
+ my $getter = "js" . $interfaceName . $codeGenerator->WK_ucfirst($constant->name);
+
+ # FIXME: this casts into int to match our previous behavior which turned 0xFFFFFFFF in -1 for NodeFilter.SHOW_ALL
+ push(@implContent, "JSValue* ${getter}(ExecState* exec, const Identifier&, const PropertySlot&)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " return jsNumber(exec, static_cast<int>(" . $constant->value . "));\n");
+ push(@implContent, "}\n\n");
+ }
+ }
+
+ if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
+ push(@implContent, "\nJSValue* ${className}::indexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " ${className}* thisObj = static_cast<$className*>(asObject(slot.slotBase()));\n");
+ if (IndexGetterReturnsStrings($implClassName)) {
+ $implIncludes{"KURL.h"} = 1;
+ push(@implContent, " return jsStringOrNull(exec, thisObj->impl()->item(slot.index()));\n");
+ } else {
+ push(@implContent, " return toJS(exec, static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n");
+ }
+ push(@implContent, "}\n");
+ if ($interfaceName eq "HTMLCollection") {
+ $implIncludes{"JSNode.h"} = 1;
+ $implIncludes{"Node.h"} = 1;
+ }
+ }
+
+ if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !UsesManualToJSImplementation($implClassName)) {
+ if ($podType) {
+ push(@implContent, "JSC::JSValue* toJS(JSC::ExecState* exec, JSSVGPODTypeWrapper<$podType>* object, SVGElement* context)\n");
+ } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
+ push(@implContent, "JSC::JSValue* toJS(JSC::ExecState* exec, $implType* object, SVGElement* context)\n");
+ } else {
+ push(@implContent, "JSC::JSValue* toJS(JSC::ExecState* exec, $implType* object)\n");
+ }
+
+ push(@implContent, "{\n");
+ if ($podType) {
+ push(@implContent, " return getDOMObjectWrapper<$className, JSSVGPODTypeWrapper<$podType> >(exec, object, context);\n");
+ } elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
+ push(@implContent, " return getDOMObjectWrapper<$className>(exec, object, context);\n");
+ } else {
+ push(@implContent, " return getDOMObjectWrapper<$className>(exec, object);\n");
+ }
+ push(@implContent, "}\n");
+ }
+
+ if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateNativeConverter"}) and !$dataNode->extendedAttributes->{"CustomNativeConverter"}) {
+ if ($podType) {
+ push(@implContent, "$podType to${interfaceName}(JSC::JSValue* value)\n");
+ } else {
+ push(@implContent, "$implClassName* to${interfaceName}(JSC::JSValue* value)\n");
+ }
+
+ push(@implContent, "{\n");
+
+ push(@implContent, " return value->isObject(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(asObject(value))->impl() : ");
+ if ($podType and $podType ne "float") {
+ push(@implContent, "$podType();\n}\n");
+ } else {
+ push(@implContent, "0;\n}\n");
+ }
+ }
+
+ push(@implContent, "\n}\n");
+
+ push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional;
+}
+
+sub GenerateImplementationFunctionCall()
+{
+ my $function = shift;
+ my $functionString = shift;
+ my $paramIndex = shift;
+ my $indent = shift;
+ my $podType = shift;
+ my $implClassName = shift;
+
+ if (@{$function->raisesExceptions}) {
+ $functionString .= ", " if $paramIndex;
+ $functionString .= "ec";
+ }
+ $functionString .= ")";
+
+ if ($function->signature->type eq "void") {
+ push(@implContent, $indent . "$functionString;\n");
+ push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
+
+ if ($podType) {
+ push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n");
+ }
+
+ push(@implContent, $indent . "return jsUndefined();\n");
+ } else {
+ push(@implContent, "\n" . $indent . "JSC::JSValue* result = " . NativeToJSValue($function->signature, 1, $implClassName, "", $functionString, "castedThisObj") . ";\n");
+ push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
+
+ if ($podType) {
+ push(@implContent, $indent . "wrapper->commitChange(imp, castedThisObj->context());\n");
+ }
+
+ push(@implContent, $indent . "return result;\n");
+ }
+}
+
+sub GetNativeTypeFromSignature
+{
+ my $signature = shift;
+ my $type = $codeGenerator->StripModule($signature->type);
+
+ if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
+ # Special-case index arguments because we need to check that they aren't < 0.
+ return "int";
+ }
+
+ return GetNativeType($type);
+}
+
+my %nativeType = (
+ "CompareHow" => "Range::CompareHow",
+ "DOMString" => "const UString&",
+ "EventTarget" => "EventTargetNode*",
+ "NodeFilter" => "RefPtr<NodeFilter>",
+ "SVGLength" => "SVGLength",
+ "SVGMatrix" => "AffineTransform",
+ "SVGNumber" => "float",
+ "SVGPaintType" => "SVGPaint::SVGPaintType",
+ "SVGPoint" => "FloatPoint",
+ "SVGRect" => "FloatRect",
+ "SVGTransform" => "SVGTransform",
+ "boolean" => "bool",
+ "double" => "double",
+ "float" => "float",
+ "long" => "int",
+ "unsigned long" => "unsigned",
+ "unsigned short" => "unsigned short",
+);
+
+sub GetNativeType
+{
+ my $type = shift;
+
+ return $nativeType{$type} if exists $nativeType{$type};
+
+ # For all other types, the native type is a pointer with same type name as the IDL type.
+ return "${type}*";
+}
+
+sub JSValueToNative
+{
+ my $signature = shift;
+ my $value = shift;
+
+ my $type = $codeGenerator->StripModule($signature->type);
+
+ return "$value->toBoolean(exec)" if $type eq "boolean";
+ return "$value->toNumber(exec)" if $type eq "double";
+ return "$value->toFloat(exec)" if $type eq "float" or $type eq "SVGNumber";
+ return "$value->toInt32(exec)" if $type eq "unsigned long" or $type eq "long" or $type eq "unsigned short";
+
+ return "static_cast<Range::CompareHow>($value->toInt32(exec))" if $type eq "CompareHow";
+ return "static_cast<SVGPaint::SVGPaintType>($value->toInt32(exec))" if $type eq "SVGPaintType";
+
+ if ($type eq "DOMString") {
+ return "valueToStringWithNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
+ return "valueToStringWithUndefinedOrNullCheck(exec, $value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
+ return "$value->toString(exec)";
+ }
+
+ if ($type eq "EventTarget") {
+ $implIncludes{"JSEventTargetNode.h"} = 1;
+ return "toEventTargetNode($value)";
+ }
+
+ $implIncludes{"FloatPoint.h"} = 1 if $type eq "SVGPoint";
+ $implIncludes{"FloatRect.h"} = 1 if $type eq "SVGRect";
+ $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";
+ $implIncludes{"JSCustomVoidCallback.h"} = 1 if $type eq "VoidCallback";
+ $implIncludes{"Event.h"} = 1 if $type eq "Event";
+
+ # Default, assume autogenerated type conversion routines
+ $implIncludes{"JS$type.h"} = 1;
+ return "to$type($value)";
+}
+
+sub NativeToJSValue
+{
+ my $signature = shift;
+ my $inFunctionCall = shift;
+ my $implClassName = shift;
+ my $implClassNameForValueConversion = shift;
+ my $value = shift;
+ my $thisValue = shift;
+
+ my $type = $codeGenerator->StripModule($signature->type);
+
+ return "jsBoolean($value)" if $type eq "boolean";
+
+ if ($codeGenerator->IsPrimitiveType($type) or $type eq "SVGPaintType" or $type eq "DOMTimeStamp") {
+ $implKJSInclude{"JSNumberCell.h"} = 1;
+ return "jsNumber(exec, $value)";
+ }
+
+ if ($codeGenerator->IsStringType($type)) {
+ $implIncludes{"KURL.h"} = 1;
+ my $conv = $signature->extendedAttributes->{"ConvertNullStringTo"};
+ if (defined $conv) {
+ return "jsStringOrNull(exec, $value)" if $conv eq "Null";
+ return "jsStringOrUndefined(exec, $value)" if $conv eq "Undefined";
+ return "jsStringOrFalse(exec, $value)" if $conv eq "False";
+
+ die "Unknown value for ConvertNullStringTo extended attribute";
+ }
+ $implKJSInclude{"JSString.h"} = 1;
+ return "jsString(exec, $value)";
+ }
+
+ if ($type eq "RGBColor") {
+ $implIncludes{"JS$type.h"} = 1;
+ return "getJSRGBColor(exec, $value)";
+ }
+
+ if ($codeGenerator->IsPodType($type)) {
+ $implIncludes{"JS$type.h"} = 1;
+
+ my $nativeType = GetNativeType($type);
+
+ my $getter = $value;
+ $getter =~ s/imp->//;
+ $getter =~ s/\(\)//;
+
+ my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
+
+ # Function calls will never return 'modifyable' POD types (ie. SVGRect getBBox()) - no need to keep track changes to the returned SVGRect
+ if ($inFunctionCall eq 0
+ and not $codeGenerator->IsSVGAnimatedType($implClassName)
+ and $codeGenerator->IsPodTypeWithWriteableProperties($type)
+ and not defined $signature->extendedAttributes->{"Immutable"}) {
+ if ($codeGenerator->IsPodType($implClassName)) {
+ return "toJS(exec, JSSVGStaticPODTypeWrapperWithPODTypeParent<$nativeType, $implClassName>::create($value, $thisValue->impl()).get(), $thisValue->context())";
+ } else {
+ return "toJS(exec, JSSVGStaticPODTypeWrapperWithParent<$nativeType, $implClassName>::create(imp, &${implClassName}::$getter, &${implClassName}::$setter).get(), imp)";
+ }
+ }
+
+ if ($implClassNameForValueConversion eq "") {
+ if (IsSVGTypeNeedingContextParameter($implClassName)) {
+ return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), castedThisObj->context())" if $inFunctionCall eq 1;
+
+ # Special case: SVGZoomEvent - it doesn't have a context, but it's no problem, as there are no readwrite props
+ return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), 0)" if $implClassName eq "SVGZoomEvent";
+ return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), $thisValue->context())";
+ } else {
+ return "toJS(exec, JSSVGStaticPODTypeWrapper<$nativeType>::create($value).get(), imp)";
+ }
+ } else { # These classes, always have a m_context pointer!
+ return "toJS(exec, JSSVGDynamicPODTypeWrapperCache<$nativeType, $implClassNameForValueConversion>::lookupOrCreateWrapper(imp, &${implClassNameForValueConversion}::$getter, &${implClassNameForValueConversion}::$setter).get(), $thisValue->context())";
+ }
+ }
+
+ if ($codeGenerator->IsSVGAnimatedType($type)) {
+ $value =~ s/\(\)//;
+ $value .= "Animated()";
+ }
+
+ if ($type eq "CSSStyleDeclaration") {
+ $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
+ }
+
+ if ($type eq "NamedNodeMap") {
+ $implIncludes{"NamedAttrMap.h"} = 1;
+ }
+
+ if ($type eq "NodeList") {
+ $implIncludes{"NameNodeList.h"} = 1;
+ }
+
+ if ($type eq "DOMObject") {
+ $implIncludes{"JSCanvasRenderingContext2D.h"} = 1;
+ } elsif ($type =~ /SVGPathSeg/) {
+ $implIncludes{"JS$type.h"} = 1;
+ $joinedName = $type;
+ $joinedName =~ s/Abs|Rel//;
+ $implIncludes{"$joinedName.h"} = 1;
+ } else {
+ # Default, include header with same name.
+ $implIncludes{"JS$type.h"} = 1;
+ $implIncludes{"$type.h"} = 1;
+ }
+
+ return $value if $codeGenerator->IsSVGAnimatedType($type);
+
+ if (IsSVGTypeNeedingContextParameter($type)) {
+ if (IsSVGTypeNeedingContextParameter($implClassName)) {
+ return "toJS(exec, WTF::getPtr($value), $thisValue->context())";
+ } else {
+ return "toJS(exec, WTF::getPtr($value), imp)";
+ }
+ }
+
+ if ($signature->extendedAttributes->{"ReturnsNew"}) {
+ return "toJSNewlyCreated(exec, WTF::getPtr($value))";
+ }
+
+ return "toJS(exec, WTF::getPtr($value))";
+}
+
+sub ceilingToPowerOf2
+{
+ my ($size) = @_;
+
+ my $powerOf2 = 1;
+ while ($size > $powerOf2) {
+ $powerOf2 <<= 1;
+ }
+
+ return $powerOf2;
+}
+
+# Internal Helper
+sub GenerateHashTable
+{
+ my $object = shift;
+
+ my $name = shift;
+ my $keys = shift;
+ my $specials = shift;
+ my $value1 = shift;
+ my $value2 = shift;
+
+ my @hashes = ();
+ foreach my $key (@{$keys}) {
+ push @hashes, $object->GenerateHashValue($key);
+ }
+
+ # Collect hashtable information
+ my $size;
+tableSizeLoop:
+ for ($size = ceilingToPowerOf2(scalar @{$keys}); ; $size += $size) {
+ my @table = ();
+ my $i = 0;
+ foreach my $hash (@hashes) {
+ my $h = $hash % $size;
+ next tableSizeLoop if defined $table[$h];
+ $table[$h] = $i++;
+ }
+ last;
+ }
+
+ # Start outputing the hashtables
+ my $nameEntries = "${name}Values";
+ $nameEntries =~ s/:/_/g;
+
+ if (($name =~ /Prototype/) or ($name =~ /Constructor/)) {
+ my $type = $name;
+ my $implClass;
+
+ if ($name =~ /Prototype/) {
+ $type =~ s/Prototype.*//;
+ $implClass = $type; $implClass =~ s/Wrapper$//;
+ push(@implContent, "/* Hash table for prototype */\n");
+ } else {
+ $type =~ s/Constructor.*//;
+ $implClass = $type; $implClass =~ s/Constructor$//;
+ push(@implContent, "/* Hash table for constructor */\n");
+ }
+ } else {
+ push(@implContent, "/* Hash table */\n");
+ }
+
+ # Dump the hash table
+ my $count = scalar @{$keys} + 1;
+ push(@implContent, "\nstatic const HashTableValue $nameEntries\[$count\] =\n\{\n");
+ my $i = 0;
+ foreach my $key (@{$keys}) {
+ push(@implContent, " { \"$key\", @$specials[$i], (intptr_t)@$value1[$i], (intptr_t)@$value2[$i] },\n");
+ ++$i;
+ }
+ push(@implContent, " { 0, 0, 0, 0 }\n");
+ push(@implContent, "};\n\n");
+ my $sizeMask = $size - 1;
+ push(@implContent, "static const HashTable $name = { $sizeMask, $nameEntries, 0 };\n\n");
+}
+
+# Internal helper
+sub GenerateHashValue
+{
+ my $object = shift;
+
+ @chars = split(/ */, $_[0]);
+
+ # This hash is designed to work on 16-bit chunks at a time. But since the normal case
+ # (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
+ # were 16-bit chunks, which should give matching results
+
+ my $EXP2_32 = 4294967296;
+
+ my $hash = 0x9e3779b9;
+ my $l = scalar @chars; #I wish this was in Ruby --- Maks
+ my $rem = $l & 1;
+ $l = $l >> 1;
+
+ my $s = 0;
+
+ # Main loop
+ for (; $l > 0; $l--) {
+ $hash += ord($chars[$s]);
+ my $tmp = leftShift(ord($chars[$s+1]), 11) ^ $hash;
+ $hash = (leftShift($hash, 16)% $EXP2_32) ^ $tmp;
+ $s += 2;
+ $hash += $hash >> 11;
+ $hash %= $EXP2_32;
+ }
+
+ # Handle end case
+ if ($rem != 0) {
+ $hash += ord($chars[$s]);
+ $hash ^= (leftShift($hash, 11)% $EXP2_32);
+ $hash += $hash >> 17;
+ }
+
+ # Force "avalanching" of final 127 bits
+ $hash ^= leftShift($hash, 3);
+ $hash += ($hash >> 5);
+ $hash = ($hash% $EXP2_32);
+ $hash ^= (leftShift($hash, 2)% $EXP2_32);
+ $hash += ($hash >> 15);
+ $hash = $hash% $EXP2_32;
+ $hash ^= (leftShift($hash, 10)% $EXP2_32);
+
+ # this avoids ever returning a hash code of 0, since that is used to
+ # signal "hash not computed yet", using a value that is likely to be
+ # effectively the same as 0 when the low bits are masked
+ $hash = 0x80000000 if ($hash == 0);
+
+ return $hash;
+}
+
+# Internal helper
+sub WriteData
+{
+ if (defined($IMPL)) {
+ # Write content to file.
+ print $IMPL @implContentHeader;
+
+ foreach my $implInclude (sort keys(%implIncludes)) {
+ my $checkType = $implInclude;
+ $checkType =~ s/\.h//;
+
+ print $IMPL "#include \"$implInclude\"\n" unless $codeGenerator->IsSVGAnimatedType($checkType);
+ }
+
+ print $IMPL "\n";
+
+ foreach my $implKJSInclude (sort keys(%implKJSInclude)) {
+ print $IMPL "#include <runtime/$implKJSInclude>\n";
+ }
+
+ print $IMPL @implContent;
+ close($IMPL);
+ undef($IMPL);
+
+ @implContentHeader = ();
+ @implContent = ();
+ %implIncludes = ();
+ %implKJSIncludes = ();
+ }
+
+ if (defined($HEADER)) {
+ # Write content to file.
+ print $HEADER @headerContentHeader;
+
+ foreach my $headerInclude (sort keys(%headerIncludes)) {
+ print $HEADER "#include \"$headerInclude\"\n";
+ }
+
+ print $HEADER @headerContent;
+ close($HEADER);
+ undef($HEADER);
+
+ @headerContentHeader = ();
+ @headerContent = ();
+ %headerIncludes = ();
+ }
+}
+
+sub constructorFor
+{
+ my $className = shift;
+ my $protoClassName = shift;
+ my $interfaceName = shift;
+ my $visibleClassName = shift;
+ my $canConstruct = shift;
+
+my $implContent = << "EOF";
+class ${className}Constructor : public DOMObject {
+public:
+ ${className}Constructor(ExecState* exec)
+ : DOMObject(${className}Constructor::createStructureID(exec->lexicalGlobalObject()->objectPrototype()))
+ {
+ putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec), None);
+ }
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual const ClassInfo* classInfo() const { return &s_info; }
+ static const ClassInfo s_info;
+
+ static PassRefPtr<StructureID> createStructureID(JSValue* proto)
+ {
+ return StructureID::create(proto, TypeInfo(ObjectType, ImplementsHasInstance));
+ }
+EOF
+
+ if ($canConstruct) {
+$implContent .= << "EOF";
+ static JSObject* construct(ExecState* exec, JSObject*, const ArgList&)
+ {
+ return asObject(toJS(exec, ${interfaceName}::create()));
+ }
+ virtual ConstructType getConstructData(ConstructData& constructData)
+ {
+ constructData.native.function = construct;
+ return ConstructTypeHost;
+ }
+EOF
+ }
+
+$implContent .= << "EOF";
+};
+
+const ClassInfo ${className}Constructor::s_info = { "${visibleClassName}Constructor", 0, &${className}ConstructorTable, 0 };
+
+bool ${className}Constructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<${className}Constructor, DOMObject>(exec, &${className}ConstructorTable, this, propertyName, slot);
+}
+
+EOF
+
+ $implKJSInclude{"JSNumberCell.h"} = 1;
+
+ return $implContent;
+}
+
+1;
diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm
new file mode 100644
index 0000000..7969b2c
--- /dev/null
+++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm
@@ -0,0 +1,1731 @@
+#
+# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
+# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
+# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
+# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
+# Copyright (C) 2006, 2007, 2008 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 CodeGeneratorObjC;
+
+use File::stat;
+
+# Global Variables
+my $module = "";
+my $outputDir = "";
+my %publicInterfaces = ();
+my $newPublicClass = 0;
+my $interfaceAvailabilityVersion = "";
+my $isProtocol = 0;
+my $noImpl = 0;
+my @ivars = ();
+
+my @headerContentHeader = ();
+my @headerContent = ();
+my %headerForwardDeclarations = ();
+my %headerForwardDeclarationsForProtocols = ();
+
+my @privateHeaderContentHeader = ();
+my @privateHeaderContent = ();
+my %privateHeaderForwardDeclarations = ();
+my %privateHeaderForwardDeclarationsForProtocols = ();
+
+my @internalHeaderContent = ();
+
+my @implContentHeader = ();
+my @implContent = ();
+my %implIncludes = ();
+
+# Hashes
+my %protocolTypeHash = ("XPathNSResolver" => 1, "EventListener" => 1, "EventTarget" => 1, "NodeFilter" => 1,
+ "SVGLocatable" => 1, "SVGTransformable" => 1, "SVGStylable" => 1, "SVGFilterPrimitiveStandardAttributes" => 1,
+ "SVGTests" => 1, "SVGLangSpace" => 1, "SVGExternalResourcesRequired" => 1, "SVGURIReference" => 1,
+ "SVGZoomAndPan" => 1, "SVGFitToViewBox" => 1, "SVGAnimatedPathData" => 1, "SVGAnimatedPoints" => 1,
+ "ElementTimeControl" => 1);
+my %nativeObjCTypeHash = ("URL" => 1, "Color" => 1);
+
+# FIXME: this should be replaced with a function that recurses up the tree
+# to find the actual base type.
+my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1,
+ "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1,
+ "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1,
+ "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1,
+ "SVGAngle" => 1, "SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, "SVGAnimatedEnumeration" => 1,
+ "SVGAnimatedInteger" => 1, "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1,
+ "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, "SVGAnimatedPoints" => 1,
+ "SVGAnimatedPreserveAspectRatio" => 1, "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1,
+ "SVGAnimatedTransformList" => 1, "SVGLength" => 1, "SVGLengthList" => 1, "SVGMatrix" => 1,
+ "SVGNumber" => 1, "SVGNumberList" => 1, "SVGPathSeg" => 1, "SVGPathSegList" => 1, "SVGPoint" => 1,
+ "SVGPointList" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1, "SVGRenderingIntent" => 1,
+ "SVGStringList" => 1, "SVGTransform" => 1, "SVGTransformList" => 1, "SVGUnitTypes" => 1);
+
+# Constants
+my $buildingForTigerOrEarlier = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} <= 10.4;
+my $buildingForLeopardOrLater = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} >= 10.5;
+my $exceptionInit = "WebCore::ExceptionCode ec = 0;";
+my $exceptionRaiseOnError = "WebCore::raiseOnDOMError(ec);";
+my $assertMainThread = "{ DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheck(); }";
+
+my %conflictMethod = (
+ # FIXME: Add C language keywords?
+ # FIXME: Add other predefined types like "id"?
+
+ "callWebScriptMethod:withArguments:" => "WebScriptObject",
+ "evaluateWebScript:" => "WebScriptObject",
+ "removeWebScriptKey:" => "WebScriptObject",
+ "setException:" => "WebScriptObject",
+ "setWebScriptValueAtIndex:value:" => "WebScriptObject",
+ "stringRepresentation" => "WebScriptObject",
+ "webScriptValueAtIndex:" => "WebScriptObject",
+
+ "autorelease" => "NSObject",
+ "awakeAfterUsingCoder:" => "NSObject",
+ "class" => "NSObject",
+ "classForCoder" => "NSObject",
+ "conformsToProtocol:" => "NSObject",
+ "copy" => "NSObject",
+ "copyWithZone:" => "NSObject",
+ "dealloc" => "NSObject",
+ "description" => "NSObject",
+ "doesNotRecognizeSelector:" => "NSObject",
+ "encodeWithCoder:" => "NSObject",
+ "finalize" => "NSObject",
+ "forwardInvocation:" => "NSObject",
+ "hash" => "NSObject",
+ "init" => "NSObject",
+ "initWithCoder:" => "NSObject",
+ "isEqual:" => "NSObject",
+ "isKindOfClass:" => "NSObject",
+ "isMemberOfClass:" => "NSObject",
+ "isProxy" => "NSObject",
+ "methodForSelector:" => "NSObject",
+ "methodSignatureForSelector:" => "NSObject",
+ "mutableCopy" => "NSObject",
+ "mutableCopyWithZone:" => "NSObject",
+ "performSelector:" => "NSObject",
+ "release" => "NSObject",
+ "replacementObjectForCoder:" => "NSObject",
+ "respondsToSelector:" => "NSObject",
+ "retain" => "NSObject",
+ "retainCount" => "NSObject",
+ "self" => "NSObject",
+ "superclass" => "NSObject",
+ "zone" => "NSObject",
+);
+
+my $fatalError = 0;
+
+# Default Licence Templates
+my $headerLicenceTemplate = << "EOF";
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig\@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+EOF
+
+my $implementationLicenceTemplate = << "EOF";
+/*
+ * This file is part of the WebKit open source project.
+ * This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+EOF
+
+# Default constructor
+sub new
+{
+ my $object = shift;
+ my $reference = { };
+
+ $codeGenerator = shift;
+ $outputDir = shift;
+
+ bless($reference, $object);
+ return $reference;
+}
+
+sub finish
+{
+ my $object = shift;
+}
+
+sub ReadPublicInterfaces
+{
+ my $class = shift;
+ my $superClass = shift;
+ my $defines = shift;
+ my $isProtocol = shift;
+
+ my $found = 0;
+ my $actualSuperClass;
+ %publicInterfaces = ();
+
+ my $fileName = "WebCore/bindings/objc/PublicDOMInterfaces.h";
+ open FILE, "-|", "/usr/bin/gcc", "-E", "-P", "-x", "objective-c",
+ (map { "-D$_" } split(/ /, $defines)), "-DOBJC_CODE_GENERATION", $fileName or die "Could not open $fileName";
+ my @documentContent = <FILE>;
+ close FILE;
+
+ foreach $line (@documentContent) {
+ if (!$isProtocol && $line =~ /^\s*\@interface\s*$class\s*:\s*(\w+)\s*([A-Z0-9_]*)/) {
+ if ($superClass ne $1) {
+ warn "Public API change. Superclass for \"$class\" differs ($1 != $superClass)";
+ $fatalError = 1;
+ }
+
+ $interfaceAvailabilityVersion = $2 if defined $2;
+ $found = 1;
+ next;
+ } elsif ($isProtocol && $line =~ /^\s*\@protocol $class\s*<[^>]+>\s*([A-Z0-9_]*)/) {
+ $interfaceAvailabilityVersion = $1 if defined $1;
+ $found = 1;
+ next;
+ }
+
+ last if $found and $line =~ /^\s?\@end\s?$/;
+
+ if ($found) {
+ # trim whitspace
+ $line =~ s/^\s+//;
+ $line =~ s/\s+$//;
+
+ my $availabilityMacro = "";
+ $line =~ s/\s([A-Z0-9_]+)\s*;$/;/;
+ $availabilityMacro = $1 if defined $1;
+
+ $publicInterfaces{$line} = $availabilityMacro if length $line;
+ }
+ }
+
+ # If this class was not found in PublicDOMInterfaces.h then it should be considered as an entirely new public class.
+ $newPublicClass = !$found;
+ $interfaceAvailabilityVersion = "WEBKIT_VERSION_LATEST" if $newPublicClass;
+}
+
+# Params: 'domClass' struct
+sub GenerateInterface
+{
+ my $object = shift;
+ my $dataNode = shift;
+ my $defines = shift;
+
+ $fatalError = 0;
+
+ my $name = $dataNode->name;
+ my $className = GetClassName($name);
+ my $parentClassName = "DOM" . GetParentImplClassName($dataNode);
+ $isProtocol = $dataNode->extendedAttributes->{ObjCProtocol};
+ $noImpl = $dataNode->extendedAttributes->{ObjCCustomImplementation} || $isProtocol;
+
+ ReadPublicInterfaces($className, $parentClassName, $defines, $isProtocol);
+
+ # Start actual generation..
+ $object->GenerateHeader($dataNode);
+ $object->GenerateImplementation($dataNode) unless $noImpl;
+
+ # Write changes.
+ $object->WriteData("DOM" . $name);
+
+ # Check for missing public API
+ if (keys %publicInterfaces > 0) {
+ my $missing = join("\n", keys %publicInterfaces);
+ warn "Public API change. There are missing public properties and/or methods from the \"$className\" class.\n$missing\n";
+ $fatalError = 1;
+ }
+
+ die if $fatalError;
+}
+
+# Params: 'idlDocument' struct
+sub GenerateModule
+{
+ my $object = shift;
+ my $dataNode = shift;
+
+ $module = $dataNode->module;
+}
+
+sub GetClassName
+{
+ my $name = $codeGenerator->StripModule(shift);
+
+ # special cases
+ return "NSString" if $codeGenerator->IsStringType($name);
+ return "NS$name" if IsNativeObjCType($name);
+ return "BOOL" if $name eq "boolean";
+ return "unsigned" if $name eq "unsigned long";
+ return "int" if $name eq "long";
+ return "DOMAbstractView" if $name eq "DOMWindow";
+ return $name if $codeGenerator->IsPrimitiveType($name) or $name eq "DOMImplementation" or $name eq "DOMTimeStamp";
+
+ # Default, assume Objective-C type has the same type name as
+ # idl type prefixed with "DOM".
+ return "DOM$name";
+}
+
+sub GetClassHeaderName
+{
+ my $name = shift;
+
+ return "DOMDOMImplementation" if $name eq "DOMImplementation";
+ return $name;
+}
+
+sub GetImplClassName
+{
+ my $name = $codeGenerator->StripModule(shift);
+
+ return "DOMImplementationFront" if $name eq "DOMImplementation";
+ return "DOMWindow" if $name eq "AbstractView";
+ return $name;
+}
+
+sub GetParentImplClassName
+{
+ my $dataNode = shift;
+
+ return "Object" if @{$dataNode->parents} eq 0;
+
+ my $parent = $codeGenerator->StripModule($dataNode->parents(0));
+
+ # special cases
+ return "Node" if $parent eq "EventTargetNode";
+ return "Object" if $parent eq "HTMLCollection";
+
+ return $parent;
+}
+
+sub GetParentAndProtocols
+{
+ my $dataNode = shift;
+ my $numParents = @{$dataNode->parents};
+
+ my $parent = "";
+ my @protocols = ();
+ if ($numParents eq 0) {
+ if ($isProtocol) {
+ push(@protocols, "NSObject");
+ push(@protocols, "NSCopying") if $dataNode->name eq "EventTarget";
+ } else {
+ $parent = "DOMObject";
+ }
+ } elsif ($numParents eq 1) {
+ my $parentName = $codeGenerator->StripModule($dataNode->parents(0));
+ if ($isProtocol) {
+ die "Parents of protocols must also be protocols." unless IsProtocolType($parentName);
+ push(@protocols, "DOM" . $parentName);
+ } else {
+ if (IsProtocolType($parentName)) {
+ push(@protocols, "DOM" . $parentName);
+ } elsif ($parentName eq "EventTargetNode") {
+ $parent = "DOMNode";
+ } elsif ($parentName eq "HTMLCollection") {
+ $parent = "DOMObject";
+ } else {
+ $parent = "DOM" . $parentName;
+ }
+ }
+ } else {
+ my @parents = @{$dataNode->parents};
+ my $firstParent = $codeGenerator->StripModule(shift(@parents));
+ if (IsProtocolType($firstParent)) {
+ push(@protocols, "DOM" . $firstParent);
+ if (!$isProtocol) {
+ $parent = "DOMObject";
+ }
+ } else {
+ $parent = "DOM" . $firstParent;
+ }
+
+ foreach my $parentName (@parents) {
+ $parentName = $codeGenerator->StripModule($parentName);
+ die "Everything past the first class should be a protocol!" unless IsProtocolType($parentName);
+
+ push(@protocols, "DOM" . $parentName);
+ }
+ }
+
+ return ($parent, @protocols);
+}
+
+sub GetBaseClass
+{
+ $parent = shift;
+
+ return $parent if $parent eq "Object" or IsBaseType($parent);
+ return "Event" if $parent eq "UIEvent";
+ return "CSSValue" if $parent eq "SVGColor" or $parent eq "CSSValueList";
+ return "Node";
+}
+
+sub IsBaseType
+{
+ my $type = shift;
+
+ return 1 if $baseTypeHash{$type};
+ return 0;
+}
+
+sub IsProtocolType
+{
+ my $type = shift;
+
+ return 1 if $protocolTypeHash{$type};
+ return 0;
+}
+
+sub IsNativeObjCType
+{
+ my $type = shift;
+
+ return 1 if $nativeObjCTypeHash{$type};
+ return 0;
+}
+
+sub GetObjCType
+{
+ my $type = shift;
+ my $name = GetClassName($type);
+
+ return "id <$name>" if IsProtocolType($type);
+ return $name if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp";
+ return "unsigned short" if $type eq "CompareHow" or $type eq "SVGPaintType";
+ return "$name *";
+}
+
+sub GetPropertyAttributes
+{
+ my $type = $codeGenerator->StripModule(shift);
+ my $readOnly = shift;
+
+ my @attributes = ();
+
+ push(@attributes, "readonly") if $readOnly;
+
+# FIXME: uncomment these lines once <rdar://problem/4996504> is fixed.
+# unless ($readOnly) {
+ if ($codeGenerator->IsStringType($type) || IsNativeObjCType($type)) {
+ push(@attributes, "copy");
+ } elsif ($codeGenerator->IsPodType($type) || $codeGenerator->IsSVGAnimatedType($type)) {
+ push(@attributes, "retain");
+ } elsif (!$codeGenerator->IsStringType($type) && !$codeGenerator->IsPrimitiveType($type) && $type ne "DOMTimeStamp" && $type ne "CompareHow" && $type ne "SVGPaintType") {
+ push(@attributes, "retain");
+ }
+# }
+
+ return "" unless @attributes > 0;
+ return "(" . join(", ", @attributes) . ")";
+}
+
+sub GetObjCTypeMaker
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ return "" if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type) or IsNativeObjCType($type);
+ return "_wrapAbstractView" if $type eq "DOMWindow";
+ return "_wrap$type";
+}
+
+sub GetObjCTypeGetterName
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ my $typeGetter = "";
+ if ($type =~ /^(HTML|CSS|SVG)/ or $type eq "DOMImplementation" or $type eq "CDATASection" or $type eq "RGBColor") {
+ $typeGetter = $type;
+ } elsif ($type =~ /^XPath(.+)/) {
+ $typeGetter = "xpath" . $1;
+ } elsif ($type eq "DOMWindow") {
+ $typeGetter = "abstractView";
+ } else {
+ $typeGetter = lcfirst($type);
+ }
+
+ # put into the form "_fooBar" for type FooBar.
+ return "_" . $typeGetter;
+}
+
+sub GetObjCTypeGetter
+{
+ my $argName = shift;
+ my $type = $codeGenerator->StripModule(shift);
+
+ return $argName if $codeGenerator->IsPrimitiveType($type) or $codeGenerator->IsStringType($type) or IsNativeObjCType($type);
+ return $argName . "EventTarget" if $type eq "EventTarget";
+ return "static_cast<WebCore::Range::CompareHow>($argName)" if $type eq "CompareHow";
+ return "static_cast<WebCore::SVGPaint::SVGPaintType>($argName)" if $type eq "SVGPaintType";
+
+ my $typeGetterMethodName = GetObjCTypeGetterName($type);
+
+ return "WTF::getPtr(nativeEventListener)" if $type eq "EventListener";
+ return "WTF::getPtr(nativeNodeFilter)" if $type eq "NodeFilter";
+ return "WTF::getPtr(nativeResolver)" if $type eq "XPathNSResolver";
+ return "[$argName $typeGetterMethodName]";
+}
+
+sub GetInternalTypeGetterSignature
+{
+ my ($interfaceName, $podType) = @_;
+
+ my $implClassNameWithNamespace = "WebCore::" . GetImplClassName($interfaceName);
+ my $podTypeWithNamespace;
+ if ($podType) {
+ $podTypeWithNamespace = ($podType eq "float") ? "$podType" : "WebCore::$podType";
+ }
+
+ # - Type-Getter
+ # - (WebCore::FooBar *)_fooBar for implementation class FooBar
+ my $typeGetterName = GetObjCTypeGetterName($interfaceName);
+ return "- " . ($podType ? "($podTypeWithNamespace)" : "($implClassNameWithNamespace *)") . $typeGetterName;
+}
+
+sub GetInternalTypeMakerSignature
+{
+ my ($interfaceName, $podType) = @_;
+
+ my $className = GetClassName($interfaceName);
+ my $implClassNameWithNamespace = "WebCore::" . GetImplClassName($interfaceName);
+ my $podTypeWithNamespace;
+ if ($podType) {
+ $podTypeWithNamespace = ($podType eq "float") ? "$podType" : "WebCore::$podType";
+ }
+
+ my @ivarsToRetain = ();
+ my $ivarsToInit = "";
+ my $typeMakerSigAddition = "";
+ if (@ivars > 0) {
+ my @ivarsInitSig = ();
+ my @ivarsInitCall = ();
+ foreach $attribute (@ivars) {
+ my $name = $attribute->signature->name;
+ my $memberName = "m_" . $name;
+ my $varName = "in" . $name;
+ my $type = GetObjCType($attribute->signature->type);
+ push(@ivarsInitSig, "$name:($type)$varName");
+ push(@ivarsInitCall, "$name:$varName");
+ push(@ivarsToRetain, " $memberName = [$varName retain];\n");
+ }
+ $ivarsToInit = " " . join(" ", @ivarsInitCall);
+ $typeMakerSigAddition = " " . join(" ", @ivarsInitSig);
+ }
+
+ my $typeMakerName = GetObjCTypeMaker($interfaceName);
+ return ("+ ($className *)$typeMakerName:(" . ($podType ? "$podTypeWithNamespace" : "$implClassNameWithNamespace *") . ")impl" . $typeMakerSigAddition,
+ $typeMakerSigAddition,
+ $ivarsToInit);
+}
+
+sub AddForwardDeclarationsForType
+{
+ my $type = $codeGenerator->StripModule(shift);
+ my $public = shift;
+
+ return if $codeGenerator->IsNonPointerType($type) ;
+
+ my $class = GetClassName($type);
+
+ if (IsProtocolType($type)) {
+ $headerForwardDeclarationsForProtocols{$class} = 1 if $public;
+ $privateHeaderForwardDeclarationsForProtocols{$class} = 1 if !$public and !$headerForwardDeclarationsForProtocols{$class};
+ return;
+ }
+
+ $headerForwardDeclarations{$class} = 1 if $public;
+
+ # Private headers include the public header, so only add a forward declaration to the private header
+ # if the public header does not already have the same forward declaration.
+ $privateHeaderForwardDeclarations{$class} = 1 if !$public and !$headerForwardDeclarations{$class};
+}
+
+sub AddIncludesForType
+{
+ my $type = $codeGenerator->StripModule(shift);
+
+ return if $codeGenerator->IsNonPointerType($type) or IsNativeObjCType($type);
+
+ if ($codeGenerator->IsStringType($type)) {
+ $implIncludes{"KURL.h"} = 1;
+ return;
+ }
+
+ if ($type eq "RGBColor") {
+ $implIncludes{"Color.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ if ($type eq "DOMWindow") {
+ $implIncludes{"DOMAbstractView.h"} = 1;
+ $implIncludes{"$type.h"} = 1;
+ return;
+ }
+
+ if ($type eq "DOMImplementation") {
+ $implIncludes{"DOMImplementationFront.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ if ($type eq "EventTarget") {
+ $implIncludes{"EventTargetNode.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ if ($codeGenerator->IsSVGAnimatedType($type)) {
+ $implIncludes{"SVGAnimatedTemplate.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ if ($type eq "SVGRect") {
+ $implIncludes{"FloatRect.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ if ($type eq "SVGPoint") {
+ $implIncludes{"FloatPoint.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ if ($type eq "SVGMatrix") {
+ $implIncludes{"AffineTransform.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ $implIncludes{"SVGException.h"} = 1;
+ return;
+ }
+
+ if ($type eq "SVGNumber") {
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ if ($type =~ /(\w+)(Abs|Rel)$/) {
+ $implIncludes{"$1.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+ return;
+ }
+
+ $implIncludes{"ObjCEventListener.h"} = 1 if $type eq "EventListener";
+ $implIncludes{"ObjCNodeFilterCondition.h"} = 1 if $type eq "NodeFilter";
+ $implIncludes{"DOMCustomXPathNSResolver.h"} = 1 if $type eq "XPathNSResolver";
+
+ # FIXME: won't compile without these
+ $implIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration";
+ $implIncludes{"NamedAttrMap.h"} = 1 if $type eq "NamedNodeMap";
+ $implIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList";
+
+ # Default, include the same named file (the implementation) and the same name prefixed with "DOM".
+ $implIncludes{"$type.h"} = 1;
+ $implIncludes{"DOM$type.h"} = 1;
+}
+
+sub GenerateHeader
+{
+ my $object = shift;
+ my $dataNode = shift;
+
+ my $interfaceName = $dataNode->name;
+ my $className = GetClassName($interfaceName);
+
+ my $parentName = "";
+ my @protocolsToImplement = ();
+ ($parentName, @protocolsToImplement) = GetParentAndProtocols($dataNode);
+
+ my $numConstants = @{$dataNode->constants};
+ my $numAttributes = @{$dataNode->attributes};
+ my $numFunctions = @{$dataNode->functions};
+
+ # - Add default header template
+ @headerContentHeader = split("\r", $headerLicenceTemplate);
+ push(@headerContentHeader, "\n");
+
+ # - INCLUDES -
+ my $includedWebKitAvailabilityHeader = 0;
+ unless ($isProtocol) {
+ my $parentHeaderName = GetClassHeaderName($parentName);
+ push(@headerContentHeader, "#import <WebCore/$parentHeaderName.h>\n");
+ $includedWebKitAvailabilityHeader = 1;
+ }
+
+ foreach my $parentProtocol (@protocolsToImplement) {
+ next if $parentProtocol =~ /^NS/;
+ $parentProtocol = GetClassHeaderName($parentProtocol);
+ push(@headerContentHeader, "#import <WebCore/$parentProtocol.h>\n");
+ $includedWebKitAvailabilityHeader = 1;
+ }
+
+ # Special case needed for legacy support of DOMRange
+ if ($interfaceName eq "Range") {
+ push(@headerContentHeader, "#import <WebCore/DOMCore.h>\n");
+ push(@headerContentHeader, "#import <WebCore/DOMDocument.h>\n");
+ push(@headerContentHeader, "#import <WebCore/DOMRangeException.h>\n");
+ $includedWebKitAvailabilityHeader = 1;
+ }
+
+ push(@headerContentHeader, "#import <JavaScriptCore/WebKitAvailability.h>\n") unless $includedWebKitAvailabilityHeader;
+
+ my $interfaceAvailabilityVersionCheck = "#if WEBKIT_VERSION_MAX_ALLOWED >= $interfaceAvailabilityVersion\n\n";
+
+ push(@headerContentHeader, "\n");
+ push(@headerContentHeader, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion;
+
+ # - Add constants.
+ if ($numConstants > 0) {
+ my @headerConstants = ();
+
+ # FIXME: we need a way to include multiple enums.
+ foreach my $constant (@{$dataNode->constants}) {
+ my $constantName = $constant->name;
+ my $constantValue = $constant->value;
+
+ my $output = " DOM_" . $constantName . " = " . $constantValue;
+ push(@headerConstants, $output);
+ }
+
+ my $combinedConstants = join(",\n", @headerConstants);
+
+ # FIXME: the formatting of the enums should line up the equal signs.
+ # FIXME: enums are unconditionally placed in the public header.
+ push(@headerContent, "enum {\n");
+ push(@headerContent, $combinedConstants);
+ push(@headerContent, "\n};\n\n");
+ }
+
+ # - Begin @interface or @protocol
+ my $interfaceDeclaration = ($isProtocol ? "\@protocol $className" : "\@interface $className : $parentName");
+ $interfaceDeclaration .= " <" . join(", ", @protocolsToImplement) . ">" if @protocolsToImplement > 0;
+ $interfaceDeclaration .= "\n";
+
+ push(@headerContent, $interfaceDeclaration);
+
+ my @headerAttributes = ();
+ my @privateHeaderAttributes = ();
+
+ # - Add attribute getters/setters.
+ if ($numAttributes > 0) {
+ # Add ivars, if any, first
+ @ivars = ();
+ foreach my $attribute (@{$dataNode->attributes}) {
+ push(@ivars, $attribute) if $attribute->signature->extendedAttributes->{"ObjCIvar"};
+ }
+
+ if (@ivars > 0) {
+ push(@headerContent, "{\n");
+ foreach my $attribute (@ivars) {
+ my $type = GetObjCType($attribute->signature->type);
+ my $name = "m_" . $attribute->signature->name;
+ my $ivarDeclaration = "$type $name";
+ push(@headerContent, " $ivarDeclaration;\n");
+ }
+ push(@headerContent, "}\n");
+ }
+
+ foreach my $attribute (@{$dataNode->attributes}) {
+ my $attributeName = $attribute->signature->name;
+
+ if ($attributeName eq "id" or $attributeName eq "hash") {
+ # Special case attributes id and hash to be idName and hashName to avoid ObjC naming conflict.
+ $attributeName .= "Name";
+ } elsif ($attributeName eq "frame") {
+ # Special case attribute frame to be frameBorders.
+ $attributeName .= "Borders";
+ }
+
+ my $attributeType = GetObjCType($attribute->signature->type);
+ my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
+
+ my $property = "\@property" . GetPropertyAttributes($attribute->signature->type, $attributeIsReadonly);
+ $property .= " " . $attributeType . ($attributeType =~ /\*$/ ? "" : " ") . $attributeName;
+
+ my $publicInterfaceKey = $property . ";";
+
+ my $availabilityMacro = "";
+ if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) {
+ $availabilityMacro = $publicInterfaces{$publicInterfaceKey};
+ }
+
+ $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if length $availabilityMacro and $buildingForTigerOrEarlier;
+
+ my $declarationSuffix = ";\n";
+ $declarationSuffix = " $availabilityMacro;\n" if length $availabilityMacro;
+
+ my $public = (defined $publicInterfaces{$publicInterfaceKey} or $newPublicClass);
+ delete $publicInterfaces{$publicInterfaceKey};
+
+ AddForwardDeclarationsForType($attribute->signature->type, $public);
+
+ my $setterName = "set" . ucfirst($attributeName) . ":";
+
+ my $conflict = $conflictMethod{$attributeName};
+ if ($conflict) {
+ warn "$className conflicts with $conflict method $attributeName\n";
+ $fatalError = 1;
+ }
+
+ $conflict = $conflictMethod{$setterName};
+ if ($conflict) {
+ warn "$className conflicts with $conflict method $setterName\n";
+ $fatalError = 1;
+ }
+
+ if ($buildingForLeopardOrLater) {
+ $property .= $declarationSuffix;
+ push(@headerAttributes, $property) if $public;
+ push(@privateHeaderAttributes, $property) unless $public;
+ } else {
+ # - GETTER
+ my $getter = "- (" . $attributeType . ")" . $attributeName . $declarationSuffix;
+ push(@headerAttributes, $getter) if $public;
+ push(@privateHeaderAttributes, $getter) unless $public;
+
+ # - SETTER
+ if (!$attributeIsReadonly) {
+ my $setter = "- (void)$setterName(" . $attributeType . ")new" . ucfirst($attributeName) . $declarationSuffix;
+ push(@headerAttributes, $setter) if $public;
+ push(@privateHeaderAttributes, $setter) unless $public;
+ }
+ }
+ }
+
+ push(@headerContent, @headerAttributes) if @headerAttributes > 0;
+ }
+
+ my @headerFunctions = ();
+ my @privateHeaderFunctions = ();
+ my @deprecatedHeaderFunctions = ();
+
+ # - Add functions.
+ if ($numFunctions > 0) {
+ foreach my $function (@{$dataNode->functions}) {
+ my $functionName = $function->signature->name;
+
+ my $returnType = GetObjCType($function->signature->type);
+ my $needsDeprecatedVersion = (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"});
+ my $numberOfParameters = @{$function->parameters};
+ my %typesToForwardDeclare = ($function->signature->type => 1);
+
+ my $parameterIndex = 0;
+ my $functionSig = "- ($returnType)$functionName";
+ my $methodName = $functionName;
+ foreach my $param (@{$function->parameters}) {
+ my $paramName = $param->name;
+ my $paramType = GetObjCType($param->type);
+
+ $typesToForwardDeclare{$param->type} = 1;
+
+ if ($parameterIndex >= 1) {
+ my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"};
+ $paramPrefix = $paramName unless defined($paramPrefix);
+ $functionSig .= " $paramPrefix";
+ $methodName .= $paramPrefix;
+ }
+
+ $functionSig .= ":($paramType)$paramName";
+ $methodName .= ":";
+
+ $parameterIndex++;
+ }
+
+ my $publicInterfaceKey = $functionSig . ";";
+
+ my $conflict = $conflictMethod{$methodName};
+ if ($conflict) {
+ warn "$className conflicts with $conflict method $methodName\n";
+ $fatalError = 1;
+ }
+
+ if ($isProtocol && !$newPublicClass && !defined $publicInterfaces{$publicInterfaceKey}) {
+ warn "Protocol method $publicInterfaceKey is not in PublicDOMInterfaces.h. Protocols require all methods to be public";
+ $fatalError = 1;
+ }
+
+ my $availabilityMacro = "";
+ if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) {
+ $availabilityMacro = $publicInterfaces{$publicInterfaceKey};
+ }
+
+ $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if length $availabilityMacro and $buildingForTigerOrEarlier;
+
+ my $functionDeclaration = $functionSig;
+ $functionDeclaration .= " " . $availabilityMacro if length $availabilityMacro;
+ $functionDeclaration .= ";\n";
+
+ my $public = (defined $publicInterfaces{$publicInterfaceKey} or $newPublicClass);
+ delete $publicInterfaces{$publicInterfaceKey};
+
+ foreach my $type (keys %typesToForwardDeclare) {
+ # add any forward declarations to the public header if a deprecated version will be generated
+ AddForwardDeclarationsForType($type, 1) if $needsDeprecatedVersion;
+ AddForwardDeclarationsForType($type, $public) unless $public and $needsDeprecatedVersion;
+ }
+
+ push(@headerFunctions, $functionDeclaration) if $public;
+ push(@privateHeaderFunctions, $functionDeclaration) unless $public;
+
+ # generate the old style method names with un-named parameters, these methods are deprecated
+ if ($needsDeprecatedVersion) {
+ my $deprecatedFunctionSig = $functionSig;
+ $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names
+
+ $publicInterfaceKey = $deprecatedFunctionSig . ";";
+
+ my $availabilityMacro = "AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0";
+ if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) {
+ $availabilityMacro = $publicInterfaces{$publicInterfaceKey};
+ }
+
+ $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if $buildingForTigerOrEarlier;
+
+ $functionDeclaration = "$deprecatedFunctionSig $availabilityMacro;\n";
+
+ push(@deprecatedHeaderFunctions, $functionDeclaration);
+
+ unless (defined $publicInterfaces{$publicInterfaceKey}) {
+ warn "Deprecated method $publicInterfaceKey is not in PublicDOMInterfaces.h. All deprecated methods need to be public, or should have the OldStyleObjC IDL attribute removed";
+ $fatalError = 1;
+ }
+
+ delete $publicInterfaces{$publicInterfaceKey};
+ }
+ }
+
+ if (@headerFunctions > 0) {
+ push(@headerContent, "\n") if $buildingForLeopardOrLater and @headerAttributes > 0;
+ push(@headerContent, @headerFunctions);
+ }
+ }
+
+ if (@deprecatedHeaderFunctions > 0 && $isProtocol) {
+ push(@headerContent, @deprecatedHeaderFunctions);
+ }
+
+ # - End @interface or @protocol
+ push(@headerContent, "\@end\n");
+
+ if (@deprecatedHeaderFunctions > 0 && !$isProtocol) {
+ # - Deprecated category @interface
+ push(@headerContent, "\n\@interface $className (" . $className . "Deprecated)\n");
+ push(@headerContent, @deprecatedHeaderFunctions);
+ push(@headerContent, "\@end\n");
+ }
+
+ push(@headerContent, "\n#endif\n") if length $interfaceAvailabilityVersion;
+
+ my %alwaysGenerateForNoSVGBuild = map { $_ => 1 } qw(DOMHTMLEmbedElement DOMHTMLObjectElement);
+
+ if (@privateHeaderAttributes > 0 or @privateHeaderFunctions > 0 or exists $alwaysGenerateForNoSVGBuild{$className}) {
+ # - Private category @interface
+ @privateHeaderContentHeader = split("\r", $headerLicenceTemplate);
+ push(@privateHeaderContentHeader, "\n");
+
+ my $classHeaderName = GetClassHeaderName($className);
+ push(@privateHeaderContentHeader, "#import <WebCore/$classHeaderName.h>\n\n");
+ push(@privateHeaderContentHeader, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion;
+
+ @privateHeaderContent = ();
+ push(@privateHeaderContent, "\@interface $className (" . $className . "Private)\n");
+ push(@privateHeaderContent, @privateHeaderAttributes) if @privateHeaderAttributes > 0;
+ push(@privateHeaderContent, "\n") if $buildingForLeopardOrLater and @privateHeaderAttributes > 0 and @privateHeaderFunctions > 0;
+ push(@privateHeaderContent, @privateHeaderFunctions) if @privateHeaderFunctions > 0;
+ push(@privateHeaderContent, "\@end\n");
+
+ push(@privateHeaderContent, "\n#endif\n") if length $interfaceAvailabilityVersion;
+ }
+
+ unless ($isProtocol) {
+ # Generate internal interfaces
+ my $podType = $dataNode->extendedAttributes->{"PODType"};
+ my $typeGetterSig = GetInternalTypeGetterSignature($interfaceName, $podType);
+ my ($typeMakerSig, $typeMakerSigAddition, $ivarsToInit) = GetInternalTypeMakerSignature($interfaceName, $podType);
+
+ # Generate interface definitions.
+ @internalHeaderContent = split("\r", $implementationLicenceTemplate);
+
+ push(@internalHeaderContent, "\n#import <WebCore/$className.h>\n\n");
+ push(@internalHeaderContent, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion;
+
+ if ($interfaceName eq "Node" or $interfaceName eq "SVGElementInstance") {
+ push(@internalHeaderContent, "\@protocol DOMEventTarget;\n\n");
+ }
+
+ if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
+ push(@internalHeaderContent, "#import <WebCore/SVGAnimatedTemplate.h>\n\n");
+ } elsif ($interfaceName eq "RGBColor") {
+ push(@internalHeaderContent, "#import <WebCore/Color.h>\n\n");
+ } else {
+ if ($podType and $podType ne "float") {
+ push(@internalHeaderContent, "namespace WebCore { class $podType; }\n\n");
+ } elsif ($interfaceName eq "Node") {
+ push(@internalHeaderContent, "namespace WebCore { class Node; class EventTarget; }\n\n");
+ } elsif ($interfaceName eq "SVGElementInstance") {
+ push(@internalHeaderContent, "namespace WebCore { class SVGElementInstance; class EventTarget; }\n\n");
+ } else {
+ my $implClassName = GetImplClassName($interfaceName);
+ push(@internalHeaderContent, "namespace WebCore { class $implClassName; }\n\n");
+ }
+ }
+
+ push(@internalHeaderContent, "\@interface $className (WebCoreInternal)\n");
+ push(@internalHeaderContent, $typeGetterSig . ";\n");
+ push(@internalHeaderContent, $typeMakerSig . ";\n");
+
+ if ($interfaceName eq "Node" or $interfaceName eq "SVGElementInstance") {
+ push(@internalHeaderContent, "+ (id <DOMEventTarget>)_wrapEventTarget:(WebCore::EventTarget *)eventTarget;\n");
+ }
+
+ push(@internalHeaderContent, "\@end\n");
+ push(@internalHeaderContent, "\n#endif\n") if length $interfaceAvailabilityVersion;
+ }
+}
+
+sub GenerateImplementation
+{
+ my $object = shift;
+ my $dataNode = shift;
+
+ if (@{$dataNode->parents} > 1) {
+ $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode);
+ }
+
+ my $interfaceName = $dataNode->name;
+ my $className = GetClassName($interfaceName);
+ my $implClassName = GetImplClassName($interfaceName);
+ my $parentImplClassName = GetParentImplClassName($dataNode);
+ my $implClassNameWithNamespace = "WebCore::" . $implClassName;
+ my $baseClass = GetBaseClass($parentImplClassName);
+ my $classHeaderName = GetClassHeaderName($className);
+ my $conditional = $dataNode->extendedAttributes->{"Conditional"};
+
+ my $numAttributes = @{$dataNode->attributes};
+ my $numFunctions = @{$dataNode->functions};
+
+ my $podType = $dataNode->extendedAttributes->{"PODType"};
+ my $podTypeWithNamespace;
+
+ if ($podType) {
+ $podTypeWithNamespace = ($podType eq "float") ? "$podType" : "WebCore::$podType";
+ }
+
+ # - Add default header template.
+ @implContentHeader = split("\r", $implementationLicenceTemplate);
+
+ # - INCLUDES -
+ push(@implContentHeader, "\n#import \"config.h\"\n");
+
+ my $conditionalString;
+ if ($conditional) {
+ $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
+ push(@implContentHeader, "\n#if ${conditionalString}\n");
+ }
+
+ push(@implContentHeader, "\n#import \"$classHeaderName.h\"\n\n");
+
+ push(@implContentHeader, "#import \"ThreadCheck.h\"\n");
+ push(@implContentHeader, "#import <wtf/GetPtr.h>\n\n");
+
+ if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
+ $implIncludes{"SVGAnimatedTemplate.h"} = 1;
+ } elsif ($interfaceName =~ /(\w+)(Abs|Rel)$/) {
+ $implIncludes{"$1.h"} = 1;
+ } else {
+ if (!$podType) {
+ $implIncludes{"$implClassName.h"} = 1;
+ } else {
+ $implIncludes{"$podType.h"} = 1 unless $podType eq "float";
+ }
+ }
+
+ $implIncludes{"DOMInternal.h"} = 1;
+ $implIncludes{"ExceptionHandlers.h"} = 1;
+
+ @implContent = ();
+
+ # add implementation accessor
+ if ($podType) {
+ push(@implContent, "#define IMPL reinterpret_cast<$podTypeWithNamespace*>(_internal)\n\n");
+ } elsif ($parentImplClassName eq "Object") {
+ push(@implContent, "#define IMPL reinterpret_cast<$implClassNameWithNamespace*>(_internal)\n\n");
+ } else {
+ my $baseClassWithNamespace = "WebCore::$baseClass";
+ push(@implContent, "#define IMPL static_cast<$implClassNameWithNamespace*>(reinterpret_cast<$baseClassWithNamespace*>(_internal))\n\n");
+ }
+
+ # START implementation
+ push(@implContent, "\@implementation $className\n\n");
+
+ # Only generate 'dealloc' and 'finalize' methods for direct subclasses of DOMObject.
+ if ($parentImplClassName eq "Object") {
+ my @ivarsToRelease = ();
+ if (@ivars > 0) {
+ foreach $attribute (@ivars) {
+ my $name = "m_" . $attribute->signature->name;
+ push(@ivarsToRelease, " [$name release];\n");
+ }
+ }
+
+ push(@implContent, "- (void)dealloc\n");
+ push(@implContent, "{\n");
+ push(@implContent, " $assertMainThread\n");
+ push(@implContent, @ivarsToRelease);
+ if ($interfaceName eq "NodeIterator") {
+ push(@implContent, " if (_internal) {\n");
+ push(@implContent, " [self detach];\n");
+ push(@implContent, " IMPL->deref();\n");
+ push(@implContent, " };\n");
+ } elsif ($podType) {
+ push(@implContent, " delete IMPL;\n");
+ } else {
+ push(@implContent, " if (_internal)\n");
+ push(@implContent, " IMPL->deref();\n");
+ }
+ push(@implContent, " [super dealloc];\n");
+ push(@implContent, "}\n\n");
+
+ push(@implContent, "- (void)finalize\n");
+ push(@implContent, "{\n");
+ if ($interfaceName eq "NodeIterator") {
+ push(@implContent, " if (_internal) {\n");
+ push(@implContent, " [self detach];\n");
+ push(@implContent, " IMPL->deref();\n");
+ push(@implContent, " };\n");
+ } elsif ($podType) {
+ push(@implContent, " delete IMPL;\n");
+ } else {
+ push(@implContent, " if (_internal)\n");
+ push(@implContent, " IMPL->deref();\n");
+ }
+ push(@implContent, " [super finalize];\n");
+ push(@implContent, "}\n\n");
+
+ }
+
+ %attributeNames = ();
+
+ # - Attributes
+ if ($numAttributes > 0) {
+ foreach my $attribute (@{$dataNode->attributes}) {
+ AddIncludesForType($attribute->signature->type);
+
+ my $idlType = $codeGenerator->StripModule($attribute->signature->type);
+
+ my $attributeName = $attribute->signature->name;
+ my $attributeType = GetObjCType($attribute->signature->type);
+ my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
+ my $attributeClassName = GetClassName($attribute->signature->type);
+
+ my $attributeInterfaceName = $attributeName;
+ if ($attributeName eq "id" or $attributeName eq "hash") {
+ # Special case attributes id and hash to be idName and hashName to avoid ObjC naming conflict.
+ $attributeInterfaceName .= "Name";
+ } elsif ($attributeName eq "frame") {
+ # Special case attribute frame to be frameBorders.
+ $attributeInterfaceName .= "Borders";
+ } elsif ($attributeName eq "ownerDocument") {
+ # FIXME: for now special case attribute ownerDocument to call document, this is incorrect
+ # legacy behavior. (see http://bugs.webkit.org/show_bug.cgi?id=10889)
+ $attributeName = "document";
+ } elsif ($codeGenerator->IsSVGAnimatedType($idlType)) {
+ # Special case for animated types.
+ $attributeName .= "Animated";
+ }
+
+ $attributeNames{$attributeInterfaceName} = 1;
+
+ # - GETTER
+ my $getterSig = "- ($attributeType)$attributeInterfaceName\n";
+ my $hasGetterException = @{$attribute->getterExceptions};
+ my $getterContentHead = "IMPL->" . $codeGenerator->WK_lcfirst($attributeName) . "(";
+ my $getterContentTail = ")";
+
+ # Special case for DOMSVGNumber
+ if ($podType and $podType eq "float") {
+ $getterContentHead = "*IMPL";
+ $getterContentTail = "";
+ }
+
+ # TODO: Handle special case for DOMSVGLength
+ if ($podType and $podType eq "SVGLength" and $attributeName eq "value") {
+ $getterContentHead = "IMPL->value(0 /* FIXME */";
+ }
+
+ my $attributeTypeSansPtr = $attributeType;
+ $attributeTypeSansPtr =~ s/ \*$//; # Remove trailing " *" from pointer types.
+
+ # special case for EventTarget protocol
+ $attributeTypeSansPtr = "DOMNode" if $idlType eq "EventTarget";
+
+ my $typeMaker = GetObjCTypeMaker($attribute->signature->type);
+
+ # Special cases
+ my @customGetterContent = ();
+ if ($attributeTypeSansPtr eq "DOMImplementation") {
+ # FIXME: We have to special case DOMImplementation until DOMImplementationFront is removed
+ $getterContentHead = "[$attributeTypeSansPtr $typeMaker:implementationFront(IMPL";
+ $getterContentTail .= "]";
+ } elsif ($attributeName =~ /(\w+)DisplayString$/) {
+ my $attributeToDisplay = $1;
+ $getterContentHead = "WebCore::displayString(IMPL->$attributeToDisplay(), [self _element]";
+ } elsif ($attributeName =~ /^absolute(\w+)URL$/) {
+ my $typeOfURL = $1;
+ $getterContentHead = "[self _getURLAttribute:";
+ if ($typeOfURL eq "Link") {
+ $getterContentTail = "\@\"href\"]";
+ } elsif ($typeOfURL eq "Image") {
+ if ($interfaceName eq "HTMLObjectElement") {
+ $getterContentTail = "\@\"data\"]";
+ } else {
+ $getterContentTail = "\@\"src\"]";
+ }
+ unless ($interfaceName eq "HTMLImageElement") {
+ push(@customGetterContent, " if (!IMPL->renderer() || !IMPL->renderer()->isImage())\n");
+ push(@customGetterContent, " return nil;\n");
+ $implIncludes{"RenderObject.h"} = 1;
+ }
+ }
+ $implIncludes{"DOMPrivate.h"} = 1;
+ } elsif ($attribute->signature->extendedAttributes->{"ConvertToString"}) {
+ $getterContentHead = "WebCore::String::number(" . $getterContentHead;
+ $getterContentTail .= ")";
+ } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
+ $getterContentTail .= ".toInt()";
+ } elsif ($codeGenerator->IsPodType($idlType)) {
+ $getterContentHead = "[$attributeTypeSansPtr $typeMaker:" . $getterContentHead;
+ $getterContentTail .= "]";
+ } elsif (IsProtocolType($idlType) and $idlType ne "EventTarget") {
+ $getterContentHead = "[$attributeClassName $typeMaker:WTF::getPtr(" . $getterContentHead;
+ $getterContentTail .= ")]";
+ } elsif ($typeMaker ne "") {
+ # Surround getter with TypeMaker
+ $getterContentHead = "[$attributeTypeSansPtr $typeMaker:WTF::getPtr(" . $getterContentHead;
+ $getterContentTail .= ")]";
+ }
+
+ my $getterContent;
+ if ($hasGetterException) {
+ $getterContent = $getterContentHead . "ec" . $getterContentTail;
+ } else {
+ $getterContent = $getterContentHead . $getterContentTail;
+ }
+
+ push(@implContent, $getterSig);
+ push(@implContent, "{\n");
+ push(@implContent, @customGetterContent);
+ if ($hasGetterException) {
+ # Differentiated between when the return type is a pointer and
+ # not for white space issue (ie. Foo *result vs. int result).
+ if ($attributeType =~ /\*$/) {
+ $getterContent = $attributeType . "result = " . $getterContent;
+ } else {
+ $getterContent = $attributeType . " result = " . $getterContent;
+ }
+
+ push(@implContent, " $exceptionInit\n");
+ push(@implContent, " $getterContent;\n");
+ push(@implContent, " $exceptionRaiseOnError\n");
+ push(@implContent, " return result;\n");
+ } else {
+ push(@implContent, " return $getterContent;\n");
+ }
+ push(@implContent, "}\n\n");
+
+ # - SETTER
+ if (!$attributeIsReadonly) {
+ # Exception handling
+ my $hasSetterException = @{$attribute->setterExceptions};
+
+ $attributeName = "set" . $codeGenerator->WK_ucfirst($attributeName);
+ my $setterName = "set" . ucfirst($attributeInterfaceName);
+ my $argName = "new" . ucfirst($attributeInterfaceName);
+ my $arg = GetObjCTypeGetter($argName, $idlType);
+
+ # The definition of ConvertFromString and ConvertToString is flipped for the setter
+ if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
+ $arg = "WebCore::String::number($arg)";
+ } elsif ($attribute->signature->extendedAttributes->{"ConvertToString"}) {
+ $arg = "WebCore::String($arg).toInt()";
+ }
+
+ my $setterSig = "- (void)$setterName:($attributeType)$argName\n";
+
+ push(@implContent, $setterSig);
+ push(@implContent, "{\n");
+
+ unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) {
+ push(@implContent, " ASSERT($argName);\n\n");
+ }
+
+ if ($podType) {
+ # Special case for DOMSVGNumber
+ if ($podType eq "float") {
+ push(@implContent, " *IMPL = $arg;\n");
+ } else {
+ push(@implContent, " IMPL->$attributeName($arg);\n");
+ }
+ } elsif ($hasSetterException) {
+ push(@implContent, " $exceptionInit\n");
+ push(@implContent, " IMPL->$attributeName($arg, ec);\n");
+ push(@implContent, " $exceptionRaiseOnError\n");
+ } else {
+ push(@implContent, " IMPL->$attributeName($arg);\n");
+ }
+
+ push(@implContent, "}\n\n");
+ }
+ }
+ }
+
+ # - Functions
+ if ($numFunctions > 0) {
+ foreach my $function (@{$dataNode->functions}) {
+ AddIncludesForType($function->signature->type);
+
+ my $functionName = $function->signature->name;
+ my $returnType = GetObjCType($function->signature->type);
+ my $hasParameters = @{$function->parameters};
+ my $raisesExceptions = @{$function->raisesExceptions};
+
+ my @parameterNames = ();
+ my @needsAssert = ();
+ my %needsCustom = ();
+
+ my $parameterIndex = 0;
+ my $functionSig = "- ($returnType)$functionName";
+ foreach my $param (@{$function->parameters}) {
+ my $paramName = $param->name;
+ my $paramType = GetObjCType($param->type);
+
+ # make a new parameter name if the original conflicts with a property name
+ $paramName = "in" . ucfirst($paramName) if $attributeNames{$paramName};
+
+ AddIncludesForType($param->type);
+
+ my $idlType = $codeGenerator->StripModule($param->type);
+ my $implGetter = GetObjCTypeGetter($paramName, $idlType);
+
+ push(@parameterNames, $implGetter);
+ $needsCustom{"XPathNSResolver"} = $paramName if $idlType eq "XPathNSResolver";
+ $needsCustom{"NodeFilter"} = $paramName if $idlType eq "NodeFilter";
+ $needsCustom{"EventListener"} = $paramName if $idlType eq "EventListener";
+ $needsCustom{"EventTarget"} = $paramName if $idlType eq "EventTarget";
+ $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"};
+
+ unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) {
+ push(@needsAssert, " ASSERT($paramName);\n");
+ }
+
+ if ($parameterIndex >= 1) {
+ my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"};
+ $paramPrefix = $param->name unless defined($paramPrefix);
+ $functionSig .= " $paramPrefix";
+ }
+
+ $functionSig .= ":($paramType)$paramName";
+
+ $parameterIndex++;
+ }
+
+ my @functionContent = ();
+ my $caller = "IMPL";
+
+ # special case the XPathNSResolver
+ if (defined $needsCustom{"XPathNSResolver"}) {
+ my $paramName = $needsCustom{"XPathNSResolver"};
+ push(@functionContent, " WebCore::XPathNSResolver* nativeResolver = 0;\n");
+ push(@functionContent, " RefPtr<WebCore::XPathNSResolver> customResolver;\n");
+ push(@functionContent, " if ($paramName) {\n");
+ push(@functionContent, " if ([$paramName isMemberOfClass:[DOMNativeXPathNSResolver class]])\n");
+ push(@functionContent, " nativeResolver = [(DOMNativeXPathNSResolver *)$paramName _xpathNSResolver];\n");
+ push(@functionContent, " else {\n");
+ push(@functionContent, " customResolver = WebCore::DOMCustomXPathNSResolver::create($paramName);\n");
+ push(@functionContent, " nativeResolver = WTF::getPtr(customResolver);\n");
+ push(@functionContent, " }\n");
+ push(@functionContent, " }\n");
+ }
+
+ # special case the EventTarget
+ if (defined $needsCustom{"EventTarget"}) {
+ my $paramName = $needsCustom{"EventTarget"};
+ push(@functionContent, " DOMNode* ${paramName}ObjC = $paramName;\n");
+ push(@functionContent, " WebCore::Node* ${paramName}Node = [${paramName}ObjC _node];\n");
+ push(@functionContent, " WebCore::EventTargetNode* ${paramName}EventTarget = (${paramName}Node && ${paramName}Node->isEventTargetNode()) ? static_cast<WebCore::EventTargetNode*>(${paramName}Node) : 0;\n\n");
+ $implIncludes{"DOMNode.h"} = 1;
+ $implIncludes{"Node.h"} = 1;
+ }
+
+ if ($function->signature->extendedAttributes->{"UsesView"}) {
+ push(@functionContent, " WebCore::DOMWindow* dv = $caller->defaultView();\n");
+ push(@functionContent, " if (!dv)\n");
+ push(@functionContent, " return nil;\n");
+ $implIncludes{"DOMWindow.h"} = 1;
+ $caller = "dv";
+ }
+
+ if ($function->signature->extendedAttributes->{"EventTargetNodeCast"}) {
+ if ($dataNode->name =~ /^SVG/) {
+ $caller = "static_cast<WebCore::SVGElementInstance*>($caller)";
+ } else {
+ push(@functionContent, " if (!$caller->isEventTargetNode())\n");
+ $caller = "WebCore::EventTargetNodeCast($caller)";
+ push(@functionContent, " WebCore::raiseDOMException(DOM_NOT_SUPPORTED_ERR);\n");
+ }
+ }
+
+ # special case the EventListener
+ if (defined $needsCustom{"EventListener"}) {
+ my $paramName = $needsCustom{"EventListener"};
+ push(@functionContent, " RefPtr<WebCore::EventListener> nativeEventListener = WebCore::ObjCEventListener::wrap($paramName);\n");
+ }
+
+ # special case the NodeFilter
+ if (defined $needsCustom{"NodeFilter"}) {
+ my $paramName = $needsCustom{"NodeFilter"};
+ push(@functionContent, " RefPtr<WebCore::NodeFilter> nativeNodeFilter;\n");
+ push(@functionContent, " if ($paramName)\n");
+ push(@functionContent, " nativeNodeFilter = WebCore::NodeFilter::create(WebCore::ObjCNodeFilterCondition::create($paramName));\n");
+ }
+
+ # FIXME! We need [Custom] support for ObjC, to move these hacks into DOMSVGLength/MatrixCustom.mm
+ my $svgMatrixRotateFromVector = ($podType and $podType eq "AffineTransform" and $functionName eq "rotateFromVector");
+ my $svgMatrixInverse = ($podType and $podType eq "AffineTransform" and $functionName eq "inverse");
+ my $svgLengthConvertToSpecifiedUnits = ($podType and $podType eq "SVGLength" and $functionName eq "convertToSpecifiedUnits");
+
+ push(@parameterNames, "ec") if $raisesExceptions and !($svgMatrixRotateFromVector || $svgMatrixInverse);
+ my $content = $caller . "->" . $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterNames) . ")";
+
+ if ($svgMatrixRotateFromVector) {
+ # Special case with rotateFromVector & SVGMatrix
+ push(@functionContent, " $exceptionInit\n");
+ push(@functionContent, " if (x == 0.0 || y == 0.0)\n");
+ push(@functionContent, " ec = WebCore::SVGException::SVG_INVALID_VALUE_ERR;\n");
+ push(@functionContent, " $exceptionRaiseOnError\n");
+ push(@functionContent, " return [DOMSVGMatrix _wrapSVGMatrix:$content];\n");
+ } elsif ($svgMatrixInverse) {
+ # Special case with inverse & SVGMatrix
+ push(@functionContent, " $exceptionInit\n");
+ push(@functionContent, " if (!$caller->isInvertible())\n");
+ push(@functionContent, " ec = WebCore::SVGException::SVG_MATRIX_NOT_INVERTABLE;\n");
+ push(@functionContent, " $exceptionRaiseOnError\n");
+ push(@functionContent, " return [DOMSVGMatrix _wrapSVGMatrix:$content];\n");
+ } elsif ($svgLengthConvertToSpecifiedUnits) {
+ push(@functionContent, " IMPL->convertToSpecifiedUnits(inUnitType, 0 /* FIXME */);\n");
+ } elsif ($returnType eq "void") {
+ # Special case 'void' return type.
+ if ($raisesExceptions) {
+ push(@functionContent, " $exceptionInit\n");
+ push(@functionContent, " $content;\n");
+ push(@functionContent, " $exceptionRaiseOnError\n");
+ } else {
+ push(@functionContent, " $content;\n");
+ }
+ } elsif (defined $needsCustom{"NodeToReturn"}) {
+ # Special case the insertBefore, replaceChild, removeChild
+ # and appendChild functions from DOMNode
+ my $toReturn = $needsCustom{"NodeToReturn"};
+ if ($raisesExceptions) {
+ push(@functionContent, " $exceptionInit\n");
+ push(@functionContent, " if ($content)\n");
+ push(@functionContent, " return $toReturn;\n");
+ push(@functionContent, " $exceptionRaiseOnError\n");
+ push(@functionContent, " return nil;\n");
+ } else {
+ push(@functionContent, " if ($content)\n");
+ push(@functionContent, " return $toReturn;\n");
+ push(@functionContent, " return nil;\n");
+ }
+ } else {
+ my $typeMaker = GetObjCTypeMaker($function->signature->type);
+ unless ($typeMaker eq "") {
+ my $returnTypeClass = "";
+ if ($function->signature->type eq "XPathNSResolver") {
+ # Special case XPathNSResolver
+ $returnTypeClass = "DOMNativeXPathNSResolver";
+ } else {
+ # Remove trailing " *" from pointer types.
+ $returnTypeClass = $returnType;
+ $returnTypeClass =~ s/ \*$//;
+ }
+
+ # Surround getter with TypeMaker
+ my $idlType = $returnTypeClass;
+ $idlType =~ s/^DOM//;
+
+ if ($codeGenerator->IsPodType($idlType)) {
+ $content = "[$returnTypeClass $typeMaker:" . $content . "]";
+ } else {
+ $content = "[$returnTypeClass $typeMaker:WTF::getPtr(" . $content . ")]";
+ }
+ }
+
+ if ($raisesExceptions) {
+ # Differentiated between when the return type is a pointer and
+ # not for white space issue (ie. Foo *result vs. int result).
+ if ($returnType =~ /\*$/) {
+ $content = $returnType . "result = " . $content;
+ } else {
+ $content = $returnType . " result = " . $content;
+ }
+
+ push(@functionContent, " $exceptionInit\n");
+ push(@functionContent, " $content;\n");
+ push(@functionContent, " $exceptionRaiseOnError\n");
+ push(@functionContent, " return result;\n");
+ } else {
+ push(@functionContent, " return $content;\n");
+ }
+ }
+
+ push(@implContent, "$functionSig\n");
+ push(@implContent, "{\n");
+ push(@implContent, @functionContent);
+ push(@implContent, "}\n\n");
+
+ # generate the old style method names with un-named parameters, these methods are deprecated
+ if (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"}) {
+ my $deprecatedFunctionSig = $functionSig;
+ $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names
+
+ push(@implContent, "$deprecatedFunctionSig\n");
+ push(@implContent, "{\n");
+ push(@implContent, @functionContent);
+ push(@implContent, "}\n\n");
+ }
+
+ # Clear the hash
+ %needsCustom = ();
+ }
+ }
+
+ # END implementation
+ push(@implContent, "\@end\n");
+
+ # Generate internal interfaces
+ unless ($dataNode->extendedAttributes->{ObjCCustomInternalImpl}) {
+ # - BEGIN WebCoreInternal category @implementation
+ push(@implContent, "\n\@implementation $className (WebCoreInternal)\n\n");
+
+ my $typeGetterSig = GetInternalTypeGetterSignature($interfaceName, $podType);
+ push(@implContent, "$typeGetterSig\n");
+ push(@implContent, "{\n");
+
+ if ($podType) {
+ push(@implContent, " return *IMPL;\n");
+ } else {
+ push(@implContent, " return IMPL;\n");
+ }
+
+ push(@implContent, "}\n\n");
+
+ my ($typeMakerSig, $typeMakerSigAddition, $ivarsToInit) = GetInternalTypeMakerSignature($interfaceName, $podType);
+
+ if ($podType) {
+ # - (id)_initWithFooBar:(WebCore::FooBar)impl for implementation class FooBar
+ my $initWithImplName = "_initWith" . $implClassName;
+ my $initWithSig = "- (id)$initWithImplName:($podTypeWithNamespace)impl" . $typeMakerSigAddition;
+
+ # FIXME: Implement Caching
+ push(@implContent, "$initWithSig\n");
+ push(@implContent, "{\n");
+ push(@implContent, " $assertMainThread;\n");
+ push(@implContent, " [super _init];\n");
+ push(@implContent, " $podTypeWithNamespace* _impl = new $podTypeWithNamespace(impl);\n");
+ push(@implContent, " _internal = reinterpret_cast<DOMObjectInternal*>(_impl);\n");
+ push(@implContent, " return self;\n");
+ push(@implContent, "}\n\n");
+
+ # - (DOMFooBar)_wrapFooBar:(WebCore::FooBar)impl for implementation class FooBar
+ push(@implContent, "$typeMakerSig\n");
+ push(@implContent, "{\n");
+ push(@implContent, " $assertMainThread;\n");
+ push(@implContent, " return [[[self alloc] $initWithImplName:impl] autorelease];\n");
+ push(@implContent, "}\n\n");
+ } elsif ($parentImplClassName eq "Object") {
+ # - (id)_initWithFooBar:(WebCore::FooBar *)impl for implementation class FooBar
+ my $initWithImplName = "_initWith" . $implClassName;
+ my $initWithSig = "- (id)$initWithImplName:($implClassNameWithNamespace *)impl" . $typeMakerSigAddition;
+
+ push(@implContent, "$initWithSig\n");
+ push(@implContent, "{\n");
+ push(@implContent, " $assertMainThread;\n");
+ push(@implContent, " [super _init];\n");
+ push(@implContent, " _internal = reinterpret_cast<DOMObjectInternal*>(impl);\n");
+ push(@implContent, " impl->ref();\n");
+ push(@implContent, " WebCore::addDOMWrapper(self, impl);\n");
+ push(@implContent, @ivarsToRetain);
+ push(@implContent, " return self;\n");
+ push(@implContent, "}\n\n");
+
+ # - (DOMFooBar)_wrapFooBar:(WebCore::FooBar *)impl for implementation class FooBar
+ push(@implContent, "$typeMakerSig\n");
+ push(@implContent, "{\n");
+ push(@implContent, " $assertMainThread;\n");
+ push(@implContent, " if (!impl)\n");
+ push(@implContent, " return nil;\n");
+ push(@implContent, " id cachedInstance;\n");
+ push(@implContent, " cachedInstance = WebCore::getDOMWrapper(impl);\n");
+ push(@implContent, " if (cachedInstance)\n");
+ push(@implContent, " return [[cachedInstance retain] autorelease];\n");
+ push(@implContent, " return [[[self alloc] $initWithImplName:impl" . $ivarsToInit . "] autorelease];\n");
+ push(@implContent, "}\n\n");
+ } else {
+ my $internalBaseType = "DOM$baseClass";
+ my $internalBaseTypeMaker = GetObjCTypeMaker($baseClass);
+
+ # - (DOMFooBar)_wrapFooBar:(WebCore::FooBar *)impl for implementation class FooBar
+ push(@implContent, "$typeMakerSig\n");
+ push(@implContent, "{\n");
+ push(@implContent, " $assertMainThread;\n");
+ push(@implContent, " return static_cast<$className*>([$internalBaseType $internalBaseTypeMaker:impl]);\n");
+ push(@implContent, "}\n\n");
+ }
+
+ # END WebCoreInternal category
+ push(@implContent, "\@end\n");
+ }
+
+ # - End the ifdef conditional if necessary
+ push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional;
+}
+
+# Internal helper
+sub WriteData
+{
+ my $object = shift;
+ my $name = shift;
+
+ # Open files for writing...
+ my $headerFileName = "$outputDir/" . $name . ".h";
+ my $privateHeaderFileName = "$outputDir/" . $name . "Private.h";
+ my $implFileName = "$outputDir/" . $name . ".mm";
+ my $internalHeaderFileName = "$outputDir/" . $name . "Internal.h";
+
+ # Remove old files.
+ unlink($headerFileName);
+ unlink($privateHeaderFileName);
+ unlink($implFileName);
+ unlink($internalHeaderFileName);
+
+ # Write public header.
+ open(HEADER, ">$headerFileName") or die "Couldn't open file $headerFileName";
+
+ print HEADER @headerContentHeader;
+ print HEADER map { "\@class $_;\n" } sort keys(%headerForwardDeclarations);
+ print HEADER map { "\@protocol $_;\n" } sort keys(%headerForwardDeclarationsForProtocols);
+
+ my $hasForwardDeclarations = keys(%headerForwardDeclarations) + keys(%headerForwardDeclarationsForProtocols);
+ print HEADER "\n" if $hasForwardDeclarations;
+ print HEADER @headerContent;
+
+ close(HEADER);
+
+ @headerContentHeader = ();
+ @headerContent = ();
+ %headerForwardDeclarations = ();
+ %headerForwardDeclarationsForProtocols = ();
+
+ if (@privateHeaderContent > 0) {
+ open(PRIVATE_HEADER, ">$privateHeaderFileName") or die "Couldn't open file $privateHeaderFileName";
+
+ print PRIVATE_HEADER @privateHeaderContentHeader;
+ print PRIVATE_HEADER map { "\@class $_;\n" } sort keys(%privateHeaderForwardDeclarations);
+ print PRIVATE_HEADER map { "\@protocol $_;\n" } sort keys(%privateHeaderForwardDeclarationsForProtocols);
+
+ $hasForwardDeclarations = keys(%privateHeaderForwardDeclarations) + keys(%privateHeaderForwardDeclarationsForProtocols);
+ print PRIVATE_HEADER "\n" if $hasForwardDeclarations;
+ print PRIVATE_HEADER @privateHeaderContent;
+
+ close(PRIVATE_HEADER);
+
+ @privateHeaderContentHeader = ();
+ @privateHeaderContent = ();
+ %privateHeaderForwardDeclarations = ();
+ %privateHeaderForwardDeclarationsForProtocols = ();
+ }
+
+ # Write implementation file.
+ unless ($noImpl) {
+ open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName";
+
+ print IMPL @implContentHeader;
+ print IMPL map { "#import \"$_\"\n" } sort keys(%implIncludes);
+
+ print IMPL "\n" if keys(%implIncludes);
+ print IMPL @implContent;
+
+ close(IMPL);
+
+ @implContentHeader = ();
+ @implContent = ();
+ %implIncludes = ();
+ }
+
+ if (@internalHeaderContent > 0) {
+ open(INTERNAL_HEADER, ">$internalHeaderFileName") or die "Couldn't open file $internalHeaderFileName";
+
+ print INTERNAL_HEADER @internalHeaderContent;
+
+ close(INTERNAL_HEADER);
+
+ @internalHeaderContent = ();
+ }
+}
+
+1;
diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm
new file mode 100644
index 0000000..de7cf9c
--- /dev/null
+++ b/WebCore/bindings/scripts/IDLParser.pm
@@ -0,0 +1,416 @@
+#
+# KDOM IDL parser
+#
+# Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
+#
+# This file is part of the KDE project
+#
+# 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 IDLParser;
+
+use IPC::Open2;
+use IDLStructure;
+
+use constant MODE_UNDEF => 0; # Default mode.
+
+use constant MODE_MODULE => 10; # 'module' section
+use constant MODE_INTERFACE => 11; # 'interface' section
+use constant MODE_EXCEPTION => 12; # 'exception' section
+use constant MODE_ALIAS => 13; # 'alias' section
+
+# Helper variables
+my @temporaryContent = "";
+
+my $parseMode = MODE_UNDEF;
+my $preservedParseMode = MODE_UNDEF;
+
+my $beQuiet; # Should not display anything on STDOUT?
+my $document = 0; # Will hold the resulting 'idlDocument'
+
+# Default Constructor
+sub new
+{
+ my $object = shift;
+ my $reference = { };
+
+ $document = 0;
+ $beQuiet = shift;
+
+ bless($reference, $object);
+ return $reference;
+}
+
+# Returns the parsed 'idlDocument'
+sub Parse
+{
+ my $object = shift;
+ my $fileName = shift;
+ my $defines = shift;
+ my $preprocessor = shift;
+
+ if (!$preprocessor) {
+ $preprocessor = "/usr/bin/gcc -E -P -x c++";
+ }
+
+ if (!$defines) {
+ $defines = "";
+ }
+
+ print " | *** Starting to parse $fileName...\n |\n" unless $beQuiet;
+
+ open2(\*PP_OUT, \*PP_IN, split(' ', $preprocessor), (map { "-D$_" } split(' ', $defines)), $fileName);
+ close PP_IN;
+ my @documentContent = <PP_OUT>;
+ close PP_OUT;
+
+ my $dataAvailable = 0;
+
+ # Simple IDL Parser (tm)
+ foreach (@documentContent) {
+ my $newParseMode = $object->DetermineParseMode($_);
+
+ if ($newParseMode ne MODE_UNDEF) {
+ if ($dataAvailable eq 0) {
+ $dataAvailable = 1; # Start node building...
+ } else {
+ $object->ProcessSection();
+ }
+ }
+
+ # Update detected data stream mode...
+ if ($newParseMode ne MODE_UNDEF) {
+ $parseMode = $newParseMode;
+ }
+
+ push(@temporaryContent, $_);
+ }
+
+ # Check if there is anything remaining to parse...
+ if (($parseMode ne MODE_UNDEF) and ($#temporaryContent > 0)) {
+ $object->ProcessSection();
+ }
+
+ print " | *** Finished parsing!\n" unless $beQuiet;
+
+ $document->fileName($fileName);
+
+ return $document;
+}
+
+sub ParseModule
+{
+ my $object = shift;
+ my $dataNode = shift;
+
+ print " |- Trying to parse module...\n" unless $beQuiet;
+
+ my $data = join("", @temporaryContent);
+ $data =~ /$IDLStructure::moduleSelector/;
+
+ my $moduleName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)"));
+ $dataNode->module($moduleName);
+
+ print " |----> Module; NAME \"$moduleName\"\n |-\n |\n" unless $beQuiet;
+}
+
+sub dumpExtendedAttributes
+{
+ my $padStr = shift;
+ my $attrs = shift;
+
+ if (!%{$attrs}) {
+ return "";
+ }
+
+ my @temp;
+ while (($name, $value) = each(%{$attrs})) {
+ push(@temp, "$name=$value");
+ }
+
+ return $padStr . "[" . join(", ", @temp) . "]";
+}
+
+sub parseExtendedAttributes
+{
+ my $str = shift;
+ $str =~ s/\[\s*(.*?)\s*\]/$1/g;
+
+ my %attrs = ();
+
+ foreach my $value (split(/\s*,\s*/, $str)) {
+ ($name,$value) = split(/\s*=\s*/, $value, 2);
+
+ # Attributes with no value are set to be true
+ $value = 1 unless defined $value;
+ $attrs{$name} = $value;
+ }
+
+ return \%attrs;
+}
+
+sub ParseInterface
+{
+ my $object = shift;
+ my $dataNode = shift;
+ my $sectionName = shift;
+
+ my $data = join("", @temporaryContent);
+
+ # Look for end-of-interface mark
+ $data =~ /};/g;
+ $data = substr($data, index($data, $sectionName), pos($data) - length($data));
+
+ $data =~ s/[\n\r]/ /g;
+
+ # Beginning of the regexp parsing magic
+ if ($sectionName eq "exception") {
+ print " |- Trying to parse exception...\n" unless $beQuiet;
+
+ my $exceptionName = "";
+ my $exceptionData = "";
+ my $exceptionDataName = "";
+ my $exceptionDataType = "";
+
+ # Match identifier of the exception, and enclosed data...
+ $data =~ /$IDLStructure::exceptionSelector/;
+ $exceptionName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)"));
+ $exceptionData = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)"));
+
+ ('' =~ /^/); # Reset variables needed for regexp matching
+
+ # ... parse enclosed data (get. name & type)
+ $exceptionData =~ /$IDLStructure::exceptionSubSelector/;
+ $exceptionDataType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$data\n)"));
+ $exceptionDataName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)"));
+
+ # Fill in domClass datastructure
+ $dataNode->name($exceptionName);
+
+ my $newDataNode = new domAttribute();
+ $newDataNode->type("readonly attribute");
+ $newDataNode->signature(new domSignature());
+
+ $newDataNode->signature->name($exceptionDataName);
+ $newDataNode->signature->type($exceptionDataType);
+
+ my $arrayRef = $dataNode->attributes;
+ push(@$arrayRef, $newDataNode);
+
+ print " |----> Exception; NAME \"$exceptionName\" DATA TYPE \"$exceptionDataType\" DATA NAME \"$exceptionDataName\"\n |-\n |\n" unless $beQuiet;
+ } elsif ($sectionName eq "interface") {
+ print " |- Trying to parse interface...\n" unless $beQuiet;
+
+ my $interfaceName = "";
+ my $interfaceData = "";
+
+ # Match identifier of the interface, and enclosed data...
+ $data =~ /$IDLStructure::interfaceSelector/;
+
+ $interfaceExtendedAttributes = (defined($1) ? $1 : " "); chop($interfaceExtendedAttributes);
+ $interfaceName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$data\n)"));
+ $interfaceBase = (defined($3) ? $3 : "");
+ $interfaceData = (defined($4) ? $4 : die("Parsing error!\nSource:\n$data\n)"));
+
+ # Fill in known parts of the domClass datastructure now...
+ $dataNode->name($interfaceName);
+ $dataNode->extendedAttributes(parseExtendedAttributes($interfaceExtendedAttributes));
+
+ # Inheritance detection
+ my @interfaceParents = split(/,/, $interfaceBase);
+ foreach(@interfaceParents) {
+ my $line = $_;
+ $line =~ s/\s*//g;
+
+ my $arrayRef = $dataNode->parents;
+ push(@$arrayRef, $line);
+ }
+
+ $interfaceData =~ s/[\n\r]/ /g;
+ my @interfaceMethods = split(/;/, $interfaceData);
+
+ foreach my $line (@interfaceMethods) {
+ if ($line =~ /attribute/) {
+ $line =~ /$IDLStructure::interfaceAttributeSelector/;
+
+ my $attributeType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)"));
+ my $attributeExtendedAttributes = (defined($2) ? $2 : " "); chop($attributeExtendedAttributes);
+
+ my $attributeDataType = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
+ my $attributeDataName = (defined($4) ? $4 : die("Parsing error!\nSource:\n$line\n)"));
+
+ ('' =~ /^/); # Reset variables needed for regexp matching
+
+ $line =~ /$IDLStructure::getterRaisesSelector/;
+ my $getterException = (defined($1) ? $1 : "");
+
+ $line =~ /$IDLStructure::setterRaisesSelector/;
+ my $setterException = (defined($1) ? $1 : "");
+
+ my $newDataNode = new domAttribute();
+ $newDataNode->type($attributeType);
+ $newDataNode->signature(new domSignature());
+
+ $newDataNode->signature->name($attributeDataName);
+ $newDataNode->signature->type($attributeDataType);
+ $newDataNode->signature->extendedAttributes(parseExtendedAttributes($attributeExtendedAttributes));
+
+ my $arrayRef = $dataNode->attributes;
+ push(@$arrayRef, $newDataNode);
+
+ print " | |> Attribute; TYPE \"$attributeType\" DATA NAME \"$attributeDataName\" DATA TYPE \"$attributeDataType\" GET EXCEPTION? \"$getterException\" SET EXCEPTION? \"$setterException\"" .
+ dumpExtendedAttributes("\n | ", $newDataNode->signature->extendedAttributes) . "\n" unless $beQuiet;
+
+ $getterException =~ s/\s+//g;
+ $setterException =~ s/\s+//g;
+ @{$newDataNode->getterExceptions} = split(/,/, $getterException);
+ @{$newDataNode->setterExceptions} = split(/,/, $setterException);
+ } elsif (($line !~ s/^\s*$//g) and ($line !~ /^\s*const/)) {
+ $line =~ /$IDLStructure::interfaceMethodSelector/ or die "Parsing error!\nSource:\n$line\n)";
+
+ my $methodExtendedAttributes = (defined($1) ? $1 : " "); chop($methodExtendedAttributes);
+ my $methodType = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
+ my $methodName = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
+ my $methodSignature = (defined($4) ? $4 : die("Parsing error!\nSource:\n$line\n)"));
+
+ ('' =~ /^/); # Reset variables needed for regexp matching
+
+ $line =~ /$IDLStructure::raisesSelector/;
+ my $methodException = (defined($1) ? $1 : "");
+
+ my $newDataNode = new domFunction();
+
+ $newDataNode->signature(new domSignature());
+ $newDataNode->signature->name($methodName);
+ $newDataNode->signature->type($methodType);
+ $newDataNode->signature->extendedAttributes(parseExtendedAttributes($methodExtendedAttributes));
+
+ print " | |- Method; TYPE \"$methodType\" NAME \"$methodName\" EXCEPTION? \"$methodException\"" .
+ dumpExtendedAttributes("\n | ", $newDataNode->signature->extendedAttributes) . "\n" unless $beQuiet;
+
+ $methodException =~ s/\s+//g;
+ @{$newDataNode->raisesExceptions} = split(/,/, $methodException);
+
+ my @params = split(/,/, $methodSignature);
+ foreach(@params) {
+ my $line = $_;
+
+ $line =~ /$IDLStructure::interfaceParameterSelector/;
+ my $paramExtendedAttributes = (defined($1) ? $1 : " "); chop($paramExtendedAttributes);
+ my $paramType = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
+ my $paramName = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
+
+ my $paramDataNode = new domSignature();
+ $paramDataNode->name($paramName);
+ $paramDataNode->type($paramType);
+ $paramDataNode->extendedAttributes(parseExtendedAttributes($paramExtendedAttributes));
+
+ my $arrayRef = $newDataNode->parameters;
+ push(@$arrayRef, $paramDataNode);
+
+ print " | |> Param; TYPE \"$paramType\" NAME \"$paramName\"" .
+ dumpExtendedAttributes("\n | ", $paramDataNode->extendedAttributes) . "\n" unless $beQuiet;
+ }
+
+ my $arrayRef = $dataNode->functions;
+ push(@$arrayRef, $newDataNode);
+ } elsif ($line =~ /^\s*const/) {
+ $line =~ /$IDLStructure::constantSelector/;
+ my $constType = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)"));
+ my $constName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
+ my $constValue = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)"));
+
+ my $newDataNode = new domConstant();
+ $newDataNode->name($constName);
+ $newDataNode->type($constType);
+ $newDataNode->value($constValue);
+
+ my $arrayRef = $dataNode->constants;
+ push(@$arrayRef, $newDataNode);
+
+ print " | |> Constant; TYPE \"$constType\" NAME \"$constName\" VALUE \"$constValue\"\n" unless $beQuiet;
+ }
+ }
+
+ print " |----> Interface; NAME \"$interfaceName\"" .
+ dumpExtendedAttributes("\n | ", $dataNode->extendedAttributes) . "\n |-\n |\n" unless $beQuiet;
+ }
+}
+
+# Internal helper
+sub DetermineParseMode
+{
+ my $object = shift;
+ my $line = shift;
+
+ my $mode = MODE_UNDEF;
+ if ($_ =~ /module/) {
+ $mode = MODE_MODULE;
+ } elsif ($_ =~ /interface/) {
+ $mode = MODE_INTERFACE;
+ } elsif ($_ =~ /exception/) {
+ $mode = MODE_EXCEPTION;
+ } elsif ($_ =~ /alias/) {
+ $mode = MODE_ALIAS;
+ }
+
+ return $mode;
+}
+
+# Internal helper
+sub ProcessSection
+{
+ my $object = shift;
+
+ if ($parseMode eq MODE_MODULE) {
+ die ("Two modules in one file! Fatal error!\n") if ($document ne 0);
+ $document = new idlDocument();
+ $object->ParseModule($document);
+ } elsif ($parseMode eq MODE_INTERFACE) {
+ my $node = new domClass();
+ $object->ParseInterface($node, "interface");
+
+ die ("No module specified! Fatal Error!\n") if ($document eq 0);
+ my $arrayRef = $document->classes;
+ push(@$arrayRef, $node);
+ } elsif($parseMode eq MODE_EXCEPTION) {
+ my $node = new domClass();
+ $object->ParseInterface($node, "exception");
+
+ die ("No module specified! Fatal Error!\n") if ($document eq 0);
+ my $arrayRef = $document->classes;
+ push(@$arrayRef, $node);
+ } elsif($parseMode eq MODE_ALIAS) {
+ print " |- Trying to parse alias...\n" unless $beQuiet;
+
+ my $line = join("", @temporaryContent);
+ $line =~ /$IDLStructure::aliasSelector/;
+
+ my $interfaceName = (defined($1) ? $1 : die("Parsing error!\nSource:\n$line\n)"));
+ my $wrapperName = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)"));
+
+ print " |----> Alias; INTERFACE \"$interfaceName\" WRAPPER \"$wrapperName\"\n |-\n |\n" unless $beQuiet;
+
+ # FIXME: Check if alias is already in aliases
+ my $aliases = $document->aliases;
+ $aliases->{$interfaceName} = $wrapperName;
+ }
+
+ @temporaryContent = "";
+}
+
+1;
diff --git a/WebCore/bindings/scripts/IDLStructure.pm b/WebCore/bindings/scripts/IDLStructure.pm
new file mode 100644
index 0000000..5a59ff1
--- /dev/null
+++ b/WebCore/bindings/scripts/IDLStructure.pm
@@ -0,0 +1,107 @@
+#
+# KDOM IDL parser
+#
+# Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
+#
+# This file is part of the KDE project
+#
+# 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 IDLStructure;
+
+use Class::Struct;
+
+# Used to represent a parsed IDL document
+struct( idlDocument => {
+ module => '$', # Module identifier
+ classes => '@', # All parsed interfaces
+ fileName => '$' # file name
+});
+
+# Used to represent 'interface' / 'exception' blocks
+struct( domClass => {
+ name => '$', # Class identifier (without module)
+ parents => '@', # List of strings
+ constants => '@', # List of 'domConstant'
+ functions => '@', # List of 'domFunction'
+ attributes => '@', # List of 'domAttribute'
+ extendedAttributes => '$', # Extended attributes
+});
+
+# Used to represent domClass contents (name of method, signature)
+struct( domFunction => {
+ signature => '$', # Return type/Object name/extended attributes
+ parameters => '@', # List of 'domSignature'
+ raisesExceptions => '@', # Possibly raised exceptions.
+});
+
+# Used to represent domClass contents (name of attribute, signature)
+struct( domAttribute => {
+ type => '$', # Attribute type (including namespace)
+ signature => '$', # Attribute signature
+ getterExceptions => '@', # Possibly raised exceptions.
+ setterExceptions => '@', # Possibly raised exceptions.
+});
+
+# Used to represent a map of 'variable name' <-> 'variable type'
+struct( domSignature => {
+ name => '$', # Variable name
+ type => '$', # Variable type
+ extendedAttributes => '$' # Extended attributes
+});
+
+# Used to represent string constants
+struct( domConstant => {
+ name => '$', # DOM Constant identifier
+ type => '$', # Type of data
+ value => '$', # Constant value
+});
+
+# Helpers
+$idlId = '[a-zA-Z0-9]'; # Generic identifier
+$idlIdNs = '[a-zA-Z0-9:]'; # Generic identifier including namespace
+$idlIdNsList = '[a-zA-Z0-9:,\ ]'; # List of Generic identifiers including namespace
+
+$idlType = '[a-zA-Z0-9_]'; # Generic type/"value string" identifier
+$idlDataType = '[a-zA-Z0-9\ ]'; # Generic data type identifier
+
+# Magic IDL parsing regular expressions
+my $supportedTypes = "((?:unsigned )?(?:int|short|(?:long )?long)|(?:$idlIdNs*))";
+
+# Special IDL notations
+$extendedAttributeSyntax = '\[[^]]*\]'; # Used for extended attributes
+
+# Regular expression based IDL 'syntactical tokenizer' used in the IDLParser
+$moduleSelector = 'module\s*(' . $idlId . '*)\s*{';
+$moduleNSSelector = 'module\s*(' . $idlId . '*)\s*\[ns\s*(' . $idlIdNs . '*)\s*(' . $idlIdNs . '*)\]\s*;';
+$constantSelector = 'const\s*' . $supportedTypes . '\s*(' . $idlType . '*)\s*=\s*(' . $idlType . '*)';
+$raisesSelector = 'raises\s*\((' . $idlIdNsList . '*)\s*\)';
+$getterRaisesSelector = '\bgetter\s+raises\s*\((' . $idlIdNsList . '*)\s*\)';
+$setterRaisesSelector = '\bsetter\s+raises\s*\((' . $idlIdNsList . '*)\s*\)';
+
+$typeNamespaceSelector = '((?:' . $idlId . '*::)*)\s*(' . $idlDataType . '*)';
+
+$exceptionSelector = 'exception\s*(' . $idlIdNs . '*)\s*([a-zA-Z\s{;]*};)';
+$exceptionSubSelector = '{\s*' . $supportedTypes . '\s*(' . $idlType . '*)\s*;\s*}';
+
+$interfaceSelector = 'interface\s*((?:' . $extendedAttributeSyntax . ' )?)(' . $idlIdNs . '*)\s*(?::(\s*[^{]*))?{([a-zA-Z0-9_=\s(),;:\[\]]*)';
+$interfaceMethodSelector = '\s*((?:' . $extendedAttributeSyntax . ' )?)' . $supportedTypes . '\s*(' . $idlIdNs . '*)\s*\(\s*([a-zA-Z0-9:\s,=\[\]]*)';
+$interfaceParameterSelector = 'in\s*((?:' . $extendedAttributeSyntax . ' )?)' . $supportedTypes . '\s*(' . $idlIdNs . '*)';
+
+$interfaceAttributeSelector = '\s*(readonly attribute|attribute)\s*(' . $extendedAttributeSyntax . ' )?' . $supportedTypes . '\s*(' . $idlType . '*)';
+
+1;
diff --git a/WebCore/bindings/scripts/InFilesParser.pm b/WebCore/bindings/scripts/InFilesParser.pm
new file mode 100644
index 0000000..89664ed
--- /dev/null
+++ b/WebCore/bindings/scripts/InFilesParser.pm
@@ -0,0 +1,140 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2008 Julien Chaffraix <jchaffraix@webkit.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+use strict;
+
+package InFilesParser;
+
+my $isParsingCommonParameters;
+my $hasStartedParsing;
+
+# Helper functions
+
+sub trimComment
+{
+ my $string = shift;
+ $string =~ s/#.+$//;
+ chomp($string);
+ return $string;
+}
+
+sub trimWS
+{
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ chomp($string);
+ return $string;
+}
+
+sub trimQuoteAndWS
+{
+ my $string = shift;
+ $string =~ s/\"([^\"]+)\"/$1/;
+ return trimWS($string);
+}
+
+# Default constructor
+
+sub new
+{
+ my $object = shift;
+ my $reference = { };
+
+ # Initialize the parser.
+ $isParsingCommonParameters = 1;
+ $hasStartedParsing = 0;
+
+ bless($reference, $object);
+ return $reference;
+}
+
+# parse take 3 attributes:
+# - the filestream to read from (the caller has to open / close it).
+# - the commonParameterHandler called when parsing the first part of the file with the parameter and the value.
+# - the perTagHandler called for each optional parameter with the element name, the parameter and its value.
+# If no parameter were provided, it is called once with an empty parameter and value.
+sub parse($)
+{
+ my $object = shift;
+ my $fileStream = shift; # IO::File only
+ my $commonParameterHandler = shift;
+ my $perTagHandler = shift;
+
+ foreach (<$fileStream>) {
+ # Empty line, change from common parameter part
+ # to per tag part if we have started parsing.
+ if (/^$/) {
+ if ($hasStartedParsing) {
+ $isParsingCommonParameters = 0;
+ }
+ next;
+ }
+
+ # There may be a few empty lines at the beginning of the file
+ # so detect the first non empty line which starts the common
+ # parameters part.
+ $hasStartedParsing = 1;
+
+ if (/^#/) {
+ next;
+ }
+
+ $_ = trimComment($_);
+
+ if ($isParsingCommonParameters) {
+ my ($name, $value) = split '=', $_;
+
+ $name = trimWS($name);
+ $value = trimQuoteAndWS($value);
+
+ &$commonParameterHandler($name, $value);
+ } else {
+ # Parsing per-tag parameters.
+
+ # Split the tag name ($1) from the optionnal parameter(s) ($2)
+ /^(\S+)\s*(.*)$/;
+ my $elementName = $1;
+
+ if ($2) {
+ my @options = split "," , $2;
+ my ($option, $value);
+ for (my $i = 0; $i < @options; ++$i) {
+ ($option, $value) = split "=", $options[$i];
+ $option = trimWS($option);
+ $value = trimQuoteAndWS($value);
+
+ &$perTagHandler($elementName, $option, $value);
+ }
+ } else {
+ # No parameter was given so call it with empty strings.
+ &$perTagHandler($elementName, "", "");
+ }
+ }
+ }
+}
+
+1;
diff --git a/WebCore/bindings/scripts/generate-bindings.pl b/WebCore/bindings/scripts/generate-bindings.pl
new file mode 100755
index 0000000..9c374bf
--- /dev/null
+++ b/WebCore/bindings/scripts/generate-bindings.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2005 Apple Computer, Inc.
+# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
+#
+# This file is part of WebKit
+#
+# 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.
+#
+
+# This script is a temporary hack.
+# Files are generated in the source directory, when they really should go
+# to the DerivedSources directory.
+# This should also eventually be a build rule driven off of .idl files
+# however a build rule only solution is blocked by several radars:
+# <rdar://problems/4251781&4251785>
+
+use strict;
+
+use File::Path;
+use Getopt::Long;
+use Cwd;
+
+use IDLParser;
+use CodeGenerator;
+
+my @idlDirectories;
+my $outputDirectory;
+my $generator;
+my $defines;
+my $preprocessor;
+
+GetOptions('include=s@' => \@idlDirectories,
+ 'outputDir=s' => \$outputDirectory,
+ 'generator=s' => \$generator,
+ 'defines=s' => \$defines,
+ 'preprocessor=s' => \$preprocessor);
+
+my $idlFile = $ARGV[0];
+
+die('Must specify input file.') unless defined($idlFile);
+die('Must specify IDL search path.') unless @idlDirectories;
+die('Must specify generator') unless defined($generator);
+die('Must specify input file.') unless defined($idlFile);
+die('Must specify output directory.') unless defined($outputDirectory);
+die('Must specify defines') unless defined($defines);
+
+$defines =~ s/^\s+|\s+$//g; # trim whitespace
+
+# Parse the given IDL file.
+my $parser = IDLParser->new(1);
+my $document = $parser->Parse($idlFile, $defines, $preprocessor);
+
+# Generate desired output for given IDL file.
+my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, 0, $preprocessor);
+$codeGen->ProcessDocument($document, $defines);