1#!/usr/bin/perl -w 2 3# Copyright (C) 2005, 2006, 2007, 2009 Apple Inc. All rights reserved. 4# Copyright (C) 2009, Julien Chaffraix <jchaffraix@webkit.org> 5# Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 17# its contributors may be used to endorse or promote products derived 18# from this software without specific prior written permission. 19# 20# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 21# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 24# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31use strict; 32 33use Config; 34use Getopt::Long; 35use File::Path; 36use IO::File; 37use InFilesParser; 38use Switch; 39 40my $printFactory = 0; 41my $printWrapperFactory = 0; 42my $printWrapperFactoryV8 = 0; 43my $tagsFile = ""; 44my $attrsFile = ""; 45my $outputDir = "."; 46my %tags = (); 47my %attrs = (); 48my %parameters = (); 49my $extraDefines = 0; 50my $preprocessor = "/usr/bin/gcc -E -P -x c++"; 51 52GetOptions( 53 'tags=s' => \$tagsFile, 54 'attrs=s' => \$attrsFile, 55 'factory' => \$printFactory, 56 'outputDir=s' => \$outputDir, 57 'extraDefines=s' => \$extraDefines, 58 'preprocessor=s' => \$preprocessor, 59 'wrapperFactory' => \$printWrapperFactory, 60 'wrapperFactoryV8' => \$printWrapperFactoryV8 61); 62 63die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile)); 64 65readNames($tagsFile, "tags") if length($tagsFile); 66readNames($attrsFile, "attrs") if length($attrsFile); 67 68die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $parameters{namespace}; 69die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $parameters{namespaceURI}; 70 71$parameters{namespacePrefix} = $parameters{namespace} unless $parameters{namespacePrefix}; 72 73mkpath($outputDir); 74my $namesBasePath = "$outputDir/$parameters{namespace}Names"; 75my $factoryBasePath = "$outputDir/$parameters{namespace}ElementFactory"; 76my $wrapperFactoryFileName = "$parameters{namespace}ElementWrapperFactory"; 77 78printNamesHeaderFile("$namesBasePath.h"); 79printNamesCppFile("$namesBasePath.cpp"); 80 81if ($printFactory) { 82 printFactoryCppFile("$factoryBasePath.cpp"); 83 printFactoryHeaderFile("$factoryBasePath.h"); 84} 85 86die "You cannot specify both --wrapperFactory and --wrapperFactoryV8" if $printWrapperFactory && $printWrapperFactoryV8; 87my $wrapperFactoryType = ""; 88if ($printWrapperFactory) { 89 $wrapperFactoryType = "JS"; 90} elsif ($printWrapperFactoryV8) { 91 $wrapperFactoryType = "V8"; 92} 93 94if ($wrapperFactoryType) { 95 printWrapperFactoryCppFile($outputDir, $wrapperFactoryType, $wrapperFactoryFileName); 96 printWrapperFactoryHeaderFile($outputDir, $wrapperFactoryType, $wrapperFactoryFileName); 97} 98 99### Hash initialization 100 101sub defaultTagPropertyHash 102{ 103 return ( 104 'constructorNeedsCreatedByParser' => 0, 105 'constructorNeedsFormElement' => 0, 106 'createWithNew' => 0, 107 'interfaceName' => defaultInterfaceName($_[0]), 108 # By default, the JSInterfaceName is the same as the interfaceName. 109 'JSInterfaceName' => defaultInterfaceName($_[0]), 110 'mapToTagName' => '', 111 'wrapperOnlyIfMediaIsAvailable' => 0, 112 'conditional' => 0 113 ); 114} 115 116sub defaultParametersHash 117{ 118 return ( 119 'namespace' => '', 120 'namespacePrefix' => '', 121 'namespaceURI' => '', 122 'guardFactoryWith' => '', 123 'tagsNullNamespace' => 0, 124 'attrsNullNamespace' => 0 125 ); 126} 127 128sub defaultInterfaceName 129{ 130 die "No namespace found" if !$parameters{namespace}; 131 return $parameters{namespace} . upperCaseName($_[0]) . "Element" 132} 133 134### Parsing handlers 135 136sub tagsHandler 137{ 138 my ($tag, $property, $value) = @_; 139 140 $tag =~ s/-/_/g; 141 142 # Initialize default property values. 143 $tags{$tag} = { defaultTagPropertyHash($tag) } if !defined($tags{$tag}); 144 145 if ($property) { 146 die "Unknown property $property for tag $tag\n" if !defined($tags{$tag}{$property}); 147 148 # The code relies on JSInterfaceName deriving from interfaceName to check for custom JSInterfaceName. 149 # So override JSInterfaceName if it was not already set. 150 $tags{$tag}{JSInterfaceName} = $value if $property eq "interfaceName" && $tags{$tag}{JSInterfaceName} eq $tags{$tag}{interfaceName}; 151 152 $tags{$tag}{$property} = $value; 153 } 154} 155 156sub attrsHandler 157{ 158 my ($attr, $property, $value) = @_; 159 160 $attr =~ s/-/_/g; 161 162 # Initialize default properties' values. 163 $attrs{$attr} = {} if !defined($attrs{$attr}); 164 165 if ($property) { 166 die "Unknown property $property for attribute $attr\n" if !defined($attrs{$attr}{$property}); 167 $attrs{$attr}{$property} = $value; 168 } 169} 170 171sub parametersHandler 172{ 173 my ($parameter, $value) = @_; 174 175 # Initialize default properties' values. 176 %parameters = defaultParametersHash() if !(keys %parameters); 177 178 die "Unknown parameter $parameter for tags/attrs\n" if !defined($parameters{$parameter}); 179 $parameters{$parameter} = $value; 180} 181 182## Support routines 183 184sub readNames 185{ 186 my ($namesFile, $type) = @_; 187 188 my $names = new IO::File; 189 190 if ($extraDefines eq 0) { 191 open($names, $preprocessor . " " . $namesFile . "|") or die "Failed to open file: $namesFile"; 192 } else { 193 open($names, $preprocessor . " -D" . join(" -D", split(" ", $extraDefines)) . " " . $namesFile . "|") or die "Failed to open file: $namesFile"; 194 } 195 196 # Store hashes keys count to know if some insertion occured. 197 my $tagsCount = keys %tags; 198 my $attrsCount = keys %attrs; 199 200 my $InParser = InFilesParser->new(); 201 202 switch ($type) { 203 case "tags" { 204 $InParser->parse($names, \¶metersHandler, \&tagsHandler); 205 } 206 case "attrs" { 207 $InParser->parse($names, \¶metersHandler, \&attrsHandler); 208 } 209 else { 210 die "Do not know how to parse $type"; 211 } 212 } 213 214 close($names); 215 216 die "Failed to read names from file: $namesFile" if ((keys %tags == $tagsCount) && (keys %attrs == $attrsCount)); 217} 218 219sub printMacros 220{ 221 my ($F, $macro, $suffix, $namesRef) = @_; 222 my %names = %$namesRef; 223 224 for my $name (sort keys %$namesRef) { 225 print F "$macro $name","$suffix;\n"; 226 } 227} 228 229sub usesDefaultWrapper 230{ 231 my $tagName = shift; 232 return $tagName eq $parameters{namespace} . "Element"; 233} 234 235# Build a direct mapping from the tags to the Element to create, excluding 236# Element that have not constructor. 237sub buildConstructorMap 238{ 239 my %tagConstructorMap = (); 240 for my $tagName (keys %tags) { 241 my $interfaceName = $tags{$tagName}{interfaceName}; 242 next if (usesDefaultWrapper($interfaceName)); 243 244 if ($tags{$tagName}{mapToTagName}) { 245 die "Cannot handle multiple mapToTagName for $tagName\n" if $tags{$tags{$tagName}{mapToTagName}}{mapToTagName}; 246 $interfaceName = $tags{ $tags{$tagName}{mapToTagName} }{interfaceName}; 247 } 248 249 # Chop the string to keep the interesting part. 250 $interfaceName =~ s/$parameters{namespace}(.*)Element/$1/; 251 $tagConstructorMap{$tagName} = lc($interfaceName); 252 } 253 254 return %tagConstructorMap; 255} 256 257# Helper method that print the constructor's signature avoiding 258# unneeded arguments. 259sub printConstructorSignature 260{ 261 my ($F, $tagName, $constructorName, $constructorTagName) = @_; 262 263 print F "static PassRefPtr<$parameters{namespace}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document* document"; 264 if ($parameters{namespace} eq "HTML") { 265 print F ", HTMLFormElement*"; 266 print F " formElement" if $tags{$tagName}{constructorNeedsFormElement}; 267 } 268 print F ", bool"; 269 print F " createdByParser" if $tags{$tagName}{constructorNeedsCreatedByParser}; 270 print F ")\n{\n"; 271} 272 273# Helper method to dump the constructor interior and call the 274# Element constructor with the right arguments. 275# The variable names should be kept in sync with the previous method. 276sub printConstructorInterior 277{ 278 my ($F, $tagName, $interfaceName, $constructorTagName) = @_; 279 280 # Handle media elements. 281 if ($tags{$tagName}{wrapperOnlyIfMediaIsAvailable}) { 282 print F <<END 283 if (!MediaPlayer::isAvailable()) 284 return HTMLElement::create($constructorTagName, document); 285END 286; 287 } 288 289 my $newPrefix = ""; 290 my $createSuffix = "::create"; 291 292 if ($tags{$tagName}{createWithNew}) { 293 $newPrefix = "new "; 294 $createSuffix = ""; 295 } 296 297 # Call the constructor with the right parameters. 298 print F " return $newPrefix$interfaceName${createSuffix}($constructorTagName, document"; 299 print F ", formElement" if $tags{$tagName}{constructorNeedsFormElement}; 300 print F ", createdByParser" if $tags{$tagName}{constructorNeedsCreatedByParser}; 301 print F ");\n}\n\n"; 302} 303 304sub printConstructors 305{ 306 my ($F, $tagConstructorMapRef) = @_; 307 my %tagConstructorMap = %$tagConstructorMapRef; 308 309 print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; 310 311 # This is to avoid generating the same constructor several times. 312 my %uniqueTags = (); 313 for my $tagName (sort keys %tagConstructorMap) { 314 my $interfaceName = $tags{$tagName}{interfaceName}; 315 316 # Ignore the mapped tag 317 # FIXME: It could be moved inside this loop but was split for readibility. 318 next if (defined($uniqueTags{$interfaceName}) || $tags{$tagName}{mapToTagName}); 319 320 $uniqueTags{$interfaceName} = '1'; 321 322 my $conditional = $tags{$tagName}{conditional}; 323 if ($conditional) { 324 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 325 print F "#if ${conditionalString}\n\n"; 326 } 327 328 printConstructorSignature($F, $tagName, $tagConstructorMap{$tagName}, "tagName"); 329 printConstructorInterior($F, $tagName, $interfaceName, "tagName"); 330 331 if ($conditional) { 332 print F "#endif\n"; 333 } 334 } 335 336 # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname. 337 for my $tagName (sort keys %tagConstructorMap) { 338 if ($tags{$tagName}{mapToTagName}) { 339 my $mappedName = $tags{$tagName}{mapToTagName}; 340 printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName"); 341 printConstructorInterior($F, $mappedName, $tags{$mappedName}{interfaceName}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())"); 342 } 343 } 344 345 print F "#endif\n" if $parameters{guardFactoryWith}; 346} 347 348sub printFunctionInits 349{ 350 my ($F, $tagConstructorMap) = @_; 351 my %tagConstructorMap = %$tagConstructorMap; 352 353 for my $tagName (sort keys %tagConstructorMap) { 354 355 my $conditional = $tags{$tagName}{conditional}; 356 if ($conditional) { 357 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 358 print F "#if ${conditionalString}\n"; 359 } 360 361 if ($tags{$tagName}{mapToTagName}) { 362 print F " addTag(${tagName}Tag, $tags{$tagName}{mapToTagName}To${tagName}Constructor);\n"; 363 } else { 364 print F " addTag(${tagName}Tag, $tagConstructorMap{$tagName}Constructor);\n"; 365 } 366 367 if ($conditional) { 368 print F "#endif\n\n"; 369 } 370 } 371} 372 373sub svgCapitalizationHacks 374{ 375 my $name = shift; 376 377 $name = "FE" . ucfirst $1 if $name =~ /^fe(.+)$/; 378 379 return $name; 380} 381 382sub upperCaseName 383{ 384 my $name = shift; 385 386 $name = svgCapitalizationHacks($name) if ($parameters{namespace} eq "SVG"); 387 388 while ($name =~ /^(.*?)_(.*)/) { 389 $name = $1 . ucfirst $2; 390 } 391 392 return ucfirst $name; 393} 394 395sub printLicenseHeader 396{ 397 my $F = shift; 398 print F "/* 399 * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. 400 * 401 * This file was generated by the dom/make_names.pl script. 402 * 403 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 404 * 405 * Redistribution and use in source and binary forms, with or without 406 * modification, are permitted provided that the following conditions 407 * are met: 408 * 1. Redistributions of source code must retain the above copyright 409 * notice, this list of conditions and the following disclaimer. 410 * 2. Redistributions in binary form must reproduce the above copyright 411 * notice, this list of conditions and the following disclaimer in the 412 * documentation and/or other materials provided with the distribution. 413 * 414 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 415 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 416 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 417 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 418 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 419 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 420 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 421 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 422 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 423 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 424 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 425 */ 426 427"; 428} 429 430sub printNamesHeaderFile 431{ 432 my ($headerPath) = shift; 433 my $F; 434 open F, ">$headerPath"; 435 436 printLicenseHeader($F); 437 print F "#ifndef DOM_$parameters{namespace}NAMES_H\n"; 438 print F "#define DOM_$parameters{namespace}NAMES_H\n\n"; 439 print F "#include \"QualifiedName.h\"\n\n"; 440 441 print F "namespace WebCore {\n\n namespace $parameters{namespace}Names {\n\n"; 442 443 my $lowerNamespace = lc($parameters{namespacePrefix}); 444 print F "#ifndef DOM_$parameters{namespace}NAMES_HIDE_GLOBALS\n"; 445 print F "// Namespace\n"; 446 print F "extern const WebCore::AtomicString ${lowerNamespace}NamespaceURI;\n\n"; 447 448 if (keys %tags) { 449 print F "// Tags\n"; 450 printMacros($F, "extern const WebCore::QualifiedName", "Tag", \%tags); 451 } 452 453 if (keys %attrs) { 454 print F "// Attributes\n"; 455 printMacros($F, "extern const WebCore::QualifiedName", "Attr", \%attrs); 456 } 457 print F "#endif\n\n"; 458 459 if (keys %tags) { 460 print F "WebCore::QualifiedName** get$parameters{namespace}Tags(size_t* size);\n"; 461 } 462 463 if (keys %attrs) { 464 print F "WebCore::QualifiedName** get$parameters{namespace}Attrs(size_t* size);\n"; 465 } 466 467 print F "\nvoid init();\n\n"; 468 print F "} }\n\n"; 469 print F "#endif\n\n"; 470 471 close F; 472} 473 474sub printNamesCppFile 475{ 476 my $cppPath = shift; 477 my $F; 478 open F, ">$cppPath"; 479 480 printLicenseHeader($F); 481 482 my $lowerNamespace = lc($parameters{namespacePrefix}); 483 484print F "#include \"config.h\"\n"; 485 486print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n"; 487print F "#define DOM_$parameters{namespace}NAMES_HIDE_GLOBALS 1\n"; 488print F "#else\n"; 489print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n"; 490print F "#endif\n\n"; 491 492 493print F "#include \"$parameters{namespace}Names.h\"\n\n"; 494print F "#include \"StaticConstructors.h\"\n"; 495 496print F "namespace WebCore {\n\n namespace $parameters{namespace}Names { 497 498using namespace WebCore; 499 500DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{namespaceURI}\") 501"; 502 503 if (keys %tags) { 504 print F "// Tags\n"; 505 for my $name (sort keys %tags) { 506 print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Tag, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n"; 507 } 508 509 print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Tags(size_t* size)\n"; 510 print F "{\n static WebCore::QualifiedName* $parameters{namespace}Tags[] = {\n"; 511 for my $name (sort keys %tags) { 512 print F " (WebCore::QualifiedName*)&${name}Tag,\n"; 513 } 514 print F " };\n"; 515 print F " *size = ", scalar(keys %tags), ";\n"; 516 print F " return $parameters{namespace}Tags;\n"; 517 print F "}\n"; 518 } 519 520 if (keys %attrs) { 521 print F "\n// Attributes\n"; 522 for my $name (sort keys %attrs) { 523 print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Attr, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n"; 524 } 525 print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Attrs(size_t* size)\n"; 526 print F "{\n static WebCore::QualifiedName* $parameters{namespace}Attr[] = {\n"; 527 for my $name (sort keys %attrs) { 528 print F " (WebCore::QualifiedName*)&${name}Attr,\n"; 529 } 530 print F " };\n"; 531 print F " *size = ", scalar(keys %attrs), ";\n"; 532 print F " return $parameters{namespace}Attr;\n"; 533 print F "}\n"; 534 } 535 536print F "\nvoid init() 537{ 538 static bool initialized = false; 539 if (initialized) 540 return; 541 initialized = true; 542 543 // Use placement new to initialize the globals. 544 545 AtomicString::init(); 546"; 547 548 print(F " AtomicString ${lowerNamespace}NS(\"$parameters{namespaceURI}\");\n\n"); 549 550 print(F " // Namespace\n"); 551 print(F " new ((void*)&${lowerNamespace}NamespaceURI) AtomicString(${lowerNamespace}NS);\n\n"); 552 if (keys %tags) { 553 my $tagsNamespace = $parameters{tagsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS"; 554 printDefinitions($F, \%tags, "tags", $tagsNamespace); 555 } 556 if (keys %attrs) { 557 my $attrsNamespace = $parameters{attrsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS"; 558 printDefinitions($F, \%attrs, "attributes", $attrsNamespace); 559 } 560 561 print F "}\n\n} }\n\n"; 562 close F; 563} 564 565sub printJSElementIncludes 566{ 567 my $F = shift; 568 my $wrapperFactoryType = shift; 569 570 my %tagsSeen; 571 for my $tagName (sort keys %tags) { 572 my $JSInterfaceName = $tags{$tagName}{JSInterfaceName}; 573 next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName); 574 $tagsSeen{$JSInterfaceName} = 1; 575 576 print F "#include \"${wrapperFactoryType}${JSInterfaceName}.h\"\n"; 577 } 578} 579 580sub printElementIncludes 581{ 582 my $F = shift; 583 584 my %tagsSeen; 585 for my $tagName (sort keys %tags) { 586 my $interfaceName = $tags{$tagName}{interfaceName}; 587 next if defined($tagsSeen{$interfaceName}); 588 $tagsSeen{$interfaceName} = 1; 589 590 print F "#include \"${interfaceName}.h\"\n"; 591 } 592} 593 594sub printDefinitions 595{ 596 my ($F, $namesRef, $type, $namespaceURI) = @_; 597 my $singularType = substr($type, 0, -1); 598 my $shortType = substr($singularType, 0, 4); 599 my $shortCamelType = ucfirst($shortType); 600 my $shortUpperType = uc($shortType); 601 602 print F " // " . ucfirst($type) . "\n"; 603 604 for my $name (sort keys %$namesRef) { 605 my $realName = $name; 606 $realName =~ s/_/-/g; 607 print F " new ((void*)&$name","${shortCamelType}) QualifiedName(nullAtom, \"$realName\", $namespaceURI);\n"; 608 } 609} 610 611## ElementFactory routines 612 613sub printFactoryCppFile 614{ 615 my $cppPath = shift; 616 my $F; 617 open F, ">$cppPath"; 618 619printLicenseHeader($F); 620 621print F <<END 622#include "config.h" 623#include "$parameters{namespace}ElementFactory.h" 624 625#include "$parameters{namespace}Names.h" 626END 627; 628 629printElementIncludes($F); 630 631print F <<END 632#include <wtf/HashMap.h> 633 634#if ENABLE(DASHBOARD_SUPPORT) 635#include "Document.h" 636#include "Settings.h" 637#endif 638 639namespace WebCore { 640 641using namespace $parameters{namespace}Names; 642 643END 644; 645 646print F "typedef PassRefPtr<$parameters{namespace}Element> (*ConstructorFunction)(const QualifiedName&, Document*"; 647print F ", HTMLFormElement*" if $parameters{namespace} eq "HTML"; 648print F ", bool createdByParser);\n"; 649print F <<END 650typedef HashMap<AtomicStringImpl*, ConstructorFunction> FunctionMap; 651 652static FunctionMap* gFunctionMap = 0; 653 654END 655; 656 657my %tagConstructorMap = buildConstructorMap(); 658 659printConstructors($F, \%tagConstructorMap); 660 661print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; 662 663print F <<END 664static void addTag(const QualifiedName& tag, ConstructorFunction func) 665{ 666 gFunctionMap->set(tag.localName().impl(), func); 667} 668 669static void createFunctionMap() 670{ 671 ASSERT(!gFunctionMap); 672 673 // Create the table. 674 gFunctionMap = new FunctionMap; 675 676 // Populate it with constructor functions. 677END 678; 679 680printFunctionInits($F, \%tagConstructorMap); 681 682print F "}\n"; 683print F "#endif\n" if $parameters{guardFactoryWith}; 684 685print F "\nPassRefPtr<$parameters{namespace}Element> $parameters{namespace}ElementFactory::create$parameters{namespace}Element(const QualifiedName& qName, Document* document"; 686print F ", HTMLFormElement* formElement" if $parameters{namespace} eq "HTML"; 687print F ", bool createdByParser)\n{\n"; 688 689print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; 690 691print F <<END 692 if (!document) 693 return 0; 694 695END 696; 697 698if ($parameters{namespace} ne "HTML") { 699print F <<END 700#if ENABLE(DASHBOARD_SUPPORT) 701 Settings* settings = document->settings(); 702 if (settings && settings->usesDashboardBackwardCompatibilityMode()) 703 return 0; 704#endif 705END 706; 707 708} 709 710print F <<END 711 if (!gFunctionMap) 712 createFunctionMap(); 713 if (ConstructorFunction function = gFunctionMap->get(qName.localName().impl())) 714END 715; 716 717if ($parameters{namespace} eq "HTML") { 718 print F " return function(qName, document, formElement, createdByParser);\n"; 719} else { 720 print F " return function(qName, document, createdByParser);\n"; 721} 722 723print F " return $parameters{namespace}Element::create(qName, document);\n"; 724 725if ($parameters{guardFactoryWith}) { 726 727print F <<END 728#else 729 return 0; 730#endif 731END 732; 733 734} 735 736print F <<END 737} 738 739} // namespace WebCore 740 741END 742; 743 744 close F; 745} 746 747sub printFactoryHeaderFile 748{ 749 my $headerPath = shift; 750 my $F; 751 open F, ">$headerPath"; 752 753 printLicenseHeader($F); 754 755 print F<<END 756#ifndef $parameters{namespace}ElementFactory_h 757#define $parameters{namespace}ElementFactory_h 758 759#include <wtf/PassRefPtr.h> 760 761namespace WebCore { 762 class Element; 763 class Document; 764 class QualifiedName; 765 class AtomicString; 766} 767 768namespace WebCore { 769 770 class $parameters{namespace}Element; 771END 772; 773 774print F " class HTMLFormElement;\n" if $parameters{namespace} eq "HTML"; 775 776print F<<END 777 // The idea behind this class is that there will eventually be a mapping from namespace URIs to ElementFactories that can dispense 778 // elements. In a compound document world, the generic createElement function (will end up being virtual) will be called. 779 class $parameters{namespace}ElementFactory { 780 public: 781 PassRefPtr<Element> createElement(const WebCore::QualifiedName&, WebCore::Document*, bool createdByParser = true); 782END 783; 784print F " static PassRefPtr<$parameters{namespace}Element> create$parameters{namespace}Element(const WebCore::QualifiedName&, WebCore::Document*"; 785print F ", HTMLFormElement* = 0" if $parameters{namespace} eq "HTML"; 786print F ", bool /*createdByParser*/ = true);\n"; 787 788printf F<<END 789 }; 790} 791 792#endif // $parameters{namespace}ElementFactory_h 793 794END 795; 796 797 close F; 798} 799 800## Wrapper Factory routines 801 802sub usesDefaultJSWrapper 803{ 804 my $name = shift; 805 806 # A tag reuses the default wrapper if its JSInterfaceName matches the default namespace Element. 807 return $tags{$name}{JSInterfaceName} eq $parameters{namespace} . "Element" || $tags{$name}{JSInterfaceName} eq "HTMLNoScriptElement"; 808} 809 810sub printWrapperFunctions 811{ 812 my $F = shift; 813 my $wrapperFactoryType = shift; 814 815 my %tagsSeen; 816 for my $tagName (sort keys %tags) { 817 # Avoid defining the same wrapper method twice. 818 my $JSInterfaceName = $tags{$tagName}{JSInterfaceName}; 819 next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName); 820 $tagsSeen{$JSInterfaceName} = 1; 821 822 my $conditional = $tags{$tagName}{conditional}; 823 if ($conditional) { 824 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 825 print F "#if ${conditionalString}\n\n"; 826 } 827 828 if ($wrapperFactoryType eq "JS") { 829 # Hack for the media tags 830 # FIXME: This should have been done via a CustomWrapper attribute and a separate *Custom file. 831 if ($tags{$tagName}{wrapperOnlyIfMediaIsAvailable}) { 832 print F <<END 833static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element) 834{ 835 if (!MediaPlayer::isAvailable()) 836 return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{namespace}Element, element.get()); 837 return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get()); 838} 839 840END 841; 842 } else { 843 print F <<END 844static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element) 845{ 846 return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get()); 847} 848 849END 850; 851 } 852 } elsif ($wrapperFactoryType eq "V8") { 853 print F <<END 854static v8::Handle<v8::Value> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element) 855{ 856 return toV8(static_cast<${JSInterfaceName}*>(element)); 857} 858 859END 860; 861 } 862 863 if ($conditional) { 864 print F "#endif\n\n"; 865 } 866 } 867} 868 869sub printWrapperFactoryCppFile 870{ 871 my $outputDir = shift; 872 my $wrapperFactoryType = shift; 873 my $wrapperFactoryFileName = shift; 874 my $F; 875 open F, ">" . $outputDir . "/" . $wrapperFactoryType . $wrapperFactoryFileName . ".cpp"; 876 877 printLicenseHeader($F); 878 879 print F "#include \"config.h\"\n\n"; 880 881 print F "#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith}; 882 883 print F "#include \"$wrapperFactoryType$parameters{namespace}ElementWrapperFactory.h\"\n"; 884 885 printJSElementIncludes($F, $wrapperFactoryType); 886 887 print F "\n#include \"$parameters{namespace}Names.h\"\n\n"; 888 889 printElementIncludes($F); 890 891 print F "\n#include <wtf/StdLibExtras.h>\n\n"; 892 893 if ($wrapperFactoryType eq "JS") { 894 print F <<END 895using namespace JSC; 896END 897; 898 } elsif ($wrapperFactoryType eq "V8") { 899 print F <<END 900#include "V8$parameters{namespace}Element.h" 901 902#include <v8.h> 903END 904; 905 } 906 907 print F <<END 908 909namespace WebCore { 910 911using namespace $parameters{namespace}Names; 912 913END 914; 915 if ($wrapperFactoryType eq "JS") { 916 print F <<END 917typedef JSNode* (*Create$parameters{namespace}ElementWrapperFunction)(ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>); 918 919END 920; 921 } elsif ($wrapperFactoryType eq "V8") { 922 print F <<END 923typedef v8::Handle<v8::Value> (*Create$parameters{namespace}ElementWrapperFunction)($parameters{namespace}Element*); 924 925END 926; 927 } 928 929 printWrapperFunctions($F, $wrapperFactoryType); 930 931 if ($wrapperFactoryType eq "JS") { 932 print F <<END 933JSNode* createJS$parameters{namespace}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element) 934{ 935 typedef HashMap<WebCore::AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction> FunctionMap; 936 DEFINE_STATIC_LOCAL(FunctionMap, map, ()); 937 if (map.isEmpty()) { 938END 939; 940 } elsif ($wrapperFactoryType eq "V8") { 941 print F <<END 942v8::Handle<v8::Value> createV8$parameters{namespace}Wrapper($parameters{namespace}Element* element, bool forceNewObject) 943{ 944 typedef HashMap<WebCore::AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction> FunctionMap; 945 DEFINE_STATIC_LOCAL(FunctionMap, map, ()); 946 if (map.isEmpty()) { 947END 948; 949 } 950 951 for my $tag (sort keys %tags) { 952 # Do not add the name to the map if it does not have a JS wrapper constructor or uses the default wrapper. 953 next if usesDefaultJSWrapper($tag, \%tags); 954 955 my $conditional = $tags{$tag}{conditional}; 956 if ($conditional) { 957 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 958 print F "#if ${conditionalString}\n"; 959 } 960 961 my $ucTag = $tags{$tag}{JSInterfaceName}; 962 print F " map.set(${tag}Tag.localName().impl(), create${ucTag}Wrapper);\n"; 963 964 if ($conditional) { 965 print F "#endif\n"; 966 } 967 } 968 969 print F <<END 970 } 971 Create$parameters{namespace}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl()); 972 if (createWrapperFunction) 973END 974; 975 if ($wrapperFactoryType eq "JS") { 976 print F <<END 977 return createWrapperFunction(exec, globalObject, element); 978 return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{namespace}Element, element.get()); 979END 980; 981 } elsif ($wrapperFactoryType eq "V8") { 982 print F <<END 983 return createWrapperFunction(element); 984 return V8$parameters{namespace}Element::wrap(element, forceNewObject); 985END 986; 987 } 988 print F <<END 989} 990 991} 992 993END 994; 995 996 print F "#endif\n" if $parameters{guardFactoryWith}; 997 998 close F; 999} 1000 1001sub printWrapperFactoryHeaderFile 1002{ 1003 my $outputDir = shift; 1004 my $wrapperFactoryType = shift; 1005 my $wrapperFactoryFileName = shift; 1006 my $F; 1007 open F, ">" . $outputDir . "/" . $wrapperFactoryType . $wrapperFactoryFileName . ".h"; 1008 1009 printLicenseHeader($F); 1010 1011 print F "#ifndef $wrapperFactoryType$parameters{namespace}ElementWrapperFactory_h\n"; 1012 print F "#define $wrapperFactoryType$parameters{namespace}ElementWrapperFactory_h\n\n"; 1013 1014 print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; 1015 1016 if ($wrapperFactoryType eq "JS") { 1017 print F <<END 1018#include <wtf/Forward.h> 1019 1020namespace JSC { 1021 class ExecState; 1022} 1023 1024namespace WebCore { 1025 1026 class JSNode; 1027 class JSDOMGlobalObject; 1028 class $parameters{namespace}Element; 1029 1030 JSNode* createJS$parameters{namespace}Wrapper(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>); 1031 1032} 1033 1034END 1035; 1036 } elsif ($wrapperFactoryType eq "V8") { 1037 print F <<END 1038#include <v8.h> 1039 1040namespace WebCore { 1041 1042 class $parameters{namespace}Element; 1043 1044 v8::Handle<v8::Value> createV8$parameters{namespace}Wrapper($parameters{namespace}Element*, bool); 1045} 1046END 1047; 1048 } 1049 1050 print F "#endif // $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith}; 1051 1052 print F "#endif // $wrapperFactoryType$parameters{namespace}ElementWrapperFactory_h\n"; 1053 1054 close F; 1055} 1056