PageRenderTime 50ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/platform/external/webkit/WebCore/bindings/scripts/CodeGeneratorObjC.pm

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