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