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