2 # Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
3 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
4 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
5 # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
6 # Copyright (C) 2006 Apple Computer, Inc.
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Library General Public
10 # License as published by the Free Software Foundation; either
11 # version 2 of the License, or (at your option) any later version.
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Library General Public License for more details.
18 # You should have received a copy of the GNU Library General Public License
19 # aint with this library; see the file COPYING.LIB. If not, write to
20 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 # Boston, MA 02111-1307, USA.
24 package CodeGeneratorObjC;
31 my %publicInterfaces = ();
32 my $newPublicClass = 0;
37 my @headerContentHeader = ();
38 my @headerContent = ();
39 my %headerForwardDeclarations = ();
40 my %headerForwardDeclarationsForProtocols = ();
42 my @privateHeaderContentHeader = ();
43 my @privateHeaderContent = ();
44 my %privateHeaderForwardDeclarations = ();
45 my %privateHeaderForwardDeclarationsForProtocols = ();
47 my @intenalHeaderContent = ();
49 my @implContentHeader = ();
51 my %implIncludes = ();
54 my %protocolTypeHash = ("XPathNSResolver" => 1, "EventListener" => 1, "EventTarget" => 1, "NodeFilter" => 1,
55 "SVGLocatable" => 1, "SVGTransformable" => 1, "SVGStylable" => 1, "SVGFilterPrimitiveStandardAttributes" => 1,
56 "SVGTests" => 1, "SVGLangSpace" => 1, "SVGExternalResourcesRequired" => 1, "SVGURIReference" => 1,
57 "SVGZoomAndPan" => 1, "SVGFitToViewBox" => 1, "SVGAnimatedPathData" => 1, "SVGAnimatedPoints" => 1);
58 my %nativeObjCTypeHash = ("URL" => 1, "Color" => 1);
60 # FIXME: this should be replaced with a function that recurses up the tree
61 # to find the actual base type.
62 my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1,
63 "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1,
64 "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1,
65 "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1,
66 "SVGAngle" => 1, "SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, "SVGAnimatedEnumeration" => 1,
67 "SVGAnimatedInteger" => 1, "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1,
68 "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, "SVGAnimatedPoints" => 1,
69 "SVGAnimatedPreserveAspectRatio" => 1, "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1,
70 "SVGAnimatedTransformList" => 1, "SVGLength" => 1, "SVGLengthList" => 1, "SVGMatrix" => 1,
71 "SVGNumber" => 1, "SVGNumberList" => 1, "SVGPathSeg" => 1, "SVGPathSegList" => 1, "SVGPoint" => 1,
72 "SVGPointList" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1, "SVGRenderingIntent" => 1,
73 "SVGStringList" => 1, "SVGTransform" => 1, "SVGTransformList" => 1, "SVGUnitTypes" => 1);
76 my $buildingForTigerOrEarlier = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} <= 10.4;
77 my $buildingForLeopardOrLater = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} >= 10.5;
78 my $exceptionInit = "WebCore::ExceptionCode ec = 0;";
79 my $exceptionRaiseOnError = "WebCore::raiseOnDOMError(ec);";
81 # Default Licence Templates
82 my $headerLicenceTemplate = << "EOF";
84 * Copyright (C) 2004-2006 Apple Computer, Inc. All rights reserved.
85 * Copyright (C) 2006 Samuel Weinig <sam.weinig\@gmail.com>
87 * Redistribution and use in source and binary forms, with or without
88 * modification, are permitted provided that the following conditions
90 * 1. Redistributions of source code must retain the above copyright
91 * notice, this list of conditions and the following disclaimer.
92 * 2. Redistributions in binary form must reproduce the above copyright
93 * notice, this list of conditions and the following disclaimer in the
94 * documentation and/or other materials provided with the distribution.
96 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
97 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
98 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
99 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
100 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
101 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
102 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
103 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
104 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
105 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
106 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
110 my $implementationLicenceTemplate = << "EOF";
112 * This file is part of the WebKit open source project.
113 * This file has been generated by generate-bindings.pl. DO NOT MODIFY!
115 * Redistribution and use in source and binary forms, with or without
116 * modification, are permitted provided that the following conditions
118 * 1. Redistributions of source code must retain the above copyright
119 * notice, this list of conditions and the following disclaimer.
120 * 2. Redistributions in binary form must reproduce the above copyright
121 * notice, this list of conditions and the following disclaimer in the
122 * documentation and/or other materials provided with the distribution.
124 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
125 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
126 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
127 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
128 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
129 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
130 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
131 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
132 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
133 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
134 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
138 # Default constructor
144 $codeGenerator = shift;
147 bless($reference, $object);
156 # Uppercase the first letter, while respecting WebKit style guidelines.
157 # E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.
161 my $ret = ucfirst($param);
162 $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/;
166 sub ReadPublicInterfaces
169 my $superClass = shift;
173 my $actualSuperClass;
174 %publicInterfaces = ();
176 my $fileName = "WebCore/bindings/objc/PublicDOMInterfaces.h";
177 open FILE, "-|", "/usr/bin/gcc", "-E", "-P", "-x", "objective-c",
178 (map { "-D$_" } split(/ /, $defines)), "-DOBJC_CODE_GENERATION", $fileName or die "Could not open $fileName";
179 my @documentContent = <FILE>;
182 foreach $line (@documentContent) {
183 if ($line =~ /^\s?\@interface $class\s?:\s?(\w+)\s?$/) {
184 die "error: Public API change. Superclass for \"$class\" differs ($1 != $superClass)" if $superClass ne $1;
189 last if $found and $line =~ /^\s?\@end\s?$/;
195 $publicInterfaces{$line} = 1;
199 # If this class was not found in PublicDOMInterfaces.h then it should be considered as an entirly new public class.
200 $newPublicClass = ! $found;
203 # Params: 'domClass' struct
204 sub GenerateInterface
207 my $dataNode = shift;
210 my $name = $dataNode->name;
211 my $className = GetClassName($name);
212 my $parentClassName = "DOM" . GetParentImplClassName($dataNode);
213 $isProtocol = $dataNode->extendedAttributes->{ObjCProtocol};
214 $noImpl = $dataNode->extendedAttributes->{ObjCCustomImplementation} || $isProtocol;
216 ReadPublicInterfaces($className, $parentClassName, $defines);
218 # Start actual generation..
219 $object->GenerateHeader($dataNode);
220 $object->GenerateImplementation($dataNode) unless $noImpl;
223 $object->WriteData("DOM" . $name);
225 # Check for missing public API
226 if (keys %publicInterfaces > 0) {
227 my $missing = join("\n", keys %publicInterfaces);
228 die "error: Public API change. There are missing public properties and/or methods from the \"$className\" class.\n$missing\n";
232 # Params: 'idlDocument' struct
236 my $dataNode = shift;
238 $module = $dataNode->module;
243 my $name = $codeGenerator->StripModule(shift);
246 return "NSString" if $codeGenerator->IsStringType($name);
247 return "NS$name" if IsNativeObjCType($name);
248 return "BOOL" if $name eq "boolean";
249 return "unsigned" if $name eq "unsigned long";
250 return "int" if $name eq "long";
251 return "DOMAbstractView" if $name eq "DOMWindow";
252 return $name if $codeGenerator->IsPrimitiveType($name) or $name eq "DOMImplementation" or $name eq "DOMTimeStamp";
254 # Default, assume Objective-C type has the same type name as
255 # idl type prefixed with "DOM".
259 sub GetClassHeaderName
263 return "DOMDOMImplementation" if $name eq "DOMImplementation";
269 my $name = $codeGenerator->StripModule(shift);
272 return "DOMImplementationFront" if $name eq "DOMImplementation";
273 return "RectImpl" if $name eq "Rect";
274 return "DOMWindow" if $name eq "AbstractView";
279 sub GetParentImplClassName
281 my $dataNode = shift;
283 return "Object" if @{$dataNode->parents} eq 0;
285 my $parent = $codeGenerator->StripModule($dataNode->parents(0));
288 return "Node" if $parent eq "EventTargetNode";
289 return "Object" if $parent eq "HTMLCollection";
294 sub GetParentAndProtocols
296 my $dataNode = shift;
297 my $numParents = @{$dataNode->parents};
301 if ($numParents eq 0) {
303 push(@protocols, "NSObject");
304 push(@protocols, "NSCopying") if $dataNode->name eq "EventTarget";
306 $parent = "DOMObject";
308 } elsif ($numParents eq 1) {
309 my $parentName = $codeGenerator->StripModule($dataNode->parents(0));
311 die "Parents of protocols must also be protocols." unless IsProtocolType($parentName);
312 push(@protocols, "DOM" . $parentName);
314 if (IsProtocolType($parentName)) {
315 push(@protocols, "DOM" . $parentName);
316 } elsif ($parentName eq "EventTargetNode") {
318 } elsif ($parentName eq "HTMLCollection") {
319 $parent = "DOMObject";
321 $parent = "DOM" . $parentName;
325 my @parents = @{$dataNode->parents};
326 my $firstParent = $codeGenerator->StripModule(shift(@parents));
327 if (IsProtocolType($firstParent)) {
328 push(@protocols, "DOM" . $firstParent);
330 $parent = "DOM" . $firstParent;
333 foreach my $parentName (@parents) {
334 $parentName = $codeGenerator->StripModule($parentName);
335 die "Everything past the first class should be a protocol!" unless IsProtocolType($parentName);
337 push(@protocols, "DOM" . $parentName);
341 return ($parent, @protocols);
348 return $parent if $parent eq "Object" or IsBaseType($parent);
349 return "Event" if $parent eq "UIEvent";
350 return "CSSValue" if $parent eq "SVGColor";
358 return 1 if $baseTypeHash{$type};
366 return 1 if $protocolTypeHash{$type};
374 return 1 if $nativeObjCTypeHash{$type};
381 my $name = GetClassName($type);
383 return "id <$name>" if IsProtocolType($type);
384 return $name if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp";
385 return "unsigned short" if $type eq "CompareHow" or $type eq "SVGPaintType";
391 my $type = $codeGenerator->StripModule(shift);
393 return "" if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type) or IsNativeObjCType($type);
394 return "_RGBColorWithRGB" if $type eq "RGBColor";
397 if ($type =~ /^(HTML|CSS|SVG)/ or $type eq "DOMImplementation" or $type eq "CDATASection") {
399 } elsif ($type =~ /^XPath(.+)/) {
400 $typeMaker = "xpath" . $1;
401 } elsif ($type eq "DOMWindow") {
402 $typeMaker = "abstractView";
403 } elsif ($type eq "EventTarget") {
406 $typeMaker = lcfirst($type);
409 # put into the form "_fooBarWith" for type FooBar.
410 $typeMaker = "_" . $typeMaker . "With";
414 sub GetObjCTypeGetterName
416 my $type = $codeGenerator->StripModule(shift);
419 if ($type =~ /^(HTML|CSS|SVG)/ or $type eq "DOMImplementation" or $type eq "CDATASection") {
421 } elsif ($type =~ /^XPath(.+)/) {
422 $typeGetter = "xpath" . $1;
423 } elsif ($type eq "DOMWindow") {
424 $typeGetter = "abstractView";
426 $typeGetter = lcfirst($type);
429 # put into the form "_fooBar" for type FooBar.
430 return "_" . $typeGetter;
433 sub GetObjCTypeGetter
436 my $type = $codeGenerator->StripModule(shift);
438 return $argName if $codeGenerator->IsPrimitiveType($type) or $codeGenerator->IsStringType($type) or IsNativeObjCType($type);
439 return $argName . "EventTarget" if $type eq "EventTarget";
440 return "static_cast<WebCore::Range::CompareHow>($argName)" if $type eq "CompareHow";
441 return "static_cast<WebCore::SVGPaint::SVGPaintType>($argName)" if $type eq "SVGPaintType";
443 my $typeGetterMethodName = GetObjCTypeGetterName($type);
445 return "[nativeResolver $typeGetterMethodName]" if $type eq "XPathNSResolver";
446 return "[$argName $typeGetterMethodName]";
449 sub AddForwardDeclarationsForType
451 my $type = $codeGenerator->StripModule(shift);
454 return if $codeGenerator->IsNonPointerType($type) ;
456 my $class = GetClassName($type);
458 if (IsProtocolType($type)) {
459 $headerForwardDeclarationsForProtocols{$class} = 1 if $public;
460 $privateHeaderForwardDeclarationsForProtocols{$class} = 1 if !$public and !$headerForwardDeclarationsForProtocols{$class};
464 $headerForwardDeclarations{$class} = 1 if $public;
466 # Private headers include the public header, so only add a forward declaration to the private header
467 # if the public header does not already have the same forward declaration.
468 $privateHeaderForwardDeclarations{$class} = 1 if !$public and !$headerForwardDeclarations{$class};
471 sub AddIncludesForType
473 my $type = $codeGenerator->StripModule(shift);
475 return if $codeGenerator->IsNonPointerType($type) or IsNativeObjCType($type);
477 if ($codeGenerator->IsStringType($type)) {
478 $implIncludes{"PlatformString.h"} = 1;
482 if ($type eq "Rect") {
483 $implIncludes{"RectImpl.h"} = 1;
484 $implIncludes{"DOM$type.h"} = 1;
488 if ($type eq "RGBColor") {
489 $implIncludes{"Color.h"} = 1;
490 $implIncludes{"DOM$type.h"} = 1;
494 if ($type eq "DOMWindow") {
495 $implIncludes{"DOMAbstractView.h"} = 1;
496 $implIncludes{"$type.h"} = 1;
500 if ($type eq "DOMImplementation") {
501 $implIncludes{"DOMImplementationFront.h"} = 1;
502 $implIncludes{"DOM$type.h"} = 1;
506 if ($type eq "EventTarget") {
507 $implIncludes{"EventTargetNode.h"} = 1;
508 $implIncludes{"DOM$type.h"} = 1;
512 if ($codeGenerator->IsSVGAnimatedType($type)) {
513 $implIncludes{"SVGAnimatedTemplate.h"} = 1;
514 $implIncludes{"DOM$type.h"} = 1;
518 if ($type eq "SVGRect") {
519 $implIncludes{"FloatRect.h"} = 1;
520 $implIncludes{"DOM$type.h"} = 1;
524 if ($type eq "SVGPoint") {
525 $implIncludes{"FloatPoint.h"} = 1;
526 $implIncludes{"DOM$type.h"} = 1;
530 if ($type eq "SVGNumber") {
531 $implIncludes{"DOM$type.h"} = 1;
535 if ($type =~ /(\w+)(Abs|Rel)$/) {
536 $implIncludes{"$1.h"} = 1;
537 $implIncludes{"DOM$type.h"} = 1;
542 # FIXME: won't compile without these
543 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration";
544 $implIncludes{"NamedAttrMap.h"} = 1 if $type eq "NamedNodeMap";
545 $implIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList";
547 # Default, include the same named file (the implementation) and the same name prefixed with "DOM".
548 $implIncludes{"$type.h"} = 1;
549 $implIncludes{"DOM$type.h"} = 1;
555 my $dataNode = shift;
557 # We only support multiple parents with SVG (for now).
558 if (@{$dataNode->parents} > 1) {
559 die "A class can't have more than one parent" unless $module eq "svg";
562 my $interfaceName = $dataNode->name;
563 my $className = GetClassName($interfaceName);
566 my @protocolsToImplement = ();
567 ($parentName, @protocolsToImplement) = GetParentAndProtocols($dataNode);
569 my $numConstants = @{$dataNode->constants};
570 my $numAttributes = @{$dataNode->attributes};
571 my $numFunctions = @{$dataNode->functions};
573 # - Add default header template
574 @headerContentHeader = split("\r", $headerLicenceTemplate);
575 push(@headerContentHeader, "\n");
578 unless ($isProtocol) {
579 my $parentHeaderName = GetClassHeaderName($parentName);
580 push(@headerContentHeader, "#import <WebCore/$parentHeaderName.h>\n");
582 foreach my $parentProtocol (@protocolsToImplement) {
583 next if $parentProtocol =~ /^NS/;
584 $parentProtocol = GetClassHeaderName($parentProtocol);
585 push(@headerContentHeader, "#import <WebCore/$parentProtocol.h>\n");
588 # Special case needed for legacy support of DOMRange
589 if ($interfaceName eq "Range") {
590 push(@headerContentHeader, "#import <WebCore/DOMCore.h>\n");
591 push(@headerContentHeader, "#import <WebCore/DOMDocument.h>\n");
592 push(@headerContentHeader, "#import <WebCore/DOMRangeException.h>\n");
595 push(@headerContentHeader, "\n");
598 if ($numConstants > 0) {
599 my @headerConstants = ();
601 # FIXME: we need a way to include multiple enums.
602 foreach my $constant (@{$dataNode->constants}) {
603 my $constantName = $constant->name;
604 my $constantValue = $constant->value;
606 my $output = " DOM_" . $constantName . " = " . $constantValue;
607 push(@headerConstants, $output);
610 my $combinedConstants = join(",\n", @headerConstants);
612 # FIXME: the formatting of the enums should line up the equal signs.
613 # FIXME: enums are unconditionally placed in the public header.
614 push(@headerContent, "enum {\n");
615 push(@headerContent, $combinedConstants);
616 push(@headerContent, "\n};\n\n");
619 # - Begin @interface or @protocol
621 my $parentProtocols = join(", ", @protocolsToImplement);
622 push(@headerContent, "\@protocol $className <$parentProtocols>\n");
624 if (@protocolsToImplement eq 0) {
625 push(@headerContent, "\@interface $className : $parentName\n");
627 my $parentProtocols = join(", ", @protocolsToImplement);
628 push(@headerContent, "\@interface $className : $parentName <$parentProtocols>\n");
632 my @headerAttributes = ();
633 my @privateHeaderAttributes = ();
635 # - Add attribute getters/setters.
636 if ($numAttributes > 0) {
637 # Add ivars, if any, first
639 foreach my $attribute (@{$dataNode->attributes}) {
640 push(@ivars, $attribute) if $attribute->signature->extendedAttributes->{"ObjCIvar"};
643 push(@headerAttributes, "{\n");
644 foreach my $attribute (@ivars) {
645 my $type = GetObjCType($attribute->signature->type);;
646 my $name = "m_" . $attribute->signature->name;
647 my $ivarDeclaration = "$type $name";
648 push(@headerAttributes, " $ivarDeclaration;\n");
650 push(@headerAttributes, "}\n");
653 foreach my $attribute (@{$dataNode->attributes}) {
654 my $attributeName = $attribute->signature->name;
656 if ($attributeName eq "id") {
657 # Special case attribute id to be idName to avoid Obj-C nameing conflict.
658 $attributeName .= "Name";
659 } elsif ($attributeName eq "frame") {
660 # Special case attribute frame to be frameBorders.
661 $attributeName .= "Borders";
664 my $attributeType = GetObjCType($attribute->signature->type);
665 my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
667 my $property = "\@property" . ($attributeIsReadonly ? "(readonly)" : "") . " " . $attributeType . ($attributeType =~ /\*$/ ? "" : " ") . $attributeName . ";";
669 my $public = ($publicInterfaces{$property} or $newPublicClass);
670 delete $publicInterfaces{$property};
672 AddForwardDeclarationsForType($attribute->signature->type, $public);
674 if ($buildingForLeopardOrLater) {
676 push(@headerAttributes, $property) if $public;
677 push(@privateHeaderAttributes, $property) unless $public;
680 my $getter = "- (" . $attributeType . ")" . $attributeName . ";\n";
681 push(@headerAttributes, $getter) if $public;
682 push(@privateHeaderAttributes, $getter) unless $public;
685 if (!$attributeIsReadonly) {
686 my $setter = "- (void)set" . WK_ucfirst($attributeName) . ":(" . $attributeType . ")new" . WK_ucfirst($attributeName) . ";\n";
687 push(@headerAttributes, $setter) if $public;
688 push(@privateHeaderAttributes, $setter) unless $public;
693 push(@headerContent, @headerAttributes) if @headerAttributes > 0;
696 my @headerFunctions = ();
697 my @privateHeaderFunctions = ();
698 my @deprecatedHeaderFunctions = ();
701 if ($numFunctions > 0) {
702 foreach my $function (@{$dataNode->functions}) {
703 my $functionName = $function->signature->name;
704 my $returnType = GetObjCType($function->signature->type);
705 my $needsDeprecatedVersion = (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"});
706 my $numberOfParameters = @{$function->parameters};
707 my %typesToForwardDeclare = ($function->signature->type => 1);
709 my $parameterIndex = 0;
710 my $functionSig = "- ($returnType)$functionName";
711 foreach my $param (@{$function->parameters}) {
712 my $paramName = $param->name;
713 my $paramType = GetObjCType($param->type);
715 $typesToForwardDeclare{$param->type} = 1;
717 if ($parameterIndex >= 1) {
718 my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"};
719 $paramPrefix = $paramName unless defined($paramPrefix);
720 $functionSig .= " $paramPrefix";
723 $functionSig .= ":($paramType)$paramName";
730 my $public = ($publicInterfaces{$functionSig} or $newPublicClass);
731 delete $publicInterfaces{$functionSig};
733 $functionSig .= "\n";
735 foreach my $type (keys %typesToForwardDeclare) {
736 # add any forward declarations to the public header if a deprecated version will be generated
737 AddForwardDeclarationsForType($type, 1) if $needsDeprecatedVersion;
738 AddForwardDeclarationsForType($type, $public) unless $public and $needsDeprecatedVersion;
741 push(@headerFunctions, $functionSig) if $public;
742 push(@privateHeaderFunctions, $functionSig) unless $public;
744 # generate the old style method names with un-named parameters, these methods are deprecated
745 if ($needsDeprecatedVersion) {
746 my $deprecatedFunctionSig = $functionSig;
747 $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names
748 my $deprecatedFunctionKey = $deprecatedFunctionSig;
750 $deprecatedFunctionSig =~ s/;\n$/ DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER;\n/ if $buildingForLeopardOrLater;
751 push(@deprecatedHeaderFunctions, $deprecatedFunctionSig);
753 $deprecatedFunctionKey =~ s/\n$//; # remove the newline
754 delete $publicInterfaces{$deprecatedFunctionKey};
758 if (@headerFunctions > 0) {
759 push(@headerContent, "\n") if $buildingForLeopardOrLater and @headerAttributes > 0;
760 push(@headerContent, @headerFunctions);
764 # - End @interface or @protocol
765 push(@headerContent, "\@end\n");
767 if (@deprecatedHeaderFunctions > 0) {
768 # - Deprecated category @interface
769 push(@headerContent, "\n\@interface $className (" . $className . "Deprecated)\n");
770 push(@headerContent, @deprecatedHeaderFunctions);
771 push(@headerContent, "\@end\n");
774 if (@privateHeaderAttributes > 0 or @privateHeaderFunctions > 0) {
775 # - Private category @interface
776 @privateHeaderContentHeader = split("\r", $headerLicenceTemplate);
777 push(@headerContentHeader, "\n");
779 my $classHeaderName = GetClassHeaderName($className);
780 push(@privateHeaderContentHeader, "#import <WebCore/$classHeaderName.h>\n\n");
782 @privateHeaderContent = ();
783 push(@privateHeaderContent, "\@interface $className (" . $className . "Private)\n");
784 push(@privateHeaderContent, @privateHeaderAttributes) if @privateHeaderAttributes > 0;
785 push(@privateHeaderContent, "\n") if $buildingForLeopardOrLater and @privateHeaderAttributes > 0 and @privateHeaderFunctions > 0;
786 push(@privateHeaderContent, @privateHeaderFunctions) if @privateHeaderFunctions > 0;
787 push(@privateHeaderContent, "\@end\n");
791 sub GenerateImplementation
794 my $dataNode = shift;
796 # We only support multiple parents with SVG (for now).
797 if (@{$dataNode->parents} > 1) {
798 die "A class can't have more than one parent" unless $module eq "svg";
799 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode);
802 my $interfaceName = $dataNode->name;
803 my $className = GetClassName($interfaceName);
804 my $implClassName = GetImplClassName($interfaceName);
805 my $parentImplClassName = GetParentImplClassName($dataNode);
806 my $implClassNameWithNamespace = "WebCore::" . $implClassName;
807 my $baseClass = GetBaseClass($parentImplClassName);
808 my $classHeaderName = GetClassHeaderName($className);
809 my $conditional = $dataNode->extendedAttributes->{"Conditional"};
811 my $numAttributes = @{$dataNode->attributes};
812 my $numFunctions = @{$dataNode->functions};
814 # - Add default header template.
815 @implContentHeader = split("\r", $implementationLicenceTemplate);
818 push(@implContentHeader, "\n#import \"config.h\"\n");
819 push(@implContentHeader, "\n#ifdef ${conditional}_SUPPORT\n\n") if $conditional;
820 push(@implContentHeader, "#import \"$classHeaderName.h\"\n\n");
821 push(@implContentHeader, "#import <wtf/GetPtr.h>\n\n");
823 if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
824 $implIncludes{"SVGAnimatedTemplate.h"} = 1;
825 } elsif ($interfaceName =~ /(\w+)(Abs|Rel)$/) {
826 $implIncludes{"$1.h"} = 1;
828 $implIncludes{"$implClassName.h"} = 1;
831 $implIncludes{"DOMInternal.h"} = 1;
832 $implIncludes{"ExceptionHandlers.h"} = 1;
836 # add implementation accessor
837 if ($parentImplClassName eq "Object") {
838 push(@implContent, "#define IMPL reinterpret_cast<$implClassNameWithNamespace*>(_internal)\n\n");
840 my $baseClassWithNamespace = "WebCore::$baseClass";
841 push(@implContent, "#define IMPL static_cast<$implClassNameWithNamespace*>(reinterpret_cast<$baseClassWithNamespace*>(_internal))\n\n");
844 # START implementation
845 push(@implContent, "\@implementation $className\n\n");
847 # Only generate 'dealloc' and 'finalize' methods for direct subclasses of DOMObject.
848 if ($parentImplClassName eq "Object") {
849 my @ivarsToRelease = ();
851 foreach $attribute (@ivars) {
852 my $name = "m_" . $attribute->signature->name;
853 push(@ivarsToRelease, " [$name release];\n");
857 push(@implContent, "- (void)dealloc\n");
858 push(@implContent, "{\n");
859 push(@implContent, @ivarsToRelease);
860 if ($interfaceName eq "NodeIterator") {
861 push(@implContent, " if (_internal) {\n");
862 push(@implContent, " [self detach];\n");
863 push(@implContent, " IMPL->deref();\n");
864 push(@implContent, " };\n");
866 push(@implContent, " if (_internal)\n");
867 push(@implContent, " IMPL->deref();\n");
869 push(@implContent, " [super dealloc];\n");
870 push(@implContent, "}\n\n");
872 push(@implContent, "- (void)finalize\n");
873 push(@implContent, "{\n");
874 if ($interfaceName eq "NodeIterator") {
875 push(@implContent, " if (_internal) {\n");
876 push(@implContent, " [self detach];\n");
877 push(@implContent, " IMPL->deref();\n");
878 push(@implContent, " };\n");
880 push(@implContent, " if (_internal)\n");
881 push(@implContent, " IMPL->deref();\n");
883 push(@implContent, " [super finalize];\n");
884 push(@implContent, "}\n\n");
888 %attributeNames = ();
891 if ($numAttributes > 0) {
892 foreach my $attribute (@{$dataNode->attributes}) {
893 AddIncludesForType($attribute->signature->type);
895 my $idlType = $codeGenerator->StripModule($attribute->signature->type);
897 my $attributeName = $attribute->signature->name;
898 my $attributeType = GetObjCType($attribute->signature->type);
899 my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
900 my $attributeClassName = GetClassName($attribute->signature->type);
902 my $attributeInterfaceName = $attributeName;
903 if ($attributeName eq "id") {
904 # Special case attribute id to be idName to avoid Obj-C nameing conflict.
905 $attributeInterfaceName .= "Name";
906 } elsif ($attributeName eq "frame") {
907 # Special case attribute frame to be frameBorders.
908 $attributeInterfaceName .= "Borders";
909 } elsif ($attributeName eq "ownerDocument") {
910 # FIXME: for now special case attribute ownerDocument to call document, this is incorrect
911 # legacy behavior. (see http://bugs.webkit.org/show_bug.cgi?id=10889)
912 $attributeName = "document";
913 } elsif ($codeGenerator->IsSVGAnimatedType($idlType)) {
914 # Special case for animated types.
915 $attributeName .= "Animated";
918 $attributeNames{$attributeInterfaceName} = 1;
921 my $getterSig = "- ($attributeType)$attributeInterfaceName\n";
922 my $hasGetterException = @{$attribute->getterExceptions};
923 my $getterContentHead = "IMPL->$attributeName(";
924 my $getterContentTail = ")";
926 my $attributeTypeSansPtr = $attributeType;
927 $attributeTypeSansPtr =~ s/ \*$//; # Remove trailing " *" from pointer types.
929 # special case for EventTarget protocol
930 $attributeTypeSansPtr = "DOMNode" if $idlType eq "EventTarget";
932 my $typeMaker = GetObjCTypeMaker($attribute->signature->type);
935 my @customGetterContent = ();
936 if ($attributeTypeSansPtr eq "DOMImplementation") {
937 # FIXME: We have to special case DOMImplementation until DOMImplementationFront is removed
938 $getterContentHead = "[$attributeTypeSansPtr $typeMaker:implementationFront(IMPL";
939 $getterContentTail .= "]";
940 } elsif ($attributeName =~ /(\w+)DisplayString$/) {
941 my $attributeToDisplay = $1;
942 $getterContentHead = "WebCore::displayString(IMPL->$attributeToDisplay(), [self _element]";
943 } elsif ($attributeName =~ /^absolute(\w+)URL$/) {
945 $getterContentHead = "[self _getURLAttribute:";
946 if ($typeOfURL eq "Link") {
947 $getterContentTail = "\@\"href\"]";
948 } elsif ($typeOfURL eq "Image") {
949 if ($interfaceName eq "HTMLObjectElement") {
950 $getterContentTail = "\@\"data\"]";
952 $getterContentTail = "\@\"src\"]";
954 unless ($interfaceName eq "HTMLImageElement") {
955 push(@customGetterContent, " if (!IMPL->renderer() || !IMPL->renderer()->isImage())\n");
956 push(@customGetterContent, " return nil;\n");
957 $implIncludes{"RenderObject.h"} = 1;
960 $implIncludes{"DOMPrivate.h"} = 1;
961 } elsif ($idlType eq "NodeFilter") {
962 push(@customGetterContent, " if (m_filter)\n");
963 push(@customGetterContent, " // This node iterator was created from the Objective-C side.\n");
964 push(@customGetterContent, " return [[m_filter retain] autorelease];\n\n");
965 push(@customGetterContent, " // This node iterator was created from the C++ side.\n");
966 $getterContentHead = "[$attributeClassName $typeMaker:WTF::getPtr(" . $getterContentHead;
967 $getterContentTail .= ")]";
968 } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
969 $getterContentTail .= ".toInt()";
970 } elsif ($idlType eq "RGBColor" or $idlType eq "SVGPoint" or $idlType eq "SVGRect" or $idlType eq "SVGNumber") {
971 $getterContentHead = "[$attributeTypeSansPtr $typeMaker:" . $getterContentHead;
972 $getterContentTail .= "]";
973 } elsif ($typeMaker ne "") {
974 # Surround getter with TypeMaker
975 $getterContentHead = "[$attributeTypeSansPtr $typeMaker:WTF::getPtr(" . $getterContentHead;
976 $getterContentTail .= ")]";
980 if ($hasGetterException) {
981 $getterContent = $getterContentHead . "ec" . $getterContentTail;
983 $getterContent = $getterContentHead . $getterContentTail;
986 push(@implContent, $getterSig);
987 push(@implContent, "{\n");
988 push(@implContent, @customGetterContent);
989 if ($hasGetterException) {
990 # Differentiated between when the return type is a pointer and
991 # not for white space issue (ie. Foo *result vs. int result).
992 if ($attributeType =~ /\*$/) {
993 $getterContent = $attributeType . "result = " . $getterContent;
995 $getterContent = $attributeType . " result = " . $getterContent;
998 push(@implContent, " $exceptionInit\n");
999 push(@implContent, " $getterContent;\n");
1000 push(@implContent, " $exceptionRaiseOnError\n");
1001 push(@implContent, " return result;\n");
1003 push(@implContent, " return $getterContent;\n");
1005 push(@implContent, "}\n\n");
1008 if (!$attributeIsReadonly) {
1009 # Exception handling
1010 my $hasSetterException = @{$attribute->setterExceptions};
1012 $attributeName = "set" . WK_ucfirst($attributeName);
1013 my $setterName = "set" . WK_ucfirst($attributeInterfaceName);
1014 my $argName = "new" . WK_ucfirst($attributeInterfaceName);
1015 my $arg = GetObjCTypeGetter($argName, $idlType);
1017 if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
1018 $arg = "WebCore::String::number($arg)";
1021 my $setterSig = "- (void)$setterName:($attributeType)$argName\n";
1023 push(@implContent, $setterSig);
1024 push(@implContent, "{\n");
1026 unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) {
1027 push(@implContent, " ASSERT($argName);\n\n");
1030 if ($hasSetterException) {
1031 push(@implContent, " $exceptionInit\n");
1032 push(@implContent, " IMPL->$attributeName($arg, ec);\n");
1033 push(@implContent, " $exceptionRaiseOnError\n");
1035 push(@implContent, " IMPL->$attributeName($arg);\n");
1038 push(@implContent, "}\n\n");
1043 my @deprecatedFunctions = ();
1046 if ($numFunctions > 0) {
1047 foreach my $function (@{$dataNode->functions}) {
1048 AddIncludesForType($function->signature->type);
1050 my $functionName = $function->signature->name;
1051 my $returnType = GetObjCType($function->signature->type);
1052 my $hasParameters = @{$function->parameters};
1053 my $raisesExceptions = @{$function->raisesExceptions};
1055 my @parameterNames = ();
1056 my @needsAssert = ();
1057 my %needsCustom = ();
1059 my $parameterIndex = 0;
1060 my $functionSig = "- ($returnType)$functionName";
1061 foreach my $param (@{$function->parameters}) {
1062 my $paramName = $param->name;
1063 my $paramType = GetObjCType($param->type);
1065 # make a new parameter name if the original conflicts with a property name
1066 $paramName = "in" . WK_ucfirst($paramName) if $attributeNames{$paramName};
1068 AddIncludesForType($param->type);
1070 my $idlType = $codeGenerator->StripModule($param->type);
1071 my $implGetter = GetObjCTypeGetter($paramName, $idlType);
1073 push(@parameterNames, $implGetter);
1074 $needsCustom{"XPathNSResolver"} = $paramName if $idlType eq "XPathNSResolver";
1075 $needsCustom{"EventTarget"} = $paramName if $idlType eq "EventTarget";
1076 $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"};
1078 unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) {
1079 push(@needsAssert, " ASSERT($paramName);\n");
1082 if ($parameterIndex >= 1) {
1083 my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"};
1084 $paramPrefix = $param->name unless defined($paramPrefix);
1085 $functionSig .= " $paramPrefix";
1088 $functionSig .= ":($paramType)$paramName";
1093 push(@parameterNames, "ec") if $raisesExceptions;
1095 my @functionContent = ();
1096 my $caller = "IMPL";
1098 # special case the XPathNSResolver
1099 if (defined $needsCustom{"XPathNSResolver"}) {
1100 my $paramName = $needsCustom{"XPathNSResolver"};
1101 push(@functionContent, " if ($paramName && ![$paramName isMemberOfClass:[DOMNativeXPathNSResolver class]])\n");
1102 push(@functionContent, " [NSException raise:NSGenericException format:\@\"createExpression currently does not work with custom NS resolvers\"];\n");
1103 push(@functionContent, " DOMNativeXPathNSResolver *nativeResolver = (DOMNativeXPathNSResolver *)$paramName;\n\n");
1106 # special case the EventTarget
1107 if (defined $needsCustom{"EventTarget"}) {
1108 my $paramName = $needsCustom{"EventTarget"};
1109 push(@functionContent, " DOMNode* ${paramName}ObjC = $paramName;\n");
1110 push(@functionContent, " WebCore::Node* ${paramName}Node = [${paramName}ObjC _node];\n");
1111 push(@functionContent, " WebCore::EventTargetNode* ${paramName}EventTarget = (${paramName}Node && ${paramName}Node->isEventTargetNode()) ? static_cast<WebCore::EventTargetNode*>(${paramName}Node) : 0;\n\n");
1112 $implIncludes{"DOMNode.h"} = 1;
1113 $implIncludes{"Node.h"} = 1;
1116 if ($function->signature->extendedAttributes->{"UsesView"}) {
1117 push(@functionContent, " WebCore::DOMWindow* dv = $caller->defaultView();\n");
1118 push(@functionContent, " if (!dv)\n");
1119 push(@functionContent, " return nil;\n");
1120 $implIncludes{"DOMWindow.h"} = 1;
1125 my $content = $caller . "->" . $functionName . "(" . join(", ", @parameterNames) . ")";
1127 if ($returnType eq "void") {
1128 # Special case 'void' return type.
1129 if ($raisesExceptions) {
1130 push(@functionContent, " $exceptionInit\n");
1131 push(@functionContent, " $content;\n");
1132 push(@functionContent, " $exceptionRaiseOnError\n");
1134 push(@functionContent, " $content;\n");
1136 } elsif (defined $needsCustom{"NodeToReturn"}) {
1137 # Special case the insertBefore, replaceChild, removeChild
1138 # and appendChild functions from DOMNode
1139 my $toReturn = $needsCustom{"NodeToReturn"};
1140 if ($raisesExceptions) {
1141 push(@functionContent, " $exceptionInit\n");
1142 push(@functionContent, " if ($content)\n");
1143 push(@functionContent, " return $toReturn;\n");
1144 push(@functionContent, " $exceptionRaiseOnError\n");
1145 push(@functionContent, " return nil;\n");
1147 push(@functionContent, " if ($content)\n");
1148 push(@functionContent, " return $toReturn;\n");
1149 push(@functionContent, " return nil;\n");
1152 my $typeMaker = GetObjCTypeMaker($function->signature->type);
1153 unless ($typeMaker eq "") {
1154 my $returnTypeClass = "";
1155 if ($function->signature->type eq "XPathNSResolver") {
1156 # Special case XPathNSResolver
1157 $returnTypeClass = "DOMNativeXPathNSResolver";
1159 # Remove trailing " *" from pointer types.
1160 $returnTypeClass = $returnType;
1161 $returnTypeClass =~ s/ \*$//;
1164 # Surround getter with TypeMaker
1165 if ($returnTypeClass eq "DOMRGBColor" or $returnTypeClass eq "DOMSVGPoint" or $returnTypeClass eq "DOMSVGRect" or $returnTypeClass eq "DOMSVGNumber") {
1166 $content = "[$returnTypeClass $typeMaker:" . $content . "]";
1168 $content = "[$returnTypeClass $typeMaker:WTF::getPtr(" . $content . ")]";
1172 if ($raisesExceptions) {
1173 # Differentiated between when the return type is a pointer and
1174 # not for white space issue (ie. Foo *result vs. int result).
1175 if ($returnType =~ /\*$/) {
1176 $content = $returnType . "result = " . $content;
1178 $content = $returnType . " result = " . $content;
1181 push(@functionContent, " $exceptionInit\n");
1182 push(@functionContent, " $content;\n");
1183 push(@functionContent, " $exceptionRaiseOnError\n");
1184 push(@functionContent, " return result;\n");
1186 push(@functionContent, " return $content;\n");
1190 push(@implContent, "$functionSig\n");
1191 push(@implContent, "{\n");
1192 push(@implContent, @functionContent);
1193 push(@implContent, "}\n\n");
1195 # generate the old style method names with un-named parameters, these methods are deprecated
1196 if (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"}) {
1197 my $deprecatedFunctionSig = $functionSig;
1198 $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names
1200 push(@deprecatedFunctions, "$deprecatedFunctionSig\n");
1201 push(@deprecatedFunctions, "{\n");
1202 push(@deprecatedFunctions, @functionContent);
1203 push(@deprecatedFunctions, "}\n\n");
1211 # END implementation
1212 push(@implContent, "\@end\n");
1214 if (@deprecatedFunctions > 0) {
1215 # - Deprecated category @implementation
1216 push(@implContent, "\n\@implementation $className (" . $className . "Deprecated)\n\n");
1217 push(@implContent, @deprecatedFunctions);
1218 push(@implContent, "\@end\n");
1222 # Generate internal interfaces
1225 # - (WebCore::FooBar *)_fooBar for implementation class FooBar
1226 my $typeGetterName = GetObjCTypeGetterName($interfaceName);
1227 my $typeGetterSig = "- ($implClassNameWithNamespace *)$typeGetterName";
1229 my @ivarsToRetain = ();
1230 my $ivarsToInit = "";
1231 my $typeMakerSigAddition = "";
1233 my @ivarsInitSig = ();
1234 my @ivarsInitCall = ();
1235 foreach $attribute (@ivars) {
1236 my $name = $attribute->signature->name;
1237 my $memberName = "m_" . $name;
1238 my $varName = "in" . $name;
1239 my $type = GetObjCType($attribute->signature->type);
1240 push(@ivarsInitSig, "$name:($type)$varName");
1241 push(@ivarsInitCall, "$name:$varName");
1242 push(@ivarsToRetain, " $memberName = [$varName retain];\n");
1244 $ivarsToInit = " " . join(" ", @ivarsInitCall);
1245 $typeMakerSigAddition = " " . join(" ", @ivarsInitSig);
1249 my $typeMakerName = GetObjCTypeMaker($interfaceName);
1250 my $typeMakerSig = "+ ($className *)$typeMakerName:($implClassNameWithNamespace *)impl" . $typeMakerSigAddition;
1252 # Generate interface definitions.
1253 @intenalHeaderContent = split("\r", $implementationLicenceTemplate);
1254 push(@intenalHeaderContent, "\n#import <WebCore/$className.h>\n");
1255 if ($codeGenerator->IsSVGAnimatedType($interfaceName)) {
1256 push(@intenalHeaderContent, "#import <WebCore/SVGAnimatedTemplate.h>\n\n");
1258 push(@intenalHeaderContent, "\nnamespace WebCore { class $implClassName; }\n\n");
1260 push(@intenalHeaderContent, "\@interface $className (WebCoreInternal)\n");
1261 push(@intenalHeaderContent, $typeGetterSig . ";\n");
1262 push(@intenalHeaderContent, $typeMakerSig . ";\n");
1263 push(@intenalHeaderContent, "\@end\n");
1265 unless ($dataNode->extendedAttributes->{ObjCCustomInternalImpl}) {
1266 # - BEGIN WebCoreInternal category @implementation
1267 push(@implContent, "\n\@implementation $className (WebCoreInternal)\n\n");
1269 push(@implContent, "$typeGetterSig\n");
1270 push(@implContent, "{\n");
1271 push(@implContent, " return IMPL;\n");
1272 push(@implContent, "}\n\n");
1274 if ($parentImplClassName eq "Object") {
1275 # - (id)_initWithFooBar:(WebCore::FooBar *)impl for implementation class FooBar
1276 my $initWithImplName = "_initWith" . $implClassName;
1277 my $initWithSig = "- (id)$initWithImplName:($implClassNameWithNamespace *)impl" . $typeMakerSigAddition;
1279 push(@implContent, "$initWithSig\n");
1280 push(@implContent, "{\n");
1281 push(@implContent, " [super _init];\n");
1282 push(@implContent, " _internal = reinterpret_cast<DOMObjectInternal*>(impl);\n");
1283 push(@implContent, " impl->ref();\n");
1284 push(@implContent, " WebCore::addDOMWrapper(self, impl);\n");
1285 push(@implContent, @ivarsToRetain);
1286 push(@implContent, " return self;\n");
1287 push(@implContent, "}\n\n");
1289 # - (DOMFooBar)_FooBarWith:(WebCore::FooBar *)impl for implementation class FooBar
1290 push(@implContent, "$typeMakerSig\n");
1291 push(@implContent, "{\n");
1292 push(@implContent, " if (!impl)\n");
1293 push(@implContent, " return nil;\n");
1294 push(@implContent, " id cachedInstance;\n");
1295 push(@implContent, " cachedInstance = WebCore::getDOMWrapper(impl);\n");
1296 push(@implContent, " if (cachedInstance)\n");
1297 push(@implContent, " return [[cachedInstance retain] autorelease];\n");
1298 push(@implContent, " return [[[self alloc] $initWithImplName:impl" . $ivarsToInit . "] autorelease];\n");
1299 push(@implContent, "}\n\n");
1301 my $internalBaseType = "DOM$baseClass";
1302 my $internalBaseTypeMaker = GetObjCTypeMaker($baseClass);
1304 # - (DOMFooBar)_FooBarWith:(WebCore::FooBar *)impl for implementation class FooBar
1305 push(@implContent, "$typeMakerSig\n");
1306 push(@implContent, "{\n");
1307 push(@implContent, " return static_cast<$className*>([$internalBaseType $internalBaseTypeMaker:impl]);\n");
1308 push(@implContent, "}\n\n");
1311 # END WebCoreInternal category
1312 push(@implContent, "\@end\n");
1315 # - End the ifdef conditional if necessary
1316 push(@implContent, "\n#endif // ${conditional}_SUPPORT\n") if $conditional;
1325 # Open files for writing...
1326 my $headerFileName = "$outputDir/" . $name . ".h";
1327 my $privateHeaderFileName = "$outputDir/" . $name . "Private.h";
1328 my $implFileName = "$outputDir/" . $name . ".mm";
1329 my $internalHeaderFileName = "$outputDir/" . $name . "Internal.h";
1332 unlink($headerFileName);
1333 unlink($privateHeaderFileName);
1334 unlink($implFileName);
1335 unlink($internalHeaderFileName);
1337 # Write public header.
1338 open(HEADER, ">$headerFileName") or die "Couldn't open file $headerFileName";
1340 print HEADER @headerContentHeader;
1341 print HEADER map { "\@class $_;\n" } sort keys(%headerForwardDeclarations);
1342 print HEADER map { "\@protocol $_;\n" } sort keys(%headerForwardDeclarationsForProtocols);
1344 my $hasForwardDeclarations = keys(%headerForwardDeclarations) + keys(%headerForwardDeclarationsForProtocols);
1345 print HEADER "\n" if $hasForwardDeclarations;
1346 print HEADER @headerContent;
1350 @headerContentHeader = ();
1351 @headerContent = ();
1352 %headerForwardDeclarations = ();
1353 %headerForwardDeclarationsForProtocols = ();
1355 if (@privateHeaderContent > 0) {
1356 open(PRIVATE_HEADER, ">$privateHeaderFileName") or die "Couldn't open file $privateHeaderFileName";
1358 print PRIVATE_HEADER @privateHeaderContentHeader;
1359 print PRIVATE_HEADER map { "\@class $_;\n" } sort keys(%privateHeaderForwardDeclarations);
1360 print PRIVATE_HEADER map { "\@protocol $_;\n" } sort keys(%privateHeaderForwardDeclarationsForProtocols);
1362 $hasForwardDeclarations = keys(%privateHeaderForwardDeclarations) + keys(%privateHeaderForwardDeclarationsForProtocols);
1363 print PRIVATE_HEADER "\n" if $hasForwardDeclarations;
1364 print PRIVATE_HEADER @privateHeaderContent;
1366 close(PRIVATE_HEADER);
1368 @privateHeaderContentHeader = ();
1369 @privateHeaderContent = ();
1370 %privateHeaderForwardDeclarations = ();
1371 %privateHeaderForwardDeclarationsForProtocols = ();
1374 # Write implementation file.
1376 open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName";
1378 print IMPL @implContentHeader;
1379 print IMPL map { "#import \"$_\"\n" } sort keys(%implIncludes);
1381 print IMPL "\n" if keys(%implIncludes);
1382 print IMPL @implContent;
1386 @implContentHeader = ();
1391 if (@intenalHeaderContent > 0) {
1392 open(INTERNAL_HEADER, ">$internalHeaderFileName") or die "Couldn't open file $internalHeaderFileName";
1394 print INTERNAL_HEADER @intenalHeaderContent;
1396 close(INTERNAL_HEADER);
1398 @intenalHeaderContent = ();