1 # 2 # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann (at] kde.org> 3 # Copyright (C) 2006 Anders Carlsson <andersca (at] mac.com> 4 # Copyright (C) 2006, 2007 Samuel Weinig <sam (at] webkit.org> 5 # Copyright (C) 2006 Alexey Proskuryakov <ap (at] webkit.org> 6 # Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 7 # Copyright (C) 2009 Cameron McCormack <cam (at] mcc.id.au> 8 # 9 # This library is free software; you can redistribute it and/or 10 # modify it under the terms of the GNU Library General Public 11 # License as published by the Free Software Foundation; either 12 # version 2 of the License, or (at your option) any later version. 13 # 14 # This library is distributed in the hope that it will be useful, 15 # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 # Library General Public License for more details. 18 # 19 # You should have received a copy of the GNU Library General Public License 20 # aint with this library; see the file COPYING.LIB. If not, write to 21 # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 # Boston, MA 02110-1301, USA. 23 # 24 25 package CodeGeneratorObjC; 26 27 use File::stat; 28 29 # Global Variables 30 my $module = ""; 31 my $outputDir = ""; 32 my $writeDependencies = 0; 33 my %publicInterfaces = (); 34 my $newPublicClass = 0; 35 my $interfaceAvailabilityVersion = ""; 36 my $isProtocol = 0; 37 my $noImpl = 0; 38 39 my @headerContentHeader = (); 40 my @headerContent = (); 41 my %headerForwardDeclarations = (); 42 my %headerForwardDeclarationsForProtocols = (); 43 44 my @privateHeaderContentHeader = (); 45 my @privateHeaderContent = (); 46 my %privateHeaderForwardDeclarations = (); 47 my %privateHeaderForwardDeclarationsForProtocols = (); 48 49 my @internalHeaderContent = (); 50 51 my @implContentHeader = (); 52 my @implContent = (); 53 my %implIncludes = (); 54 my @depsContent = (); 55 56 # Hashes 57 my %protocolTypeHash = ("XPathNSResolver" => 1, "EventListener" => 1, "EventTarget" => 1, "NodeFilter" => 1, 58 "SVGLocatable" => 1, "SVGTransformable" => 1, "SVGStylable" => 1, "SVGFilterPrimitiveStandardAttributes" => 1, 59 "SVGTests" => 1, "SVGLangSpace" => 1, "SVGExternalResourcesRequired" => 1, "SVGURIReference" => 1, 60 "SVGZoomAndPan" => 1, "SVGFitToViewBox" => 1, "SVGAnimatedPathData" => 1, "SVGAnimatedPoints" => 1, 61 "ElementTimeControl" => 1); 62 my %nativeObjCTypeHash = ("URL" => 1, "Color" => 1); 63 64 # FIXME: this should be replaced with a function that recurses up the tree 65 # to find the actual base type. 66 my %baseTypeHash = ("Object" => 1, "Node" => 1, "NodeList" => 1, "NamedNodeMap" => 1, "DOMImplementation" => 1, 67 "Event" => 1, "CSSRule" => 1, "CSSValue" => 1, "StyleSheet" => 1, "MediaList" => 1, 68 "Counter" => 1, "Rect" => 1, "RGBColor" => 1, "XPathExpression" => 1, "XPathResult" => 1, 69 "NodeIterator" => 1, "TreeWalker" => 1, "AbstractView" => 1, "Blob" => 1, 70 "SVGAngle" => 1, "SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, "SVGAnimatedEnumeration" => 1, 71 "SVGAnimatedInteger" => 1, "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1, 72 "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, "SVGAnimatedPoints" => 1, 73 "SVGAnimatedPreserveAspectRatio" => 1, "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1, 74 "SVGAnimatedTransformList" => 1, "SVGLength" => 1, "SVGLengthList" => 1, "SVGMatrix" => 1, 75 "SVGNumber" => 1, "SVGNumberList" => 1, "SVGPathSeg" => 1, "SVGPathSegList" => 1, "SVGPoint" => 1, 76 "SVGPointList" => 1, "SVGPreserveAspectRatio" => 1, "SVGRect" => 1, "SVGRenderingIntent" => 1, 77 "SVGStringList" => 1, "SVGTransform" => 1, "SVGTransformList" => 1, "SVGUnitTypes" => 1); 78 79 # Constants 80 my $buildingForTigerOrEarlier = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} <= 10.4; 81 my $buildingForLeopardOrLater = 1 if $ENV{"MACOSX_DEPLOYMENT_TARGET"} and $ENV{"MACOSX_DEPLOYMENT_TARGET"} >= 10.5; 82 my $exceptionInit = "WebCore::ExceptionCode ec = 0;"; 83 my $exceptionRaiseOnError = "WebCore::raiseOnDOMError(ec);"; 84 my $assertMainThread = "{ DOM_ASSERT_MAIN_THREAD(); WebCoreThreadViolationCheckRoundOne(); }"; 85 86 my %conflictMethod = ( 87 # FIXME: Add C language keywords? 88 # FIXME: Add other predefined types like "id"? 89 90 "callWebScriptMethod:withArguments:" => "WebScriptObject", 91 "evaluateWebScript:" => "WebScriptObject", 92 "removeWebScriptKey:" => "WebScriptObject", 93 "setException:" => "WebScriptObject", 94 "setWebScriptValueAtIndex:value:" => "WebScriptObject", 95 "stringRepresentation" => "WebScriptObject", 96 "webScriptValueAtIndex:" => "WebScriptObject", 97 98 "autorelease" => "NSObject", 99 "awakeAfterUsingCoder:" => "NSObject", 100 "class" => "NSObject", 101 "classForCoder" => "NSObject", 102 "conformsToProtocol:" => "NSObject", 103 "copy" => "NSObject", 104 "copyWithZone:" => "NSObject", 105 "dealloc" => "NSObject", 106 "description" => "NSObject", 107 "doesNotRecognizeSelector:" => "NSObject", 108 "encodeWithCoder:" => "NSObject", 109 "finalize" => "NSObject", 110 "forwardInvocation:" => "NSObject", 111 "hash" => "NSObject", 112 "init" => "NSObject", 113 "initWithCoder:" => "NSObject", 114 "isEqual:" => "NSObject", 115 "isKindOfClass:" => "NSObject", 116 "isMemberOfClass:" => "NSObject", 117 "isProxy" => "NSObject", 118 "methodForSelector:" => "NSObject", 119 "methodSignatureForSelector:" => "NSObject", 120 "mutableCopy" => "NSObject", 121 "mutableCopyWithZone:" => "NSObject", 122 "performSelector:" => "NSObject", 123 "release" => "NSObject", 124 "replacementObjectForCoder:" => "NSObject", 125 "respondsToSelector:" => "NSObject", 126 "retain" => "NSObject", 127 "retainCount" => "NSObject", 128 "self" => "NSObject", 129 "superclass" => "NSObject", 130 "zone" => "NSObject", 131 ); 132 133 my $fatalError = 0; 134 135 # Default License Templates 136 my $headerLicenseTemplate = << "EOF"; 137 /* 138 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 139 * Copyright (C) 2006 Samuel Weinig <sam.weinig\@gmail.com> 140 * 141 * Redistribution and use in source and binary forms, with or without 142 * modification, are permitted provided that the following conditions 143 * are met: 144 * 1. Redistributions of source code must retain the above copyright 145 * notice, this list of conditions and the following disclaimer. 146 * 2. Redistributions in binary form must reproduce the above copyright 147 * notice, this list of conditions and the following disclaimer in the 148 * documentation and/or other materials provided with the distribution. 149 * 150 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 151 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 152 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 153 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 154 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 155 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 156 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 157 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 158 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 159 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 160 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 161 */ 162 EOF 163 164 my $implementationLicenseTemplate = << "EOF"; 165 /* 166 * This file is part of the WebKit open source project. 167 * This file has been generated by generate-bindings.pl. DO NOT MODIFY! 168 * 169 * Redistribution and use in source and binary forms, with or without 170 * modification, are permitted provided that the following conditions 171 * are met: 172 * 1. Redistributions of source code must retain the above copyright 173 * notice, this list of conditions and the following disclaimer. 174 * 2. Redistributions in binary form must reproduce the above copyright 175 * notice, this list of conditions and the following disclaimer in the 176 * documentation and/or other materials provided with the distribution. 177 * 178 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 179 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 181 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 182 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 183 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 184 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 185 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 186 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 187 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 188 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 189 */ 190 EOF 191 192 # Default constructor 193 sub new 194 { 195 my $object = shift; 196 my $reference = { }; 197 198 $codeGenerator = shift; 199 $outputDir = shift; 200 shift; # $useLayerOnTop 201 shift; # $preprocessor 202 $writeDependencies = shift; 203 204 bless($reference, $object); 205 return $reference; 206 } 207 208 sub finish 209 { 210 my $object = shift; 211 } 212 213 sub ReadPublicInterfaces 214 { 215 my $class = shift; 216 my $superClass = shift; 217 my $defines = shift; 218 my $isProtocol = shift; 219 220 my $found = 0; 221 my $actualSuperClass; 222 %publicInterfaces = (); 223 224 my $fileName = "WebCore/bindings/objc/PublicDOMInterfaces.h"; 225 open FILE, "-|", "/usr/bin/gcc", "-E", "-P", "-x", "objective-c", 226 (map { "-D$_" } split(/ +/, $defines)), "-DOBJC_CODE_GENERATION", $fileName or die "Could not open $fileName"; 227 my @documentContent = <FILE>; 228 close FILE; 229 230 foreach $line (@documentContent) { 231 if (!$isProtocol && $line =~ /^\s*\@interface\s*$class\s*:\s*(\w+)\s*([A-Z0-9_]*)/) { 232 if ($superClass ne $1) { 233 warn "Public API change. Superclass for \"$class\" differs ($1 != $superClass)"; 234 $fatalError = 1; 235 } 236 237 $interfaceAvailabilityVersion = $2 if defined $2; 238 $found = 1; 239 next; 240 } elsif ($isProtocol && $line =~ /^\s*\@protocol $class\s*<[^>]+>\s*([A-Z0-9_]*)/) { 241 $interfaceAvailabilityVersion = $1 if defined $1; 242 $found = 1; 243 next; 244 } 245 246 last if $found and $line =~ /^\s?\@end\s?$/; 247 248 if ($found) { 249 # trim whitspace 250 $line =~ s/^\s+//; 251 $line =~ s/\s+$//; 252 253 my $availabilityMacro = ""; 254 $line =~ s/\s([A-Z0-9_]+)\s*;$/;/; 255 $availabilityMacro = $1 if defined $1; 256 257 $publicInterfaces{$line} = $availabilityMacro if length $line; 258 } 259 } 260 261 # If this class was not found in PublicDOMInterfaces.h then it should be considered as an entirely new public class. 262 $newPublicClass = !$found; 263 $interfaceAvailabilityVersion = "WEBKIT_VERSION_LATEST" if $newPublicClass; 264 } 265 266 # Params: 'domClass' struct 267 sub GenerateInterface 268 { 269 my $object = shift; 270 my $dataNode = shift; 271 my $defines = shift; 272 273 $fatalError = 0; 274 275 my $name = $dataNode->name; 276 my $className = GetClassName($name); 277 my $parentClassName = "DOM" . GetParentImplClassName($dataNode); 278 $isProtocol = $dataNode->extendedAttributes->{ObjCProtocol}; 279 $noImpl = $dataNode->extendedAttributes->{ObjCCustomImplementation} || $isProtocol; 280 281 ReadPublicInterfaces($className, $parentClassName, $defines, $isProtocol); 282 283 # Start actual generation.. 284 $object->GenerateHeader($dataNode); 285 $object->GenerateImplementation($dataNode) unless $noImpl; 286 287 # Write changes. 288 $object->WriteData("DOM" . $name); 289 290 # Check for missing public API 291 if (keys %publicInterfaces > 0) { 292 my $missing = join("\n", keys %publicInterfaces); 293 warn "Public API change. There are missing public properties and/or methods from the \"$className\" class.\n$missing\n"; 294 $fatalError = 1; 295 } 296 297 die if $fatalError; 298 } 299 300 # Params: 'idlDocument' struct 301 sub GenerateModule 302 { 303 my $object = shift; 304 my $dataNode = shift; 305 306 $module = $dataNode->module; 307 } 308 309 sub GetClassName 310 { 311 my $name = $codeGenerator->StripModule(shift); 312 313 # special cases 314 return "NSString" if $codeGenerator->IsStringType($name) or $name eq "SerializedScriptValue"; 315 return "NS$name" if IsNativeObjCType($name); 316 return "BOOL" if $name eq "boolean"; 317 return "unsigned" if $name eq "unsigned long"; 318 return "int" if $name eq "long"; 319 return "NSTimeInterval" if $name eq "Date"; 320 return "DOMAbstractView" if $name eq "DOMWindow"; 321 return $name if $codeGenerator->IsPrimitiveType($name) or $name eq "DOMImplementation" or $name eq "DOMTimeStamp"; 322 323 # Default, assume Objective-C type has the same type name as 324 # idl type prefixed with "DOM". 325 return "DOM$name"; 326 } 327 328 sub GetClassHeaderName 329 { 330 my $name = shift; 331 332 return "DOMDOMImplementation" if $name eq "DOMImplementation"; 333 return $name; 334 } 335 336 sub GetImplClassName 337 { 338 my $name = $codeGenerator->StripModule(shift); 339 340 return "DOMImplementationFront" if $name eq "DOMImplementation"; 341 return "DOMWindow" if $name eq "AbstractView"; 342 return $name; 343 } 344 345 sub GetParentImplClassName 346 { 347 my $dataNode = shift; 348 349 return "Object" if @{$dataNode->parents} eq 0; 350 351 my $parent = $codeGenerator->StripModule($dataNode->parents(0)); 352 353 # special cases 354 return "Object" if $parent eq "HTMLCollection"; 355 356 return $parent; 357 } 358 359 sub GetParentAndProtocols 360 { 361 my $dataNode = shift; 362 my $numParents = @{$dataNode->parents}; 363 364 my $parent = ""; 365 my @protocols = (); 366 if ($numParents eq 0) { 367 if ($isProtocol) { 368 push(@protocols, "NSObject"); 369 push(@protocols, "NSCopying") if $dataNode->name eq "EventTarget"; 370 } else { 371 $parent = "DOMObject"; 372 } 373 } elsif ($numParents eq 1) { 374 my $parentName = $codeGenerator->StripModule($dataNode->parents(0)); 375 if ($isProtocol) { 376 die "Parents of protocols must also be protocols." unless IsProtocolType($parentName); 377 push(@protocols, "DOM" . $parentName); 378 } else { 379 if (IsProtocolType($parentName)) { 380 push(@protocols, "DOM" . $parentName); 381 } elsif ($parentName eq "HTMLCollection") { 382 $parent = "DOMObject"; 383 } else { 384 $parent = "DOM" . $parentName; 385 } 386 } 387 } else { 388 my @parents = @{$dataNode->parents}; 389 my $firstParent = $codeGenerator->StripModule(shift(@parents)); 390 if (IsProtocolType($firstParent)) { 391 push(@protocols, "DOM" . $firstParent); 392 if (!$isProtocol) { 393 $parent = "DOMObject"; 394 } 395 } else { 396 $parent = "DOM" . $firstParent; 397 } 398 399 foreach my $parentName (@parents) { 400 $parentName = $codeGenerator->StripModule($parentName); 401 die "Everything past the first class should be a protocol!" unless IsProtocolType($parentName); 402 403 push(@protocols, "DOM" . $parentName); 404 } 405 } 406 407 return ($parent, @protocols); 408 } 409 410 sub GetBaseClass 411 { 412 $parent = shift; 413 414 return $parent if $parent eq "Object" or IsBaseType($parent); 415 return "Event" if $parent eq "UIEvent"; 416 return "CSSValue" if $parent eq "SVGColor" or $parent eq "CSSValueList"; 417 return "Node"; 418 } 419 420 sub IsBaseType 421 { 422 my $type = shift; 423 424 return 1 if $baseTypeHash{$type}; 425 return 0; 426 } 427 428 sub IsProtocolType 429 { 430 my $type = shift; 431 432 return 1 if $protocolTypeHash{$type}; 433 return 0; 434 } 435 436 sub IsNativeObjCType 437 { 438 my $type = shift; 439 440 return 1 if $nativeObjCTypeHash{$type}; 441 return 0; 442 } 443 444 sub GetObjCType 445 { 446 my $type = shift; 447 my $name = GetClassName($type); 448 449 return "id <$name>" if IsProtocolType($type); 450 return $name if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp"; 451 return "unsigned short" if $type eq "CompareHow" or $type eq "SVGPaintType"; 452 return "$name *"; 453 } 454 455 sub GetPropertyAttributes 456 { 457 my $type = $codeGenerator->StripModule(shift); 458 my $readOnly = shift; 459 460 my @attributes = (); 461 462 push(@attributes, "readonly") if $readOnly; 463 464 # FIXME: <rdar://problem/5049934> Consider using 'nonatomic' on the DOM @property declarations. 465 if ($codeGenerator->IsStringType($type) || IsNativeObjCType($type)) { 466 push(@attributes, "copy"); 467 } elsif ($codeGenerator->IsPodType($type) || $codeGenerator->IsSVGAnimatedType($type)) { 468 push(@attributes, "retain"); 469 } elsif (!$codeGenerator->IsStringType($type) && !$codeGenerator->IsPrimitiveType($type) && $type ne "DOMTimeStamp" && $type ne "CompareHow" && $type ne "SVGPaintType") { 470 push(@attributes, "retain"); 471 } 472 473 return "" unless @attributes > 0; 474 return "(" . join(", ", @attributes) . ")"; 475 } 476 477 sub ConversionNeeded 478 { 479 my $type = $codeGenerator->StripModule(shift); 480 481 return !$codeGenerator->IsNonPointerType($type) && !$codeGenerator->IsStringType($type) && !IsNativeObjCType($type); 482 } 483 484 sub GetObjCTypeGetter 485 { 486 my $argName = shift; 487 my $type = $codeGenerator->StripModule(shift); 488 489 return $argName if $codeGenerator->IsPrimitiveType($type) or $codeGenerator->IsStringType($type) or IsNativeObjCType($type); 490 return $argName . "Node" if $type eq "EventTarget"; 491 return "static_cast<WebCore::Range::CompareHow>($argName)" if $type eq "CompareHow"; 492 return "static_cast<WebCore::SVGPaint::SVGPaintType>($argName)" if $type eq "SVGPaintType"; 493 return "WTF::getPtr(nativeEventListener)" if $type eq "EventListener"; 494 return "WTF::getPtr(nativeNodeFilter)" if $type eq "NodeFilter"; 495 return "WTF::getPtr(nativeResolver)" if $type eq "XPathNSResolver"; 496 497 if ($type eq "SerializedScriptValue") { 498 $implIncludes{"SerializedScriptValue.h"} = 1; 499 return "WebCore::SerializedScriptValue::create(WebCore::String($argName))"; 500 } 501 return "core($argName)"; 502 } 503 504 sub AddForwardDeclarationsForType 505 { 506 my $type = $codeGenerator->StripModule(shift); 507 my $public = shift; 508 509 return if $codeGenerator->IsNonPointerType($type) ; 510 511 my $class = GetClassName($type); 512 513 if (IsProtocolType($type)) { 514 $headerForwardDeclarationsForProtocols{$class} = 1 if $public; 515 $privateHeaderForwardDeclarationsForProtocols{$class} = 1 if !$public and !$headerForwardDeclarationsForProtocols{$class}; 516 return; 517 } 518 519 $headerForwardDeclarations{$class} = 1 if $public; 520 521 # Private headers include the public header, so only add a forward declaration to the private header 522 # if the public header does not already have the same forward declaration. 523 $privateHeaderForwardDeclarations{$class} = 1 if !$public and !$headerForwardDeclarations{$class}; 524 } 525 526 sub AddIncludesForType 527 { 528 my $type = $codeGenerator->StripModule(shift); 529 530 return if $codeGenerator->IsNonPointerType($type); 531 532 if (IsNativeObjCType($type)) { 533 if ($type eq "Color") { 534 $implIncludes{"ColorMac.h"} = 1; 535 } 536 return; 537 } 538 539 if ($codeGenerator->IsStringType($type)) { 540 $implIncludes{"KURL.h"} = 1; 541 return; 542 } 543 544 if ($type eq "DOMWindow") { 545 $implIncludes{"DOMAbstractViewInternal.h"} = 1; 546 $implIncludes{"DOMWindow.h"} = 1; 547 return; 548 } 549 550 if ($type eq "DOMImplementation") { 551 $implIncludes{"DOMDOMImplementationInternal.h"} = 1; 552 $implIncludes{"DOMImplementationFront.h"} = 1; 553 return; 554 } 555 556 if ($type eq "EventTarget") { 557 $implIncludes{"Node.h"} = 1; 558 $implIncludes{"DOMEventTarget.h"} = 1; 559 return; 560 } 561 562 if ($codeGenerator->IsSVGAnimatedType($type)) { 563 $implIncludes{"SVGAnimatedTemplate.h"} = 1; 564 $implIncludes{"DOM${type}Internal.h"} = 1; 565 return; 566 } 567 568 if ($type eq "SVGRect") { 569 $implIncludes{"FloatRect.h"} = 1; 570 $implIncludes{"DOMSVGRectInternal.h"} = 1; 571 return; 572 } 573 574 if ($type eq "SVGPoint") { 575 $implIncludes{"FloatPoint.h"} = 1; 576 $implIncludes{"DOMSVGPointInternal.h"} = 1; 577 return; 578 } 579 580 if ($type eq "SVGMatrix") { 581 $implIncludes{"AffineTransform.h"} = 1; 582 $implIncludes{"DOMSVGMatrixInternal.h"} = 1; 583 $implIncludes{"SVGException.h"} = 1; 584 return; 585 } 586 587 if ($type eq "SVGNumber") { 588 $implIncludes{"DOMSVGNumberInternal.h"} = 1; 589 return; 590 } 591 592 if ($type =~ /(\w+)(Abs|Rel)$/) { 593 $implIncludes{"$1.h"} = 1; 594 $implIncludes{"DOM${type}Internal.h"} = 1; 595 return; 596 } 597 598 if ($type eq "NodeFilter") { 599 $implIncludes{"NodeFilter.h"} = 1; 600 $implIncludes{"ObjCNodeFilterCondition.h"} = 1; 601 return; 602 } 603 604 if ($type eq "EventListener") { 605 $implIncludes{"EventListener.h"} = 1; 606 $implIncludes{"ObjCEventListener.h"} = 1; 607 return; 608 } 609 610 if ($type eq "XPathNSResolver") { 611 $implIncludes{"DOMCustomXPathNSResolver.h"} = 1; 612 $implIncludes{"XPathNSResolver.h"} = 1; 613 return; 614 } 615 616 if ($type eq "SerializedScriptValue") { 617 $implIncludes{"SerializedScriptValue.h"} = 1; 618 return; 619 } 620 621 # FIXME: won't compile without these 622 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration"; 623 $implIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList"; 624 625 # Default, include the same named file (the implementation) and the same name prefixed with "DOM". 626 $implIncludes{"$type.h"} = 1; 627 $implIncludes{"DOM${type}Internal.h"} = 1; 628 } 629 630 sub GenerateHeader 631 { 632 my $object = shift; 633 my $dataNode = shift; 634 635 my $interfaceName = $dataNode->name; 636 my $className = GetClassName($interfaceName); 637 638 my $parentName = ""; 639 my @protocolsToImplement = (); 640 ($parentName, @protocolsToImplement) = GetParentAndProtocols($dataNode); 641 642 my $numConstants = @{$dataNode->constants}; 643 my $numAttributes = @{$dataNode->attributes}; 644 my $numFunctions = @{$dataNode->functions}; 645 646 # - Add default header template 647 @headerContentHeader = split("\r", $headerLicenseTemplate); 648 push(@headerContentHeader, "\n"); 649 650 # - INCLUDES - 651 my $includedWebKitAvailabilityHeader = 0; 652 unless ($isProtocol) { 653 my $parentHeaderName = GetClassHeaderName($parentName); 654 push(@headerContentHeader, "#import <WebCore/$parentHeaderName.h>\n"); 655 $includedWebKitAvailabilityHeader = 1; 656 } 657 658 foreach my $parentProtocol (@protocolsToImplement) { 659 next if $parentProtocol =~ /^NS/; 660 $parentProtocol = GetClassHeaderName($parentProtocol); 661 push(@headerContentHeader, "#import <WebCore/$parentProtocol.h>\n"); 662 $includedWebKitAvailabilityHeader = 1; 663 } 664 665 # Special case needed for legacy support of DOMRange 666 if ($interfaceName eq "Range") { 667 push(@headerContentHeader, "#import <WebCore/DOMCore.h>\n"); 668 push(@headerContentHeader, "#import <WebCore/DOMDocument.h>\n"); 669 push(@headerContentHeader, "#import <WebCore/DOMRangeException.h>\n"); 670 $includedWebKitAvailabilityHeader = 1; 671 } 672 673 push(@headerContentHeader, "#import <JavaScriptCore/WebKitAvailability.h>\n") unless $includedWebKitAvailabilityHeader; 674 675 my $interfaceAvailabilityVersionCheck = "#if WEBKIT_VERSION_MAX_ALLOWED >= $interfaceAvailabilityVersion\n\n"; 676 677 push(@headerContentHeader, "\n"); 678 push(@headerContentHeader, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion; 679 680 # - Add constants. 681 if ($numConstants > 0) { 682 my @headerConstants = (); 683 684 # FIXME: we need a way to include multiple enums. 685 foreach my $constant (@{$dataNode->constants}) { 686 my $constantName = $constant->name; 687 my $constantValue = $constant->value; 688 689 my $output = " DOM_" . $constantName . " = " . $constantValue; 690 push(@headerConstants, $output); 691 } 692 693 my $combinedConstants = join(",\n", @headerConstants); 694 695 # FIXME: the formatting of the enums should line up the equal signs. 696 # FIXME: enums are unconditionally placed in the public header. 697 push(@headerContent, "enum {\n"); 698 push(@headerContent, $combinedConstants); 699 push(@headerContent, "\n};\n\n"); 700 } 701 702 # - Begin @interface or @protocol 703 my $interfaceDeclaration = ($isProtocol ? "\@protocol $className" : "\@interface $className : $parentName"); 704 $interfaceDeclaration .= " <" . join(", ", @protocolsToImplement) . ">" if @protocolsToImplement > 0; 705 $interfaceDeclaration .= "\n"; 706 707 push(@headerContent, $interfaceDeclaration); 708 709 my @headerAttributes = (); 710 my @privateHeaderAttributes = (); 711 712 # - Add attribute getters/setters. 713 if ($numAttributes > 0) { 714 foreach my $attribute (@{$dataNode->attributes}) { 715 my $attributeName = $attribute->signature->name; 716 717 if ($attributeName eq "id" or $attributeName eq "hash") { 718 # Special case attributes id and hash to be idName and hashName to avoid ObjC naming conflict. 719 $attributeName .= "Name"; 720 } elsif ($attributeName eq "frame") { 721 # Special case attribute frame to be frameBorders. 722 $attributeName .= "Borders"; 723 } 724 725 my $attributeType = GetObjCType($attribute->signature->type); 726 my $attributeIsReadonly = ($attribute->type =~ /^readonly/); 727 728 my $property = "\@property" . GetPropertyAttributes($attribute->signature->type, $attributeIsReadonly); 729 # Some SVGFE*Element.idl use 'operator' as attribute name, rewrite as '_operator' to avoid clashes with C/C++ 730 $attributeName =~ s/operator/_operator/ if ($attributeName =~ /operator/); 731 $property .= " " . $attributeType . ($attributeType =~ /\*$/ ? "" : " ") . $attributeName; 732 733 my $publicInterfaceKey = $property . ";"; 734 735 my $availabilityMacro = ""; 736 if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) { 737 $availabilityMacro = $publicInterfaces{$publicInterfaceKey}; 738 } 739 740 $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if length $availabilityMacro and $buildingForTigerOrEarlier; 741 742 my $declarationSuffix = ";\n"; 743 $declarationSuffix = " $availabilityMacro;\n" if length $availabilityMacro; 744 745 my $public = (defined $publicInterfaces{$publicInterfaceKey} or $newPublicClass); 746 delete $publicInterfaces{$publicInterfaceKey}; 747 748 AddForwardDeclarationsForType($attribute->signature->type, $public); 749 750 my $setterName = "set" . ucfirst($attributeName) . ":"; 751 752 my $conflict = $conflictMethod{$attributeName}; 753 if ($conflict) { 754 warn "$className conflicts with $conflict method $attributeName\n"; 755 $fatalError = 1; 756 } 757 758 $conflict = $conflictMethod{$setterName}; 759 if ($conflict) { 760 warn "$className conflicts with $conflict method $setterName\n"; 761 $fatalError = 1; 762 } 763 764 if ($buildingForLeopardOrLater) { 765 $property .= $declarationSuffix; 766 push(@headerAttributes, $property) if $public; 767 push(@privateHeaderAttributes, $property) unless $public; 768 } else { 769 # - GETTER 770 my $getter = "- (" . $attributeType . ")" . $attributeName . $declarationSuffix; 771 push(@headerAttributes, $getter) if $public; 772 push(@privateHeaderAttributes, $getter) unless $public; 773 774 # - SETTER 775 if (!$attributeIsReadonly) { 776 my $setter = "- (void)$setterName(" . $attributeType . ")new" . ucfirst($attributeName) . $declarationSuffix; 777 push(@headerAttributes, $setter) if $public; 778 push(@privateHeaderAttributes, $setter) unless $public; 779 } 780 } 781 } 782 783 push(@headerContent, @headerAttributes) if @headerAttributes > 0; 784 } 785 786 my @headerFunctions = (); 787 my @privateHeaderFunctions = (); 788 my @deprecatedHeaderFunctions = (); 789 790 # - Add functions. 791 if ($numFunctions > 0) { 792 foreach my $function (@{$dataNode->functions}) { 793 my $functionName = $function->signature->name; 794 795 my $returnType = GetObjCType($function->signature->type); 796 my $needsDeprecatedVersion = (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"}); 797 my $numberOfParameters = @{$function->parameters}; 798 my %typesToForwardDeclare = ($function->signature->type => 1); 799 800 my $parameterIndex = 0; 801 my $functionSig = "- ($returnType)$functionName"; 802 my $methodName = $functionName; 803 foreach my $param (@{$function->parameters}) { 804 my $paramName = $param->name; 805 my $paramType = GetObjCType($param->type); 806 807 $typesToForwardDeclare{$param->type} = 1; 808 809 if ($parameterIndex >= 1) { 810 my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"}; 811 $paramPrefix = $paramName unless defined($paramPrefix); 812 $functionSig .= " $paramPrefix"; 813 $methodName .= $paramPrefix; 814 } 815 816 $functionSig .= ":($paramType)$paramName"; 817 $methodName .= ":"; 818 819 $parameterIndex++; 820 } 821 822 my $publicInterfaceKey = $functionSig . ";"; 823 824 my $conflict = $conflictMethod{$methodName}; 825 if ($conflict) { 826 warn "$className conflicts with $conflict method $methodName\n"; 827 $fatalError = 1; 828 } 829 830 if ($isProtocol && !$newPublicClass && !defined $publicInterfaces{$publicInterfaceKey}) { 831 warn "Protocol method $publicInterfaceKey is not in PublicDOMInterfaces.h. Protocols require all methods to be public"; 832 $fatalError = 1; 833 } 834 835 my $availabilityMacro = ""; 836 if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) { 837 $availabilityMacro = $publicInterfaces{$publicInterfaceKey}; 838 } 839 840 $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if length $availabilityMacro and $buildingForTigerOrEarlier; 841 842 my $functionDeclaration = $functionSig; 843 $functionDeclaration .= " " . $availabilityMacro if length $availabilityMacro; 844 $functionDeclaration .= ";\n"; 845 846 my $public = (defined $publicInterfaces{$publicInterfaceKey} or $newPublicClass); 847 delete $publicInterfaces{$publicInterfaceKey}; 848 849 foreach my $type (keys %typesToForwardDeclare) { 850 # add any forward declarations to the public header if a deprecated version will be generated 851 AddForwardDeclarationsForType($type, 1) if $needsDeprecatedVersion; 852 AddForwardDeclarationsForType($type, $public) unless $public and $needsDeprecatedVersion; 853 } 854 855 push(@headerFunctions, $functionDeclaration) if $public; 856 push(@privateHeaderFunctions, $functionDeclaration) unless $public; 857 858 # generate the old style method names with un-named parameters, these methods are deprecated 859 if ($needsDeprecatedVersion) { 860 my $deprecatedFunctionSig = $functionSig; 861 $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names 862 863 $publicInterfaceKey = $deprecatedFunctionSig . ";"; 864 865 my $availabilityMacro = "AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0"; 866 if (defined $publicInterfaces{$publicInterfaceKey} and length $publicInterfaces{$publicInterfaceKey}) { 867 $availabilityMacro = $publicInterfaces{$publicInterfaceKey}; 868 } 869 870 $availabilityMacro = "WEBKIT_OBJC_METHOD_ANNOTATION($availabilityMacro)" if $buildingForTigerOrEarlier; 871 872 $functionDeclaration = "$deprecatedFunctionSig $availabilityMacro;\n"; 873 874 push(@deprecatedHeaderFunctions, $functionDeclaration); 875 876 unless (defined $publicInterfaces{$publicInterfaceKey}) { 877 warn "Deprecated method $publicInterfaceKey is not in PublicDOMInterfaces.h. All deprecated methods need to be public, or should have the OldStyleObjC IDL attribute removed"; 878 $fatalError = 1; 879 } 880 881 delete $publicInterfaces{$publicInterfaceKey}; 882 } 883 } 884 885 if (@headerFunctions > 0) { 886 push(@headerContent, "\n") if $buildingForLeopardOrLater and @headerAttributes > 0; 887 push(@headerContent, @headerFunctions); 888 } 889 } 890 891 if (@deprecatedHeaderFunctions > 0 && $isProtocol) { 892 push(@headerContent, @deprecatedHeaderFunctions); 893 } 894 895 # - End @interface or @protocol 896 push(@headerContent, "\@end\n"); 897 898 if (@deprecatedHeaderFunctions > 0 && !$isProtocol) { 899 # - Deprecated category @interface 900 push(@headerContent, "\n\@interface $className (" . $className . "Deprecated)\n"); 901 push(@headerContent, @deprecatedHeaderFunctions); 902 push(@headerContent, "\@end\n"); 903 } 904 905 push(@headerContent, "\n#endif\n") if length $interfaceAvailabilityVersion; 906 907 my %alwaysGenerateForNoSVGBuild = map { $_ => 1 } qw(DOMHTMLEmbedElement DOMHTMLObjectElement); 908 909 if (@privateHeaderAttributes > 0 or @privateHeaderFunctions > 0 or exists $alwaysGenerateForNoSVGBuild{$className}) { 910 # - Private category @interface 911 @privateHeaderContentHeader = split("\r", $headerLicenseTemplate); 912 push(@privateHeaderContentHeader, "\n"); 913 914 my $classHeaderName = GetClassHeaderName($className); 915 push(@privateHeaderContentHeader, "#import <WebCore/$classHeaderName.h>\n\n"); 916 push(@privateHeaderContentHeader, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion; 917 918 @privateHeaderContent = (); 919 push(@privateHeaderContent, "\@interface $className (" . $className . "Private)\n"); 920 push(@privateHeaderContent, @privateHeaderAttributes) if @privateHeaderAttributes > 0; 921 push(@privateHeaderContent, "\n") if $buildingForLeopardOrLater and @privateHeaderAttributes > 0 and @privateHeaderFunctions > 0; 922 push(@privateHeaderContent, @privateHeaderFunctions) if @privateHeaderFunctions > 0; 923 push(@privateHeaderContent, "\@end\n"); 924 925 push(@privateHeaderContent, "\n#endif\n") if length $interfaceAvailabilityVersion; 926 } 927 928 unless ($isProtocol) { 929 # Generate internal interfaces 930 my $podType = $dataNode->extendedAttributes->{"PODType"}; 931 932 # Generate interface definitions. 933 @internalHeaderContent = split("\r", $implementationLicenseTemplate); 934 935 push(@internalHeaderContent, "\n#import <WebCore/$className.h>\n\n"); 936 push(@internalHeaderContent, $interfaceAvailabilityVersionCheck) if length $interfaceAvailabilityVersion; 937 938 if ($interfaceName eq "Node") { 939 push(@internalHeaderContent, "\@protocol DOMEventTarget;\n\n"); 940 } 941 942 my $startedNamespace = 0; 943 944 my $implClassName = GetImplClassName($interfaceName); 945 946 if ($codeGenerator->IsSVGAnimatedType($interfaceName)) { 947 push(@internalHeaderContent, "#import <WebCore/SVGAnimatedTemplate.h>\n\n"); 948 } else { 949 push(@internalHeaderContent, "namespace WebCore {\n"); 950 $startedNamespace = 1; 951 if ($podType and $podType ne "float") { 952 push(@internalHeaderContent, " class $podType;\n"); 953 } elsif ($interfaceName eq "Node") { 954 push(@internalHeaderContent, " class EventTarget;\n class Node;\n"); 955 } else { 956 push(@internalHeaderContent, " class $implClassName;\n"); 957 } 958 push(@internalHeaderContent, "}\n\n"); 959 } 960 961 if ($podType) { 962 if ($podType eq "float") { 963 push(@internalHeaderContent, "float core($className *);\n"); 964 } else { 965 push(@internalHeaderContent, "WebCore::$podType core($className *);\n"); 966 } 967 } else { 968 push(@internalHeaderContent, "WebCore::$implClassName* core($className *);\n"); 969 } 970 971 if ($podType) { 972 if ($podType eq "float") { 973 push(@internalHeaderContent, "$className *kit($podType);\n"); 974 } else { 975 push(@internalHeaderContent, "$className *kit(WebCore::$podType);\n"); 976 } 977 } else { 978 push(@internalHeaderContent, "$className *kit(WebCore::$implClassName*);\n"); 979 } 980 981 if ($dataNode->extendedAttributes->{Polymorphic}) { 982 push(@internalHeaderContent, "Class kitClass(WebCore::$implClassName*);\n"); 983 } 984 985 if ($interfaceName eq "Node") { 986 push(@internalHeaderContent, "id <DOMEventTarget> kit(WebCore::EventTarget*);\n"); 987 } 988 989 push(@internalHeaderContent, "\n#endif\n") if length $interfaceAvailabilityVersion; 990 } 991 } 992 993 sub GenerateImplementation 994 { 995 my $object = shift; 996 my $dataNode = shift; 997 998 my @ancestorInterfaceNames = (); 999 1000 if (@{$dataNode->parents} > 1) { 1001 $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames); 1002 } 1003 1004 my $interfaceName = $dataNode->name; 1005 my $className = GetClassName($interfaceName); 1006 my $implClassName = GetImplClassName($interfaceName); 1007 my $parentImplClassName = GetParentImplClassName($dataNode); 1008 my $implClassNameWithNamespace = "WebCore::" . $implClassName; 1009 my $baseClass = GetBaseClass($parentImplClassName); 1010 my $classHeaderName = GetClassHeaderName($className); 1011 my $conditional = $dataNode->extendedAttributes->{"Conditional"}; 1012 1013 my $numAttributes = @{$dataNode->attributes}; 1014 my $numFunctions = @{$dataNode->functions}; 1015 1016 my $podType = $dataNode->extendedAttributes->{"PODType"}; 1017 my $podTypeWithNamespace; 1018 1019 if ($podType) { 1020 $podTypeWithNamespace = ($podType eq "float") ? "$podType" : "WebCore::$podType"; 1021 } 1022 1023 # - Add default header template. 1024 @implContentHeader = split("\r", $implementationLicenseTemplate); 1025 1026 # - INCLUDES - 1027 push(@implContentHeader, "\n#import \"config.h\"\n"); 1028 1029 my $conditionalString; 1030 if ($conditional) { 1031 $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 1032 push(@implContentHeader, "\n#if ${conditionalString}\n\n"); 1033 } 1034 1035 push(@implContentHeader, "#import \"DOMInternal.h\"\n\n"); 1036 push(@implContentHeader, "#import \"$classHeaderName.h\"\n\n"); 1037 1038 $implIncludes{"ExceptionHandlers.h"} = 1; 1039 $implIncludes{"ThreadCheck.h"} = 1; 1040 $implIncludes{"WebScriptObjectPrivate.h"} = 1; 1041 $implIncludes{$classHeaderName . "Internal.h"} = 1; 1042 1043 # FIXME: These includes are only needed when the class is a subclass of one of these polymorphic classes. 1044 $implIncludes{"DOMBlobInternal.h"} = 1; 1045 $implIncludes{"DOMCSSRuleInternal.h"} = 1; 1046 $implIncludes{"DOMCSSValueInternal.h"} = 1; 1047 $implIncludes{"DOMEventInternal.h"} = 1; 1048 $implIncludes{"DOMNodeInternal.h"} = 1; 1049 $implIncludes{"DOMStyleSheetInternal.h"} = 1; 1050 1051 $implIncludes{"DOMSVGPathSegInternal.h"} = 1 if $interfaceName =~ /^SVGPathSeg.+/; 1052 1053 if ($codeGenerator->IsSVGAnimatedType($interfaceName)) { 1054 $implIncludes{"SVGAnimatedTemplate.h"} = 1; 1055 } elsif ($interfaceName =~ /(\w+)(Abs|Rel)$/) { 1056 $implIncludes{"$1.h"} = 1; 1057 } else { 1058 if (!$podType) { 1059 $implIncludes{"$implClassName.h"} = 1; 1060 } else { 1061 $implIncludes{"$podType.h"} = 1 unless $podType eq "float"; 1062 } 1063 } 1064 1065 @implContent = (); 1066 1067 push(@implContent, "#import <wtf/GetPtr.h>\n\n"); 1068 1069 # add implementation accessor 1070 if ($podType) { 1071 push(@implContent, "#define IMPL reinterpret_cast<$podTypeWithNamespace*>(_internal)\n\n"); 1072 } elsif ($parentImplClassName eq "Object") { 1073 push(@implContent, "#define IMPL reinterpret_cast<$implClassNameWithNamespace*>(_internal)\n\n"); 1074 } else { 1075 my $baseClassWithNamespace = "WebCore::$baseClass"; 1076 push(@implContent, "#define IMPL static_cast<$implClassNameWithNamespace*>(reinterpret_cast<$baseClassWithNamespace*>(_internal))\n\n"); 1077 } 1078 1079 # START implementation 1080 push(@implContent, "\@implementation $className\n\n"); 1081 1082 # Only generate 'dealloc' and 'finalize' methods for direct subclasses of DOMObject. 1083 if ($parentImplClassName eq "Object") { 1084 $implIncludes{"WebCoreObjCExtras.h"} = 1; 1085 push(@implContent, "- (void)dealloc\n"); 1086 push(@implContent, "{\n"); 1087 push(@implContent, " if (WebCoreObjCScheduleDeallocateOnMainThread([$className class], self))\n"); 1088 push(@implContent, " return;\n"); 1089 push(@implContent, "\n"); 1090 if ($interfaceName eq "NodeIterator") { 1091 push(@implContent, " if (_internal) {\n"); 1092 push(@implContent, " [self detach];\n"); 1093 push(@implContent, " IMPL->deref();\n"); 1094 push(@implContent, " };\n"); 1095 } elsif ($podType) { 1096 push(@implContent, " delete IMPL;\n"); 1097 } else { 1098 push(@implContent, " if (_internal)\n"); 1099 push(@implContent, " IMPL->deref();\n"); 1100 } 1101 push(@implContent, " [super dealloc];\n"); 1102 push(@implContent, "}\n\n"); 1103 1104 push(@implContent, "- (void)finalize\n"); 1105 push(@implContent, "{\n"); 1106 if ($interfaceName eq "NodeIterator") { 1107 push(@implContent, " if (_internal) {\n"); 1108 push(@implContent, " [self detach];\n"); 1109 push(@implContent, " IMPL->deref();\n"); 1110 push(@implContent, " };\n"); 1111 } elsif ($podType) { 1112 push(@implContent, " delete IMPL;\n"); 1113 } else { 1114 push(@implContent, " if (_internal)\n"); 1115 push(@implContent, " IMPL->deref();\n"); 1116 } 1117 push(@implContent, " [super finalize];\n"); 1118 push(@implContent, "}\n\n"); 1119 1120 } 1121 1122 %attributeNames = (); 1123 1124 # - Attributes 1125 if ($numAttributes > 0) { 1126 foreach my $attribute (@{$dataNode->attributes}) { 1127 AddIncludesForType($attribute->signature->type); 1128 1129 my $idlType = $codeGenerator->StripModule($attribute->signature->type); 1130 1131 my $attributeName = $attribute->signature->name; 1132 my $attributeType = GetObjCType($attribute->signature->type); 1133 my $attributeIsReadonly = ($attribute->type =~ /^readonly/); 1134 my $attributeClassName = GetClassName($attribute->signature->type); 1135 1136 my $attributeInterfaceName = $attributeName; 1137 if ($attributeName eq "id" or $attributeName eq "hash") { 1138 # Special case attributes id and hash to be idName and hashName to avoid ObjC naming conflict. 1139 $attributeInterfaceName .= "Name"; 1140 } elsif ($attributeName eq "frame") { 1141 # Special case attribute frame to be frameBorders. 1142 $attributeInterfaceName .= "Borders"; 1143 } elsif ($attributeName eq "ownerDocument") { 1144 # FIXME: for now special case attribute ownerDocument to call document, this is incorrect 1145 # legacy behavior. (see http://bugs.webkit.org/show_bug.cgi?id=10889) 1146 $attributeName = "document"; 1147 } elsif ($codeGenerator->IsSVGAnimatedType($idlType)) { 1148 # Special case for animated types. 1149 $attributeName .= "Animated"; 1150 } 1151 1152 $attributeNames{$attributeInterfaceName} = 1; 1153 1154 # - GETTER 1155 my $getterSig = "- ($attributeType)$attributeInterfaceName\n"; 1156 1157 # Some SVGFE*Element.idl use 'operator' as attribute name, rewrite as '_operator' to avoid clashes with C/C++ 1158 $attributeName =~ s/operatorAnimated/_operatorAnimated/ if ($attributeName =~ /operatorAnimated/); 1159 $getterSig =~ s/operator/_operator/ if ($getterSig =~ /operator/); 1160 1161 my $hasGetterException = @{$attribute->getterExceptions}; 1162 my $getterContentHead; 1163 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 1164 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; 1165 if ($reflect || $reflectURL) { 1166 my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); 1167 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 1168 $implIncludes{"${namespace}.h"} = 1; 1169 my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute"; 1170 $getterContentHead = "IMPL->${getAttributeFunctionName}(WebCore::${namespace}::${contentAttributeName}Attr"; 1171 } else { 1172 $getterContentHead = "IMPL->" . $codeGenerator->WK_lcfirst($attributeName) . "("; 1173 } 1174 my $getterContentTail = ")"; 1175 1176 # Special case for DOMSVGNumber 1177 if ($podType and $podType eq "float") { 1178 $getterContentHead = "*IMPL"; 1179 $getterContentTail = ""; 1180 } 1181 1182 # TODO: Handle special case for DOMSVGLength 1183 if ($podType and $podType eq "SVGLength" and $attributeName eq "value") { 1184 $getterContentHead = "IMPL->value(0 /* FIXME */"; 1185 } 1186 1187 my $attributeTypeSansPtr = $attributeType; 1188 $attributeTypeSansPtr =~ s/ \*$//; # Remove trailing " *" from pointer types. 1189 1190 # special case for EventTarget protocol 1191 $attributeTypeSansPtr = "DOMNode" if $idlType eq "EventTarget"; 1192 1193 # Special cases 1194 my @customGetterContent = (); 1195 if ($attributeTypeSansPtr eq "DOMImplementation") { 1196 # FIXME: We have to special case DOMImplementation until DOMImplementationFront is removed 1197 $getterContentHead = "kit(implementationFront(IMPL"; 1198 $getterContentTail .= ")"; 1199 } elsif ($attributeName =~ /(\w+)DisplayString$/) { 1200 my $attributeToDisplay = $1; 1201 $getterContentHead = "WebCore::displayString(IMPL->$attributeToDisplay(), core(self)"; 1202 $implIncludes{"HitTestResult.h"} = 1; 1203 } elsif ($attributeName =~ /^absolute(\w+)URL$/) { 1204 my $typeOfURL = $1; 1205 $getterContentHead = "[self _getURLAttribute:"; 1206 if ($typeOfURL eq "Link") { 1207 $getterContentTail = "\@\"href\"]"; 1208 } elsif ($typeOfURL eq "Image") { 1209 if ($interfaceName eq "HTMLObjectElement") { 1210 $getterContentTail = "\@\"data\"]"; 1211 } else { 1212 $getterContentTail = "\@\"src\"]"; 1213 } 1214 unless ($interfaceName eq "HTMLImageElement") { 1215 push(@customGetterContent, " if (!IMPL->renderer() || !IMPL->renderer()->isImage())\n"); 1216 push(@customGetterContent, " return nil;\n"); 1217 $implIncludes{"RenderObject.h"} = 1; 1218 } 1219 } 1220 $implIncludes{"DOMPrivate.h"} = 1; 1221 } elsif ($attribute->signature->extendedAttributes->{"ConvertToString"}) { 1222 $getterContentHead = "WebCore::String::number(" . $getterContentHead; 1223 $getterContentTail .= ")"; 1224 } elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { 1225 $getterContentTail .= ".toInt()"; 1226 } elsif ($codeGenerator->IsPodType($idlType) or $idlType eq "Date") { 1227 $getterContentHead = "kit($getterContentHead"; 1228 $getterContentTail .= ")"; 1229 } elsif (IsProtocolType($idlType) and $idlType ne "EventTarget") { 1230 $getterContentHead = "kit($getterContentHead"; 1231 $getterContentTail .= ")"; 1232 } elsif ($idlType eq "Color") { 1233 $getterContentHead = "WebCore::nsColor($getterContentHead"; 1234 $getterContentTail .= ")"; 1235 } elsif ($attribute->signature->type eq "SerializedScriptValue") { 1236 $getterContentHead = "$getterContentHead"; 1237 $getterContentTail .= "->toString()"; 1238 } elsif (ConversionNeeded($attribute->signature->type)) { 1239 $getterContentHead = "kit(WTF::getPtr($getterContentHead"; 1240 $getterContentTail .= "))"; 1241 } 1242 1243 my $getterContent; 1244 if ($hasGetterException) { 1245 $getterContent = $getterContentHead . "ec" . $getterContentTail; 1246 } else { 1247 $getterContent = $getterContentHead . $getterContentTail; 1248 } 1249 1250 push(@implContent, $getterSig); 1251 push(@implContent, "{\n"); 1252 push(@implContent, @customGetterContent); 1253 if ($hasGetterException) { 1254 # Differentiated between when the return type is a pointer and 1255 # not for white space issue (ie. Foo *result vs. int result). 1256 if ($attributeType =~ /\*$/) { 1257 $getterContent = $attributeType . "result = " . $getterContent; 1258 } else { 1259 $getterContent = $attributeType . " result = " . $getterContent; 1260 } 1261 1262 push(@implContent, " $exceptionInit\n"); 1263 push(@implContent, " $getterContent;\n"); 1264 push(@implContent, " $exceptionRaiseOnError\n"); 1265 push(@implContent, " return result;\n"); 1266 } else { 1267 push(@implContent, " return $getterContent;\n"); 1268 } 1269 push(@implContent, "}\n\n"); 1270 1271 # - SETTER 1272 if (!$attributeIsReadonly) { 1273 # Exception handling 1274 my $hasSetterException = @{$attribute->setterExceptions}; 1275 1276 my $coreSetterName = "set" . $codeGenerator->WK_ucfirst($attributeName); 1277 my $setterName = "set" . ucfirst($attributeInterfaceName); 1278 my $argName = "new" . ucfirst($attributeInterfaceName); 1279 my $arg = GetObjCTypeGetter($argName, $idlType); 1280 1281 # The definition of ConvertFromString and ConvertToString is flipped for the setter 1282 if ($attribute->signature->extendedAttributes->{"ConvertFromString"}) { 1283 $arg = "WebCore::String::number($arg)"; 1284 } elsif ($attribute->signature->extendedAttributes->{"ConvertToString"}) { 1285 $arg = "WebCore::String($arg).toInt()"; 1286 } 1287 1288 my $setterSig = "- (void)$setterName:($attributeType)$argName\n"; 1289 1290 push(@implContent, $setterSig); 1291 push(@implContent, "{\n"); 1292 1293 unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) { 1294 push(@implContent, " ASSERT($argName);\n\n"); 1295 } 1296 1297 if ($idlType eq "Date") { 1298 $arg = "core(" . $arg . ")"; 1299 } 1300 1301 if ($podType) { 1302 # Special case for DOMSVGNumber 1303 if ($podType eq "float") { 1304 push(@implContent, " *IMPL = $arg;\n"); 1305 } else { 1306 push(@implContent, " IMPL->$coreSetterName($arg);\n"); 1307 } 1308 } else { 1309 my $reflect = $attribute->signature->extendedAttributes->{"Reflect"}; 1310 my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"}; 1311 push(@implContent, " $exceptionInit\n") if $hasSetterException; 1312 my $ec = $hasSetterException ? ", ec" : ""; 1313 if ($reflect || $reflectURL) { 1314 my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $attributeName : ($reflect || $reflectURL); 1315 my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName); 1316 $implIncludes{"${namespace}.h"} = 1; 1317 push(@implContent, " IMPL->setAttribute(WebCore::${namespace}::${contentAttributeName}Attr, $arg$ec);\n"); 1318 } else { 1319 push(@implContent, " IMPL->$coreSetterName($arg$ec);\n"); 1320 } 1321 push(@implContent, " $exceptionRaiseOnError\n") if $hasSetterException; 1322 } 1323 1324 push(@implContent, "}\n\n"); 1325 } 1326 } 1327 } 1328 1329 # - Functions 1330 if ($numFunctions > 0) { 1331 foreach my $function (@{$dataNode->functions}) { 1332 AddIncludesForType($function->signature->type); 1333 1334 my $functionName = $function->signature->name; 1335 my $returnType = GetObjCType($function->signature->type); 1336 my $hasParameters = @{$function->parameters}; 1337 my $raisesExceptions = @{$function->raisesExceptions}; 1338 1339 my @parameterNames = (); 1340 my @needsAssert = (); 1341 my %needsCustom = (); 1342 1343 my $parameterIndex = 0; 1344 my $functionSig = "- ($returnType)$functionName"; 1345 foreach my $param (@{$function->parameters}) { 1346 my $paramName = $param->name; 1347 my $paramType = GetObjCType($param->type); 1348 1349 # make a new parameter name if the original conflicts with a property name 1350 $paramName = "in" . ucfirst($paramName) if $attributeNames{$paramName}; 1351 1352 AddIncludesForType($param->type); 1353 1354 my $idlType = $codeGenerator->StripModule($param->type); 1355 my $implGetter = GetObjCTypeGetter($paramName, $idlType); 1356 1357 push(@parameterNames, $implGetter); 1358 $needsCustom{"XPathNSResolver"} = $paramName if $idlType eq "XPathNSResolver"; 1359 $needsCustom{"NodeFilter"} = $paramName if $idlType eq "NodeFilter"; 1360 $needsCustom{"EventListener"} = $paramName if $idlType eq "EventListener"; 1361 $needsCustom{"EventTarget"} = $paramName if $idlType eq "EventTarget"; 1362 $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"}; 1363 1364 unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) { 1365 push(@needsAssert, " ASSERT($paramName);\n"); 1366 } 1367 1368 if ($parameterIndex >= 1) { 1369 my $paramPrefix = $param->extendedAttributes->{"ObjCPrefix"}; 1370 $paramPrefix = $param->name unless defined($paramPrefix); 1371 $functionSig .= " $paramPrefix"; 1372 } 1373 1374 $functionSig .= ":($paramType)$paramName"; 1375 1376 $parameterIndex++; 1377 } 1378 1379 my @functionContent = (); 1380 my $caller = "IMPL"; 1381 1382 # special case the XPathNSResolver 1383 if (defined $needsCustom{"XPathNSResolver"}) { 1384 my $paramName = $needsCustom{"XPathNSResolver"}; 1385 push(@functionContent, " WebCore::XPathNSResolver* nativeResolver = 0;\n"); 1386 push(@functionContent, " RefPtr<WebCore::XPathNSResolver> customResolver;\n"); 1387 push(@functionContent, " if ($paramName) {\n"); 1388 push(@functionContent, " if ([$paramName isMemberOfClass:[DOMNativeXPathNSResolver class]])\n"); 1389 push(@functionContent, " nativeResolver = core(static_cast<DOMNativeXPathNSResolver *>($paramName));\n"); 1390 push(@functionContent, " else {\n"); 1391 push(@functionContent, " customResolver = WebCore::DOMCustomXPathNSResolver::create($paramName);\n"); 1392 push(@functionContent, " nativeResolver = WTF::getPtr(customResolver);\n"); 1393 push(@functionContent, " }\n"); 1394 push(@functionContent, " }\n"); 1395 } 1396 1397 # special case the EventTarget 1398 if (defined $needsCustom{"EventTarget"}) { 1399 my $paramName = $needsCustom{"EventTarget"}; 1400 push(@functionContent, " DOMNode* ${paramName}ObjC = $paramName;\n"); 1401 push(@functionContent, " WebCore::Node* ${paramName}Node = core(${paramName}ObjC);\n"); 1402 $implIncludes{"DOMNode.h"} = 1; 1403 $implIncludes{"Node.h"} = 1; 1404 } 1405 1406 if ($function->signature->extendedAttributes->{"UsesView"}) { 1407 push(@functionContent, " WebCore::DOMWindow* dv = $caller->defaultView();\n"); 1408 push(@functionContent, " if (!dv)\n"); 1409 push(@functionContent, " return nil;\n"); 1410 $implIncludes{"DOMWindow.h"} = 1; 1411 $caller = "dv"; 1412 } 1413 1414 # special case the EventListener 1415 if (defined $needsCustom{"EventListener"}) { 1416 my $paramName = $needsCustom{"EventListener"}; 1417 push(@functionContent, " RefPtr<WebCore::EventListener> nativeEventListener = WebCore::ObjCEventListener::wrap($paramName);\n"); 1418 } 1419 1420 # special case the NodeFilter 1421 if (defined $needsCustom{"NodeFilter"}) { 1422 my $paramName = $needsCustom{"NodeFilter"}; 1423 push(@functionContent, " RefPtr<WebCore::NodeFilter> nativeNodeFilter;\n"); 1424 push(@functionContent, " if ($paramName)\n"); 1425 push(@functionContent, " nativeNodeFilter = WebCore::NodeFilter::create(WebCore::ObjCNodeFilterCondition::create($paramName));\n"); 1426 } 1427 1428 # FIXME! We need [Custom] support for ObjC, to move these hacks into DOMSVGLength/MatrixCustom.mm 1429 my $svgMatrixRotateFromVector = ($podType and $podType eq "AffineTransform" and $functionName eq "rotateFromVector"); 1430 my $svgMatrixInverse = ($podType and $podType eq "AffineTransform" and $functionName eq "inverse"); 1431 my $svgLengthConvertToSpecifiedUnits = ($podType and $podType eq "SVGLength" and $functionName eq "convertToSpecifiedUnits"); 1432 1433 push(@parameterNames, "ec") if $raisesExceptions and !($svgMatrixRotateFromVector || $svgMatrixInverse); 1434 my $content = $caller . "->" . $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterNames) . ")"; 1435 1436 if ($svgMatrixRotateFromVector) { 1437 # Special case with rotateFromVector & SVGMatrix 1438 push(@functionContent, " $exceptionInit\n"); 1439 push(@functionContent, " if (x == 0.0 || y == 0.0)\n"); 1440 push(@functionContent, " ec = WebCore::SVGException::SVG_INVALID_VALUE_ERR;\n"); 1441 push(@functionContent, " $exceptionRaiseOnError\n"); 1442 push(@functionContent, " return kit($content);\n"); 1443 } elsif ($svgMatrixInverse) { 1444 # Special case with inverse & SVGMatrix 1445 push(@functionContent, " $exceptionInit\n"); 1446 push(@functionContent, " if (!$caller->isInvertible())\n"); 1447 push(@functionContent, " ec = WebCore::SVGException::SVG_MATRIX_NOT_INVERTABLE;\n"); 1448 push(@functionContent, " $exceptionRaiseOnError\n"); 1449 push(@functionContent, " return kit($content);\n"); 1450 } elsif ($svgLengthConvertToSpecifiedUnits) { 1451 push(@functionContent, " IMPL->convertToSpecifiedUnits(inUnitType, 0 /* FIXME */);\n"); 1452 } elsif ($returnType eq "void") { 1453 # Special case 'void' return type. 1454 if ($raisesExceptions) { 1455 push(@functionContent, " $exceptionInit\n"); 1456 push(@functionContent, " $content;\n"); 1457 push(@functionContent, " $exceptionRaiseOnError\n"); 1458 } else { 1459 push(@functionContent, " $content;\n"); 1460 } 1461 } elsif (defined $needsCustom{"NodeToReturn"}) { 1462 # Special case the insertBefore, replaceChild, removeChild 1463 # and appendChild functions from DOMNode 1464 my $toReturn = $needsCustom{"NodeToReturn"}; 1465 if ($raisesExceptions) { 1466 push(@functionContent, " $exceptionInit\n"); 1467 push(@functionContent, " if ($content)\n"); 1468 push(@functionContent, " return $toReturn;\n"); 1469 push(@functionContent, " $exceptionRaiseOnError\n"); 1470 push(@functionContent, " return nil;\n"); 1471 } else { 1472 push(@functionContent, " if ($content)\n"); 1473 push(@functionContent, " return $toReturn;\n"); 1474 push(@functionContent, " return nil;\n"); 1475 } 1476 } elsif ($returnType eq "SerializedScriptValue") { 1477 $content = "foo"; 1478 } else { 1479 if (ConversionNeeded($function->signature->type)) { 1480 if ($codeGenerator->IsPodType($function->signature->type)) { 1481 $content = "kit($content)"; 1482 } else { 1483 $content = "kit(WTF::getPtr($content))"; 1484 } 1485 } 1486 1487 if ($raisesExceptions) { 1488 # Differentiated between when the return type is a pointer and 1489 # not for white space issue (ie. Foo *result vs. int result). 1490 if ($returnType =~ /\*$/) { 1491 $content = $returnType . "result = " . $content; 1492 } else { 1493 $content = $returnType . " result = " . $content; 1494 } 1495 1496 push(@functionContent, " $exceptionInit\n"); 1497 push(@functionContent, " $content;\n"); 1498 push(@functionContent, " $exceptionRaiseOnError\n"); 1499 push(@functionContent, " return result;\n"); 1500 } else { 1501 push(@functionContent, " return $content;\n"); 1502 } 1503 } 1504 1505 push(@implContent, "$functionSig\n"); 1506 push(@implContent, "{\n"); 1507 push(@implContent, @functionContent); 1508 push(@implContent, "}\n\n"); 1509 1510 # generate the old style method names with un-named parameters, these methods are deprecated 1511 if (@{$function->parameters} > 1 and $function->signature->extendedAttributes->{"OldStyleObjC"}) { 1512 my $deprecatedFunctionSig = $functionSig; 1513 $deprecatedFunctionSig =~ s/\s\w+:/ :/g; # remove parameter names 1514 1515 push(@implContent, "$deprecatedFunctionSig\n"); 1516 push(@implContent, "{\n"); 1517 push(@implContent, @functionContent); 1518 push(@implContent, "}\n\n"); 1519 } 1520 1521 # Clear the hash 1522 %needsCustom = (); 1523 } 1524 } 1525 1526 # END implementation 1527 push(@implContent, "\@end\n"); 1528 1529 # Generate internal interfaces 1530 if ($podType) { 1531 my $prefixedPodType = $podType eq "float" ? $podType : "WebCore::$podType"; 1532 push(@implContent, "\n$prefixedPodType core($className *wrapper)\n"); 1533 push(@implContent, "{\n"); 1534 push(@implContent, " return wrapper ? *reinterpret_cast<$prefixedPodType*>(wrapper->_internal) : $prefixedPodType();\n"); 1535 push(@implContent, "}\n\n"); 1536 } else { 1537 push(@implContent, "\nWebCore::$implClassName* core($className *wrapper)\n"); 1538 push(@implContent, "{\n"); 1539 push(@implContent, " return wrapper ? reinterpret_cast<WebCore::$implClassName*>(wrapper->_internal) : 0;\n"); 1540 push(@implContent, "}\n\n"); 1541 } 1542 1543 if ($podType) { 1544 # FIXME: Implement caching. 1545 my $prefixedPodType = $podType eq "float" ? $podType : "WebCore::$podType"; 1546 push(@implContent, "$className *kit($prefixedPodType value)\n"); 1547 push(@implContent, "{\n"); 1548 push(@implContent, " $assertMainThread;\n"); 1549 push(@implContent, " $className *wrapper = [[$className alloc] _init];\n"); 1550 push(@implContent, " wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(new $prefixedPodType(value));\n"); 1551 push(@implContent, " return [wrapper autorelease];\n"); 1552 push(@implContent, "}\n"); 1553 } elsif ($parentImplClassName eq "Object") { 1554 push(@implContent, "$className *kit(WebCore::$implClassName* value)\n"); 1555 push(@implContent, "{\n"); 1556 push(@implContent, " $assertMainThread;\n"); 1557 push(@implContent, " if (!value)\n"); 1558 push(@implContent, " return nil;\n"); 1559 push(@implContent, " if ($className *wrapper = getDOMWrapper(value))\n"); 1560 push(@implContent, " return [[wrapper retain] autorelease];\n"); 1561 if ($dataNode->extendedAttributes->{Polymorphic}) { 1562 push(@implContent, " $className *wrapper = [[kitClass(value) alloc] _init];\n"); 1563 push(@implContent, " if (!wrapper)\n"); 1564 push(@implContent, " return nil;\n"); 1565 } else { 1566 push(@implContent, " $className *wrapper = [[$className alloc] _init];\n"); 1567 } 1568 push(@implContent, " wrapper->_internal = reinterpret_cast<DOMObjectInternal*>(value);\n"); 1569 push(@implContent, " value->ref();\n"); 1570 push(@implContent, " addDOMWrapper(wrapper, value);\n"); 1571 push(@implContent, " return [wrapper autorelease];\n"); 1572 push(@implContent, "}\n"); 1573 } else { 1574 push(@implContent, "$className *kit(WebCore::$implClassName* value)\n"); 1575 push(@implContent, "{\n"); 1576 push(@implContent, " $assertMainThread;\n"); 1577 push(@implContent, " return static_cast<$className*>(kit(static_cast<WebCore::$baseClass*>(value)));\n"); 1578 push(@implContent, "}\n"); 1579 } 1580 1581 # - End the ifdef conditional if necessary 1582 push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional; 1583 1584 # - Generate dependencies. 1585 if ($writeDependencies && @ancestorInterfaceNames) { 1586 push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n"); 1587 push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames); 1588 } 1589 } 1590 1591 # Internal helper 1592 sub WriteData 1593 { 1594 my $object = shift; 1595 my $name = shift; 1596 1597 # Open files for writing... 1598 my $headerFileName = "$outputDir/" . $name . ".h"; 1599 my $privateHeaderFileName = "$outputDir/" . $name . "Private.h"; 1600 my $implFileName = "$outputDir/" . $name . ".mm"; 1601 my $internalHeaderFileName = "$outputDir/" . $name . "Internal.h"; 1602 my $depsFileName = "$outputDir/" . $name . ".dep"; 1603 1604 # Remove old files. 1605 unlink($headerFileName); 1606 unlink($privateHeaderFileName); 1607 unlink($implFileName); 1608 unlink($internalHeaderFileName); 1609 unlink($depsFileName); 1610 1611 # Write public header. 1612 open(HEADER, ">$headerFileName") or die "Couldn't open file $headerFileName"; 1613 1614 print HEADER @headerContentHeader; 1615 print HEADER map { "\@class $_;\n" } sort keys(%headerForwardDeclarations); 1616 print HEADER map { "\@protocol $_;\n" } sort keys(%headerForwardDeclarationsForProtocols); 1617 1618 my $hasForwardDeclarations = keys(%headerForwardDeclarations) + keys(%headerForwardDeclarationsForProtocols); 1619 print HEADER "\n" if $hasForwardDeclarations; 1620 print HEADER @headerContent; 1621 1622 close(HEADER); 1623 1624 @headerContentHeader = (); 1625 @headerContent = (); 1626 %headerForwardDeclarations = (); 1627 %headerForwardDeclarationsForProtocols = (); 1628 1629 if (@privateHeaderContent > 0) { 1630 open(PRIVATE_HEADER, ">$privateHeaderFileName") or die "Couldn't open file $privateHeaderFileName"; 1631 1632 print PRIVATE_HEADER @privateHeaderContentHeader; 1633 print PRIVATE_HEADER map { "\@class $_;\n" } sort keys(%privateHeaderForwardDeclarations); 1634 print PRIVATE_HEADER map { "\@protocol $_;\n" } sort keys(%privateHeaderForwardDeclarationsForProtocols); 1635 1636 $hasForwardDeclarations = keys(%privateHeaderForwardDeclarations) + keys(%privateHeaderForwardDeclarationsForProtocols); 1637 print PRIVATE_HEADER "\n" if $hasForwardDeclarations; 1638 print PRIVATE_HEADER @privateHeaderContent; 1639 1640 close(PRIVATE_HEADER); 1641 1642 @privateHeaderContentHeader = (); 1643 @privateHeaderContent = (); 1644 %privateHeaderForwardDeclarations = (); 1645 %privateHeaderForwardDeclarationsForProtocols = (); 1646 } 1647 1648 # Write implementation file. 1649 unless ($noImpl) { 1650 open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName"; 1651 1652 print IMPL @implContentHeader; 1653 print IMPL map { "#import \"$_\"\n" } sort keys(%implIncludes); 1654 print IMPL @implContent; 1655 1656 close(IMPL); 1657 1658 @implContentHeader = (); 1659 @implContent = (); 1660 %implIncludes = (); 1661 } 1662 1663 if (@internalHeaderContent > 0) { 1664 open(INTERNAL_HEADER, ">$internalHeaderFileName") or die "Couldn't open file $internalHeaderFileName"; 1665 1666 print INTERNAL_HEADER @internalHeaderContent; 1667 1668 close(INTERNAL_HEADER); 1669 1670 @internalHeaderContent = (); 1671 } 1672 1673 # Write dependency file. 1674 if (@depsContent) { 1675 open(DEPS, ">$depsFileName") or die "Couldn't open file $depsFileName"; 1676 print DEPS @depsContent; 1677 close(DEPS); 1678 @depsContent = (); 1679 } 1680 } 1681 1682 1; 1683