/src/3rdparty/webkit/Source/WebCore/bindings/scripts/CodeGeneratorCPP.pm

https://bitbucket.org/ultra_iter/qt-vtl · Perl · 961 lines · 701 code · 177 blank · 83 comment · 115 complexity · 7233b24f04b7ecb200e6ac6fda8a5e0e MD5 · raw file

  1. # Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
  2. # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
  3. # Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
  4. # Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
  5. # Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  6. # Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
  7. # Copyright (C) Research In Motion Limited 2010. All rights reserved.
  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 CodeGeneratorCPP;
  25. # Global Variables
  26. my $module = "";
  27. my $outputDir = "";
  28. my @headerContentHeader = ();
  29. my @headerContent = ();
  30. my %headerForwardDeclarations = ();
  31. my @implContentHeader = ();
  32. my @implContent = ();
  33. my %implIncludes = ();
  34. # Constants
  35. my $exceptionInit = "WebCore::ExceptionCode ec = 0;";
  36. my $exceptionRaiseOnError = "webDOMRaiseError(static_cast<WebDOMExceptionCode>(ec));";
  37. # Default License Templates
  38. my $headerLicenseTemplate = << "EOF";
  39. /*
  40. * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  41. * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
  42. * Copyright (C) 2006 Samuel Weinig <sam.weinig\@gmail.com>
  43. * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  44. *
  45. * This library is free software; you can redistribute it and/or
  46. * modify it under the terms of the GNU Library General Public
  47. * License as published by the Free Software Foundation; either
  48. * version 2 of the License, or (at your option) any later version.
  49. *
  50. * This library is distributed in the hope that it will be useful,
  51. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  52. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  53. * Library General Public License for more details.
  54. *
  55. * You should have received a copy of the GNU Library General Public License
  56. * along with this library; see the file COPYING.LIB. If not, write to
  57. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  58. * Boston, MA 02110-1301, USA.
  59. */
  60. EOF
  61. my $implementationLicenseTemplate = << "EOF";
  62. /*
  63. * This file is part of the WebKit open source project.
  64. * This file has been generated by generate-bindings.pl. DO NOT MODIFY!
  65. *
  66. * This library is free software; you can redistribute it and/or
  67. * modify it under the terms of the GNU Library General Public
  68. * License as published by the Free Software Foundation; either
  69. * version 2 of the License, or (at your option) any later version.
  70. *
  71. * This library is distributed in the hope that it will be useful,
  72. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  73. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  74. * Library General Public License for more details.
  75. *
  76. * You should have received a copy of the GNU Library General Public License
  77. * along with this library; see the file COPYING.LIB. If not, write to
  78. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  79. * Boston, MA 02110-1301, USA.
  80. */
  81. EOF
  82. # Default constructor
  83. sub new
  84. {
  85. my $object = shift;
  86. my $reference = { };
  87. $codeGenerator = shift;
  88. $outputDir = shift;
  89. shift; # $outputHeadersDir
  90. shift; # $useLayerOnTop
  91. shift; # $preprocessor
  92. shift; # $writeDependencies
  93. bless($reference, $object);
  94. return $reference;
  95. }
  96. sub finish
  97. {
  98. my $object = shift;
  99. }
  100. # Params: 'domClass' struct
  101. sub GenerateInterface
  102. {
  103. my $object = shift;
  104. my $dataNode = shift;
  105. my $defines = shift;
  106. my $name = $dataNode->name;
  107. my $className = GetClassName($name);
  108. my $parentClassName = "WebDOM" . GetParentImplClassName($dataNode);
  109. # Start actual generation.
  110. $object->GenerateHeader($dataNode);
  111. $object->GenerateImplementation($dataNode);
  112. # Write changes.
  113. $object->WriteData("WebDOM" . $name);
  114. }
  115. # Params: 'idlDocument' struct
  116. sub GenerateModule
  117. {
  118. my $object = shift;
  119. my $dataNode = shift;
  120. $module = $dataNode->module;
  121. }
  122. sub GetClassName
  123. {
  124. my $name = $codeGenerator->StripModule(shift);
  125. # special cases
  126. return "WebDOMString" if $codeGenerator->IsStringType($name) or $name eq "SerializedScriptValue";
  127. return "WebDOMObject" if $name eq "DOMObject";
  128. return "bool" if $name eq "boolean";
  129. return $name if $codeGenerator->IsPrimitiveType($name);
  130. return "WebDOMCustomVoidCallback" if $name eq "VoidCallback";
  131. return "WebDOM$name";
  132. }
  133. sub GetImplClassName
  134. {
  135. return $codeGenerator->StripModule(shift);
  136. }
  137. sub GetParentImplClassName
  138. {
  139. my $dataNode = shift;
  140. if (@{$dataNode->parents} eq 0) {
  141. return "EventTarget" if $dataNode->extendedAttributes->{"EventTarget"};
  142. return "Object";
  143. }
  144. return $codeGenerator->StripModule($dataNode->parents(0));
  145. }
  146. sub GetParent
  147. {
  148. my $dataNode = shift;
  149. my $numParents = @{$dataNode->parents};
  150. my $parent = "";
  151. if ($numParents eq 0) {
  152. $parent = "WebDOMObject";
  153. $parent = "WebDOMEventTarget" if $dataNode->extendedAttributes->{"EventTarget"};
  154. } elsif ($numParents eq 1) {
  155. my $parentName = $codeGenerator->StripModule($dataNode->parents(0));
  156. $parent = "WebDOM" . $parentName;
  157. } else {
  158. my @parents = @{$dataNode->parents};
  159. my $firstParent = $codeGenerator->StripModule(shift(@parents));
  160. $parent = "WebDOM" . $firstParent;
  161. }
  162. return $parent;
  163. }
  164. sub ShouldSkipTypeInImplementation
  165. {
  166. my $typeInfo = shift;
  167. return 1 if $typeInfo->signature->extendedAttributes->{"Custom"}
  168. and !$typeInfo->signature->extendedAttributes->{"NoCPPCustom"};
  169. return 1 if $typeInfo->signature->extendedAttributes->{"CustomArgumentHandling"}
  170. or $typeInfo->signature->extendedAttributes->{"CustomGetter"}
  171. or $typeInfo->signature->extendedAttributes->{"NeedsUserGestureCheck"}
  172. or $typeInfo->signature->extendedAttributes->{"CPPCustom"};
  173. # FIXME: We don't generate bindings for SVG related interfaces yet
  174. return 1 if $typeInfo->signature->name =~ /getSVGDocument/;
  175. return 1 if $typeInfo->signature->name =~ /Constructor/;
  176. return 0;
  177. }
  178. sub ShouldSkipTypeInHeader
  179. {
  180. my $typeInfo = shift;
  181. # FIXME: We currently ignore any attribute/function needing custom code
  182. return 1 if $typeInfo->signature->extendedAttributes->{"CustomArgumentHandling"}
  183. or $typeInfo->signature->extendedAttributes->{"CustomGetter"};
  184. # FIXME: We don't generate bindings for SVG related interfaces yet
  185. return 1 if $typeInfo->signature->name =~ /getSVGDocument/;
  186. return 1 if $typeInfo->signature->name =~ /Constructor/;
  187. return 0;
  188. }
  189. sub GetCPPType
  190. {
  191. my $type = shift;
  192. my $useConstReference = shift;
  193. my $name = GetClassName($type);
  194. return "int" if $type eq "long";
  195. return "unsigned" if $name eq "unsigned long";
  196. return "unsigned short" if $type eq "CompareHow";
  197. return "double" if $name eq "Date";
  198. if ($codeGenerator->IsStringType($type)) {
  199. if ($useConstReference) {
  200. return "const $name&";
  201. }
  202. return $name;
  203. }
  204. return $name if $codeGenerator->IsPrimitiveType($type) or $type eq "DOMTimeStamp";
  205. return "const $name&" if $useConstReference;
  206. return $name;
  207. }
  208. sub ConversionNeeded
  209. {
  210. my $type = $codeGenerator->StripModule(shift);
  211. return !$codeGenerator->IsNonPointerType($type) && !$codeGenerator->IsStringType($type);
  212. }
  213. sub GetCPPTypeGetter
  214. {
  215. my $argName = shift;
  216. my $type = $codeGenerator->StripModule(shift);
  217. return $argName if $codeGenerator->IsPrimitiveType($type) or $codeGenerator->IsStringType($type);
  218. return "static_cast<WebCore::Range::CompareHow>($argName)" if $type eq "CompareHow";
  219. return "WebCore::SerializedScriptValue::create(WTF::String($argName))" if $type eq "SerializedScriptValue";
  220. return "toWebCore($argName)";
  221. }
  222. sub AddForwardDeclarationsForType
  223. {
  224. my $type = $codeGenerator->StripModule(shift);
  225. my $public = shift;
  226. return if $codeGenerator->IsNonPointerType($type) or $codeGenerator->IsStringType($type);
  227. my $class = GetClassName($type);
  228. $headerForwardDeclarations{$class} = 1 if $public;
  229. }
  230. sub AddIncludesForType
  231. {
  232. my $type = $codeGenerator->StripModule(shift);
  233. return if $codeGenerator->IsNonPointerType($type);
  234. return if $type =~ /Constructor/;
  235. if ($codeGenerator->IsStringType($type)) {
  236. $implIncludes{"wtf/text/AtomicString.h"} = 1;
  237. $implIncludes{"KURL.h"} = 1;
  238. $implIncludes{"WebDOMString.h"} = 1;
  239. return;
  240. }
  241. if ($type eq "DOMObject") {
  242. $implIncludes{"WebDOMObject.h"} = 1;
  243. return;
  244. }
  245. if ($type eq "EventListener") {
  246. $implIncludes{"WebNativeEventListener.h"} = 1;
  247. return;
  248. }
  249. if ($type eq "SerializedScriptValue") {
  250. $implIncludes{"SerializedScriptValue.h"} = 1;
  251. return;
  252. }
  253. if ($type eq "VoidCallback") {
  254. $implIncludes{"WebDOMCustomVoidCallback.h"} = 1;
  255. return;
  256. }
  257. $implIncludes{"Node.h"} = 1 if $type eq "NodeList";
  258. $implIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration";
  259. # Default, include the same named file (the implementation) and the same name prefixed with "WebDOM".
  260. $implIncludes{"$type.h"} = 1 unless $type eq "DOMObject";
  261. $implIncludes{"WebDOM$type.h"} = 1;
  262. }
  263. sub GenerateConditionalStringFromAttributeValue
  264. {
  265. my $conditional = shift;
  266. if ($conditional =~ /&/) {
  267. return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
  268. } elsif ($conditional =~ /\|/) {
  269. return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
  270. } else {
  271. return "ENABLE(" . $conditional . ")";
  272. }
  273. }
  274. sub GenerateConditionalString
  275. {
  276. my $node = shift;
  277. my $conditional = $node->extendedAttributes->{"Conditional"};
  278. if ($conditional) {
  279. return GenerateConditionalStringFromAttributeValue($conditional);
  280. } else {
  281. return "";
  282. }
  283. }
  284. sub GenerateHeader
  285. {
  286. my $object = shift;
  287. my $dataNode = shift;
  288. my $interfaceName = $dataNode->name;
  289. my $className = GetClassName($interfaceName);
  290. my $implClassName = GetImplClassName($interfaceName);
  291. my $implClassNameWithNamespace = "WebCore::" . $implClassName;
  292. my $parentName = "";
  293. $parentName = GetParent($dataNode);
  294. my $numConstants = @{$dataNode->constants};
  295. my $numAttributes = @{$dataNode->attributes};
  296. my $numFunctions = @{$dataNode->functions};
  297. # - Add default header template
  298. @headerContentHeader = split("\r", $headerLicenseTemplate);
  299. push(@headerContentHeader, "\n#ifndef $className" . "_h");
  300. push(@headerContentHeader, "\n#define $className" . "_h\n\n");
  301. my $conditionalString = GenerateConditionalString($dataNode);
  302. push(@headerContentHeader, "#if ${conditionalString}\n\n") if $conditionalString;
  303. # - INCLUDES -
  304. my %headerIncludes = ();
  305. $headerIncludes{"WebDOMString.h"} = 1;
  306. $headerIncludes{"$parentName.h"} = 1;
  307. foreach my $include (sort keys(%headerIncludes)) {
  308. push(@headerContentHeader, "#include <$include>\n");
  309. }
  310. push(@headerContent, "class $className");
  311. push(@headerContent, " : public $parentName") if $parentName;
  312. push(@headerContent, " {\n");
  313. push(@headerContent, "public:\n");
  314. # Constructor
  315. push(@headerContent, " $className();\n");
  316. push(@headerContent, " explicit $className($implClassNameWithNamespace*);\n");
  317. # Copy constructor and assignment operator on classes which have the d-ptr
  318. if ($parentName eq "WebDOMObject") {
  319. push(@headerContent, " $className(const $className&);\n");
  320. push(@headerContent, " ${className}& operator=(const $className&);\n");
  321. }
  322. # Destructor
  323. if ($parentName eq "WebDOMObject") {
  324. push(@headerContent, " virtual ~$className();\n");
  325. } else {
  326. push(@headerContent, " virtual ~$className() { }\n");
  327. }
  328. push(@headerContent, "\n");
  329. $headerForwardDeclarations{$implClassNameWithNamespace} = 1;
  330. # - Add constants.
  331. if ($numConstants > 0) {
  332. my @headerConstants = ();
  333. # FIXME: we need a way to include multiple enums.
  334. foreach my $constant (@{$dataNode->constants}) {
  335. my $constantName = $constant->name;
  336. my $constantValue = $constant->value;
  337. my $output = "WEBDOM_" . $constantName . " = " . $constantValue;
  338. push(@headerConstants, " " . $output);
  339. }
  340. my $combinedConstants = join(",\n", @headerConstants);
  341. push(@headerContent, " ");
  342. push(@headerContent, "enum {\n");
  343. push(@headerContent, $combinedConstants);
  344. push(@headerContent, "\n ");
  345. push(@headerContent, "};\n\n");
  346. }
  347. my @headerAttributes = ();
  348. # - Add attribute getters/setters.
  349. if ($numAttributes > 0) {
  350. foreach my $attribute (@{$dataNode->attributes}) {
  351. next if ShouldSkipTypeInHeader($attribute);
  352. my $attributeConditionalString = GenerateConditionalString($attribute->signature);
  353. my $attributeName = $attribute->signature->name;
  354. my $attributeType = GetCPPType($attribute->signature->type, 0);
  355. my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
  356. my $property = "";
  357. $property .= "#if ${attributeConditionalString}\n" if $attributeConditionalString;
  358. $property .= " " . $attributeType . ($attributeType =~ /\*$/ ? "" : " ") . $attributeName . "() const";
  359. my $availabilityMacro = "";
  360. my $declarationSuffix = ";\n";
  361. AddForwardDeclarationsForType($attribute->signature->type, 1);
  362. $attributeType = GetCPPType($attribute->signature->type, 1);
  363. my $setterName = "set" . ucfirst($attributeName);
  364. $property .= $declarationSuffix;
  365. push(@headerAttributes, $property);
  366. if (!$attributeIsReadonly and !$attribute->signature->extendedAttributes->{"Replaceable"}) {
  367. $property = " void $setterName($attributeType)";
  368. $property .= $declarationSuffix;
  369. push(@headerAttributes, $property);
  370. }
  371. push(@headerAttributes, "#endif\n") if $attributeConditionalString;
  372. }
  373. push(@headerContent, @headerAttributes) if @headerAttributes > 0;
  374. }
  375. my @headerFunctions = ();
  376. my @deprecatedHeaderFunctions = ();
  377. my @interfaceFunctions = ();
  378. # - Add functions.
  379. if ($numFunctions > 0) {
  380. foreach my $function (@{$dataNode->functions}) {
  381. next if ShouldSkipTypeInHeader($function);
  382. my $functionName = $function->signature->name;
  383. my $returnType = GetCPPType($function->signature->type, 0);
  384. my $numberOfParameters = @{$function->parameters};
  385. my %typesToForwardDeclare = ($function->signature->type => 1);
  386. my $parameterIndex = 0;
  387. my $functionSig = "$returnType $functionName(";
  388. my $methodName = $functionName;
  389. foreach my $param (@{$function->parameters}) {
  390. my $paramName = $param->name;
  391. my $paramType = GetCPPType($param->type, 1);
  392. $typesToForwardDeclare{$param->type} = 1;
  393. $functionSig .= ", " if $parameterIndex >= 1;
  394. $functionSig .= "$paramType $paramName";
  395. $parameterIndex++;
  396. }
  397. $functionSig .= ")";
  398. if ($dataNode->extendedAttributes->{"PureInterface"}) {
  399. push(@interfaceFunctions, " virtual " . $functionSig . " = 0;\n");
  400. }
  401. my $functionDeclaration = $functionSig;
  402. $functionDeclaration .= ";\n";
  403. foreach my $type (keys %typesToForwardDeclare) {
  404. # add any forward declarations to the public header if a deprecated version will be generated
  405. AddForwardDeclarationsForType($type, 1);
  406. }
  407. push(@headerFunctions, " ");
  408. push(@headerFunctions, $functionDeclaration);
  409. }
  410. if (@headerFunctions > 0) {
  411. push(@headerContent, "\n") if @headerAttributes > 0;
  412. push(@headerContent, @headerFunctions);
  413. }
  414. }
  415. push(@headerContent, "\n");
  416. push(@headerContent, " $implClassNameWithNamespace* impl() const;\n");
  417. if ($parentName eq "WebDOMObject") {
  418. push(@headerContent, "\nprotected:\n");
  419. push(@headerContent, " struct ${className}Private;\n");
  420. push(@headerContent, " ${className}Private* m_impl;\n");
  421. }
  422. push(@headerContent, "};\n\n");
  423. # for PureInterface classes also add the interface that the client code needs to
  424. # implement
  425. if ($dataNode->extendedAttributes->{"PureInterface"}) {
  426. push(@headerContent, "class WebUser$interfaceName {\n");
  427. push(@headerContent, "public:\n");
  428. push(@headerContent, " virtual void ref() = 0;\n");
  429. push(@headerContent, " virtual void deref() = 0;\n\n");
  430. push(@headerContent, @interfaceFunctions);
  431. push(@headerContent, "\nprotected:\n");
  432. push(@headerContent, " virtual ~WebUser$interfaceName() {}\n");
  433. push(@headerContent, "};\n\n");
  434. }
  435. push(@headerContent, "WebCore::$implClassName* toWebCore(const $className&);\n");
  436. push(@headerContent, "$className toWebKit(WebCore::$implClassName*);\n");
  437. if ($dataNode->extendedAttributes->{"PureInterface"}) {
  438. push(@headerContent, "$className toWebKit(WebUser$interfaceName*);\n");
  439. }
  440. push(@headerContent, "\n#endif\n");
  441. push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditionalString;
  442. }
  443. sub AddEarlyReturnStatement
  444. {
  445. my $returnType = shift;
  446. if (!defined($returnType) or $returnType eq "void") {
  447. $returnType = "";
  448. } elsif ($codeGenerator->IsPrimitiveType($returnType)) {
  449. $returnType = " 0";
  450. } elsif ($returnType eq "bool") {
  451. $returnType = " false";
  452. } else {
  453. $returnType = " $returnType()";
  454. }
  455. # TODO: We could set exceptions here, if we want that
  456. my $statement = " if (!impl())\n";
  457. $statement .= " return$returnType;\n\n";
  458. return $statement;
  459. }
  460. sub AddReturnStatement
  461. {
  462. my $typeInfo = shift;
  463. my $returnValue = shift;
  464. # Used to invoke KURLs "const String&" operator
  465. if ($codeGenerator->IsStringType($typeInfo->signature->type)) {
  466. return " return static_cast<const WTF::String&>($returnValue);\n";
  467. }
  468. return " return $returnValue;\n";
  469. }
  470. sub GenerateImplementation
  471. {
  472. my $object = shift;
  473. my $dataNode = shift;
  474. my @ancestorInterfaceNames = ();
  475. if (@{$dataNode->parents} > 1) {
  476. $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
  477. }
  478. my $interfaceName = $dataNode->name;
  479. my $className = GetClassName($interfaceName);
  480. my $implClassName = GetImplClassName($interfaceName);
  481. my $parentImplClassName = GetParentImplClassName($dataNode);
  482. my $implClassNameWithNamespace = "WebCore::" . $implClassName;
  483. my $baseClass = "WebDOM$parentImplClassName";
  484. my $conditional = $dataNode->extendedAttributes->{"Conditional"};
  485. my $numAttributes = @{$dataNode->attributes};
  486. my $numFunctions = @{$dataNode->functions};
  487. # - Add default header template.
  488. @implContentHeader = split("\r", $implementationLicenseTemplate);
  489. # - INCLUDES -
  490. push(@implContentHeader, "\n#include \"config.h\"\n");
  491. my $conditionalString = GenerateConditionalString($dataNode);
  492. push(@implContentHeader, "\n#if ${conditionalString}\n\n") if $conditionalString;
  493. push(@implContentHeader, "#include \"$className.h\"\n\n");
  494. $implIncludes{"WebExceptionHandler.h"} = 1;
  495. $implIncludes{"$implClassName.h"} = 1;
  496. @implContent = ();
  497. push(@implContent, "#include <wtf/GetPtr.h>\n");
  498. push(@implContent, "#include <wtf/RefPtr.h>\n\n");
  499. # Private datastructure, encapsulating WebCore types
  500. if ($baseClass eq "WebDOMObject") {
  501. push(@implContent, "struct ${className}::${className}Private {\n");
  502. push(@implContent, " ${className}Private($implClassNameWithNamespace* object = 0)\n");
  503. push(@implContent, " : impl(object)\n");
  504. push(@implContent, " {\n");
  505. push(@implContent, " }\n\n");
  506. push(@implContent, " RefPtr<$implClassNameWithNamespace> impl;\n");
  507. push(@implContent, "};\n\n");
  508. }
  509. # Constructor
  510. push(@implContent, "${className}::$className()\n");
  511. push(@implContent, " : ${baseClass}()\n");
  512. push(@implContent, " , m_impl(0)\n") if ($baseClass eq "WebDOMObject");
  513. push(@implContent, "{\n");
  514. push(@implContent, "}\n\n");
  515. push(@implContent, "${className}::$className($implClassNameWithNamespace* impl)\n");
  516. if ($baseClass eq "WebDOMObject") {
  517. push(@implContent, " : ${baseClass}()\n");
  518. push(@implContent, " , m_impl(new ${className}Private(impl))\n");
  519. push(@implContent, "{\n");
  520. push(@implContent, "}\n\n");
  521. push(@implContent, "${className}::${className}(const ${className}& copy)\n");
  522. push(@implContent, " : ${baseClass}()\n");
  523. push(@implContent, "{\n");
  524. push(@implContent, " m_impl = copy.impl() ? new ${className}Private(copy.impl()) : 0;\n");
  525. push(@implContent, "}\n\n");
  526. push(@implContent, "${className}& ${className}::operator\=(const ${className}& copy)\n");
  527. push(@implContent, "{\n");
  528. push(@implContent, " delete m_impl;\n");
  529. push(@implContent, " m_impl = copy.impl() ? new ${className}Private(copy.impl()) : 0;\n");
  530. push(@implContent, " return *this;\n");
  531. push(@implContent, "}\n\n");
  532. push(@implContent, "$implClassNameWithNamespace* ${className}::impl() const\n");
  533. push(@implContent, "{\n");
  534. push(@implContent, " return m_impl ? m_impl->impl.get() : 0;\n");
  535. push(@implContent, "}\n\n");
  536. # Destructor
  537. push(@implContent, "${className}::~$className()\n");
  538. push(@implContent, "{\n");
  539. push(@implContent, " delete m_impl;\n");
  540. push(@implContent, " m_impl = 0;\n");
  541. push(@implContent, "}\n\n");
  542. } else {
  543. push(@implContent, " : ${baseClass}(impl)\n");
  544. push(@implContent, "{\n");
  545. push(@implContent, "}\n\n");
  546. push(@implContent, "$implClassNameWithNamespace* ${className}::impl() const\n");
  547. push(@implContent, "{\n");
  548. push(@implContent, " return static_cast<$implClassNameWithNamespace*>(${baseClass}::impl());\n");
  549. push(@implContent, "}\n\n");
  550. }
  551. # START implementation
  552. %attributeNames = ();
  553. # - Attributes
  554. if ($numAttributes > 0) {
  555. foreach my $attribute (@{$dataNode->attributes}) {
  556. next if ShouldSkipTypeInImplementation($attribute);
  557. AddIncludesForType($attribute->signature->type);
  558. my $idlType = $codeGenerator->StripModule($attribute->signature->type);
  559. my $attributeName = $attribute->signature->name;
  560. my $attributeType = GetCPPType($attribute->signature->type, 0);
  561. my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
  562. $attributeNames{$attributeName} = 1;
  563. # - GETTER
  564. my $getterSig = "$attributeType $className\:\:$attributeName() const\n";
  565. my $hasGetterException = @{$attribute->getterExceptions};
  566. my $getterContentHead = "impl()->" . $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
  567. my $getterContentTail = ")";
  568. # Special cases
  569. my @customGetterContent = ();
  570. if ($attribute->signature->extendedAttributes->{"ConvertToString"}) {
  571. $getterContentHead = "WTF::String::number(" . $getterContentHead;
  572. $getterContentTail .= ")";
  573. } elsif ($attribute->signature->type eq "SerializedScriptValue") {
  574. $getterContentHead = "$getterContentHead";
  575. $getterContentTail .= "->toString()";
  576. } elsif (ConversionNeeded($attribute->signature->type)) {
  577. $getterContentHead = "toWebKit(WTF::getPtr($getterContentHead";
  578. $getterContentTail .= "))";
  579. }
  580. my $getterContent;
  581. if ($hasGetterException) {
  582. $getterContent = $getterContentHead . "ec" . $getterContentTail;
  583. } else {
  584. $getterContent = $getterContentHead . $getterContentTail;
  585. }
  586. my $attributeConditionalString = GenerateConditionalString($attribute->signature);
  587. push(@implContent, "#if ${attributeConditionalString}\n") if $attributeConditionalString;
  588. push(@implContent, $getterSig);
  589. push(@implContent, "{\n");
  590. push(@implContent, AddEarlyReturnStatement($attributeType));
  591. push(@implContent, @customGetterContent);
  592. if ($hasGetterException) {
  593. # Differentiated between when the return type is a pointer and
  594. # not for white space issue (ie. Foo *result vs. int result).
  595. if ($attributeType =~ /\*$/) {
  596. $getterContent = $attributeType . "result = " . $getterContent;
  597. } else {
  598. $getterContent = $attributeType . " result = " . $getterContent;
  599. }
  600. push(@implContent, " $exceptionInit\n");
  601. push(@implContent, " $getterContent;\n");
  602. push(@implContent, " $exceptionRaiseOnError\n");
  603. push(@implContent, AddReturnStatement($attribute, "result"));
  604. } else {
  605. push(@implContent, AddReturnStatement($attribute, $getterContent));
  606. }
  607. push(@implContent, "}\n\n");
  608. # - SETTER
  609. if (!$attributeIsReadonly and !$attribute->signature->extendedAttributes->{"Replaceable"}) {
  610. # Exception handling
  611. my $hasSetterException = @{$attribute->setterExceptions};
  612. my $coreSetterName = "set" . $codeGenerator->WK_ucfirst($attributeName);
  613. my $setterName = "set" . ucfirst($attributeName);
  614. my $argName = "new" . ucfirst($attributeName);
  615. my $arg = GetCPPTypeGetter($argName, $idlType);
  616. # The definition of ConvertToString is flipped for the setter
  617. if ($attribute->signature->extendedAttributes->{"ConvertToString"}) {
  618. $arg = "WTF::String($arg).toInt()";
  619. }
  620. my $attributeType = GetCPPType($attribute->signature->type, 1);
  621. push(@implContent, "void $className\:\:$setterName($attributeType $argName)\n");
  622. push(@implContent, "{\n");
  623. push(@implContent, AddEarlyReturnStatement());
  624. push(@implContent, " $exceptionInit\n") if $hasSetterException;
  625. my $ec = $hasSetterException ? ", ec" : "";
  626. my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
  627. push(@implContent, " impl()->$setterExpressionPrefix$arg$ec);\n");
  628. push(@implContent, " $exceptionRaiseOnError\n") if $hasSetterException;
  629. push(@implContent, "}\n\n");
  630. }
  631. push(@implContent, "#endif\n") if $attributeConditionalString;
  632. }
  633. }
  634. # - Functions
  635. if ($numFunctions > 0) {
  636. foreach my $function (@{$dataNode->functions}) {
  637. # Treat PureInterface as Custom as well, since the WebCore versions will take a script context as well
  638. next if ShouldSkipTypeInImplementation($function) || $dataNode->extendedAttributes->{"PureInterface"};
  639. AddIncludesForType($function->signature->type);
  640. my $functionName = $function->signature->name;
  641. my $returnType = GetCPPType($function->signature->type, 0);
  642. my $hasParameters = @{$function->parameters};
  643. my $raisesExceptions = @{$function->raisesExceptions};
  644. my @parameterNames = ();
  645. my @needsAssert = ();
  646. my %needsCustom = ();
  647. my $parameterIndex = 0;
  648. my $functionSig = "$returnType $className\:\:$functionName(";
  649. foreach my $param (@{$function->parameters}) {
  650. my $paramName = $param->name;
  651. my $paramType = GetCPPType($param->type, 1);
  652. # make a new parameter name if the original conflicts with a property name
  653. $paramName = "in" . ucfirst($paramName) if $attributeNames{$paramName};
  654. AddIncludesForType($param->type);
  655. my $idlType = $codeGenerator->StripModule($param->type);
  656. my $implGetter = GetCPPTypeGetter($paramName, $idlType);
  657. push(@parameterNames, $implGetter);
  658. $needsCustom{"NodeToReturn"} = $paramName if $param->extendedAttributes->{"Return"};
  659. unless ($codeGenerator->IsPrimitiveType($idlType) or $codeGenerator->IsStringType($idlType)) {
  660. push(@needsAssert, " ASSERT($paramName);\n");
  661. }
  662. $functionSig .= ", " if $parameterIndex >= 1;
  663. $functionSig .= "$paramType $paramName";
  664. $parameterIndex++;
  665. }
  666. $functionSig .= ")";
  667. my @functionContent = ();
  668. push(@parameterNames, "ec") if $raisesExceptions;
  669. my $content = "impl()->" . $codeGenerator->WK_lcfirst($functionName) . "(" . join(", ", @parameterNames) . ")";
  670. if ($returnType eq "void") {
  671. # Special case 'void' return type.
  672. if ($raisesExceptions) {
  673. push(@functionContent, " $exceptionInit\n");
  674. push(@functionContent, " $content;\n");
  675. push(@functionContent, " $exceptionRaiseOnError\n");
  676. } else {
  677. push(@functionContent, " $content;\n");
  678. }
  679. } elsif (defined $needsCustom{"NodeToReturn"}) {
  680. # TODO: This is important to enable, once we care about custom code!
  681. # Special case the insertBefore, replaceChild, removeChild
  682. # and appendChild functions from DOMNode
  683. my $toReturn = $needsCustom{"NodeToReturn"};
  684. if ($raisesExceptions) {
  685. push(@functionContent, " $exceptionInit\n");
  686. push(@functionContent, " if ($content)\n");
  687. push(@functionContent, " return $toReturn;\n");
  688. push(@functionContent, " $exceptionRaiseOnError\n");
  689. push(@functionContent, " return $className();\n");
  690. } else {
  691. push(@functionContent, " if ($content)\n");
  692. push(@functionContent, " return $toReturn;\n");
  693. push(@functionContent, " return NULL;\n");
  694. }
  695. } else {
  696. if (ConversionNeeded($function->signature->type)) {
  697. $content = "toWebKit(WTF::getPtr($content))";
  698. }
  699. if ($raisesExceptions) {
  700. # Differentiated between when the return type is a pointer and
  701. # not for white space issue (ie. Foo *result vs. int result).
  702. if ($returnType =~ /\*$/) {
  703. $content = $returnType . "result = " . $content;
  704. } else {
  705. $content = $returnType . " result = " . $content;
  706. }
  707. push(@functionContent, " $exceptionInit\n");
  708. push(@functionContent, " $content;\n");
  709. push(@functionContent, " $exceptionRaiseOnError\n");
  710. push(@functionContent, " return result;\n");
  711. } else {
  712. push(@functionContent, " return $content;\n");
  713. }
  714. }
  715. push(@implContent, "$functionSig\n");
  716. push(@implContent, "{\n");
  717. push(@implContent, AddEarlyReturnStatement($returnType));
  718. push(@implContent, @functionContent);
  719. push(@implContent, "}\n\n");
  720. # Clear the hash
  721. %needsCustom = ();
  722. }
  723. }
  724. # END implementation
  725. # Generate internal interfaces
  726. push(@implContent, "WebCore::$implClassName* toWebCore(const $className& wrapper)\n");
  727. push(@implContent, "{\n");
  728. push(@implContent, " return wrapper.impl();\n");
  729. push(@implContent, "}\n\n");
  730. push(@implContent, "$className toWebKit(WebCore::$implClassName* value)\n");
  731. push(@implContent, "{\n");
  732. push(@implContent, " return $className(value);\n");
  733. push(@implContent, "}\n");
  734. # - End the ifdef conditional if necessary
  735. push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString;
  736. }
  737. # Internal helper
  738. sub WriteData
  739. {
  740. my $object = shift;
  741. my $name = shift;
  742. # Open files for writing...
  743. my $headerFileName = "$outputDir/" . $name . ".h";
  744. my $implFileName = "$outputDir/" . $name . ".cpp";
  745. # Remove old files.
  746. unlink($headerFileName);
  747. unlink($implFileName);
  748. # Write public header.
  749. open(HEADER, ">$headerFileName") or die "Couldn't open file $headerFileName";
  750. print HEADER @headerContentHeader;
  751. print HEADER "\n";
  752. foreach my $class (sort keys(%headerForwardDeclarations)) {
  753. if ($class =~ /::/) {
  754. my $namespacePart = $class;
  755. $namespacePart =~ s/::.*//;
  756. my $classPart = $class;
  757. $classPart =~ s/${namespacePart}:://;
  758. print HEADER "namespace $namespacePart {\nclass $classPart;\n};\n\n";
  759. } else {
  760. print HEADER "class $class;\n"
  761. }
  762. }
  763. my $hasForwardDeclarations = keys(%headerForwardDeclarations);
  764. print HEADER "\n" if $hasForwardDeclarations;
  765. print HEADER @headerContent;
  766. close(HEADER);
  767. @headerContentHeader = ();
  768. @headerContent = ();
  769. %headerForwardDeclarations = ();
  770. # Write implementation file.
  771. open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName";
  772. print IMPL @implContentHeader;
  773. foreach my $include (sort keys(%implIncludes)) {
  774. # "className.h" is already included right after config.h, silence check-webkit-style
  775. next if $include eq "$name.h";
  776. print IMPL "#include \"$include\"\n";
  777. }
  778. print IMPL @implContent;
  779. close(IMPL);
  780. @implContentHeader = ();
  781. @implContent = ();
  782. %implIncludes = ();
  783. }
  784. 1;