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 (at] webkit.org> 5 # Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 6 # Copyright (C) 2011 Ericsson AB. All rights reserved. 7 # 8 # Redistribution and use in source and binary forms, with or without 9 # modification, are permitted provided that the following conditions 10 # are met: 11 # 12 # 1. Redistributions of source code must retain the above copyright 13 # notice, this list of conditions and the following disclaimer. 14 # 2. Redistributions in binary form must reproduce the above copyright 15 # notice, this list of conditions and the following disclaimer in the 16 # documentation and/or other materials provided with the distribution. 17 # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 18 # its contributors may be used to endorse or promote products derived 19 # from this software without specific prior written permission. 20 # 21 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 22 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 25 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 use strict; 33 34 use StaticString; 35 use Config; 36 use Getopt::Long; 37 use File::Path; 38 use File::Spec; 39 use IO::File; 40 use InFilesParser; 41 42 sub readTags($$); 43 sub readAttrs($$); 44 45 my $printFactory = 0; 46 my $fontNamesIn = ""; 47 my $resourceTypesIn = ""; 48 my $tagsFile = ""; 49 my $attrsFile = ""; 50 my $outputDir = "."; 51 my %parsedTags = (); 52 my %parsedAttrs = (); 53 my %enabledTags = (); 54 my %enabledAttrs = (); 55 my %allTags = (); 56 my %allAttrs = (); 57 my %allStrings = (); 58 my %parameters = (); 59 my $extraDefines = 0; 60 my $initDefaults = 1; 61 my %extensionAttrs = (); 62 63 require Config; 64 65 my $gccLocation = ""; 66 if ($ENV{CC}) { 67 $gccLocation = $ENV{CC}; 68 } elsif (($Config::Config{'osname'}) =~ /solaris/i) { 69 $gccLocation = "/usr/sfw/bin/gcc"; 70 } else { 71 $gccLocation = "/usr/bin/gcc"; 72 } 73 my $preprocessor = $gccLocation . " -E -x c++"; 74 75 GetOptions( 76 'tags=s' => \$tagsFile, 77 'attrs=s' => \$attrsFile, 78 'factory' => \$printFactory, 79 'outputDir=s' => \$outputDir, 80 'extraDefines=s' => \$extraDefines, 81 'preprocessor=s' => \$preprocessor, 82 'fonts=s' => \$fontNamesIn, 83 'resourceTypes=s' => \$resourceTypesIn 84 ); 85 86 mkpath($outputDir); 87 88 if (length($fontNamesIn)) { 89 my $familyNamesFileBase = "FontFamily"; 90 my $familyNamesPrefix = "CSS"; 91 createGenericNamesFile($fontNamesIn, $familyNamesFileBase, $familyNamesPrefix); 92 } 93 94 if (length($resourceTypesIn)) { 95 my $baseName = "FetchInitiatorType"; 96 my $basePrefix = "Loader_Cache"; 97 createGenericNamesFile($resourceTypesIn, $baseName, $basePrefix); 98 } 99 100 die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile)); 101 102 if (length($tagsFile)) { 103 %allTags = %{readTags($tagsFile, 0)}; 104 %enabledTags = %{readTags($tagsFile, 1)}; 105 namesToStrings(\%allTags, \%allStrings); 106 } 107 108 if (length($attrsFile)) { 109 %allAttrs = %{readAttrs($attrsFile, 0)}; 110 %enabledAttrs = %{readAttrs($attrsFile, 1)}; 111 namesToStrings(\%allAttrs, \%allStrings); 112 } 113 114 die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $parameters{namespace}; 115 die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $parameters{namespaceURI}; 116 117 $parameters{namespacePrefix} = $parameters{namespace} unless $parameters{namespacePrefix}; 118 $parameters{fallbackJSInterfaceName} = $parameters{fallbackInterfaceName} unless $parameters{fallbackJSInterfaceName}; 119 120 my $namesBasePath = "$outputDir/$parameters{namespace}Names"; 121 my $factoryBasePath = "$outputDir/$parameters{namespace}ElementFactory"; 122 my $wrapperFactoryFileName = "$parameters{namespace}ElementWrapperFactory"; 123 124 printNamesHeaderFile("$namesBasePath.h"); 125 printNamesCppFile("$namesBasePath.cpp"); 126 127 if ($printFactory) { 128 printFactoryCppFile("$factoryBasePath.cpp"); 129 printFactoryHeaderFile("$factoryBasePath.h"); 130 } 131 132 printWrapperFactoryCppFile($outputDir, $wrapperFactoryFileName); 133 printWrapperFactoryHeaderFile($outputDir, $wrapperFactoryFileName); 134 135 ### Hash initialization 136 137 sub defaultTagPropertyHash 138 { 139 return ( 140 'constructorNeedsCreatedByParser' => 0, 141 'constructorNeedsFormElement' => 0, 142 'noConstructor' => 0, 143 'interfaceName' => defaultInterfaceName($_[0]), 144 # By default, the JSInterfaceName is the same as the interfaceName. 145 'JSInterfaceName' => defaultInterfaceName($_[0]), 146 'mapToTagName' => '', 147 'wrapperOnlyIfMediaIsAvailable' => 0, 148 'conditional' => 0, 149 'contextConditional' => 0, 150 'runtimeConditional' => 0 151 ); 152 } 153 154 sub defaultParametersHash 155 { 156 return ( 157 'namespace' => '', 158 'namespacePrefix' => '', 159 'namespaceURI' => '', 160 'guardFactoryWith' => '', 161 'tagsNullNamespace' => 0, 162 'attrsNullNamespace' => 0, 163 'fallbackInterfaceName' => '', 164 'fallbackJSInterfaceName' => '' 165 ); 166 } 167 168 sub defaultInterfaceName 169 { 170 die "No namespace found" if !$parameters{namespace}; 171 return $parameters{namespace} . upperCaseName($_[0]) . "Element" 172 } 173 174 ### Parsing handlers 175 176 sub valueForName 177 { 178 my $name = shift; 179 my $value = $extensionAttrs{$name}; 180 181 if (!$value) { 182 $value = $name; 183 $value =~ s/_/-/g; 184 } 185 186 return $value; 187 } 188 189 sub namesToStrings 190 { 191 my $namesRef = shift; 192 my $stringsRef = shift; 193 194 my %names = %$namesRef; 195 196 for my $name (keys %names) { 197 $stringsRef->{$name} = valueForName($name); 198 } 199 } 200 201 sub tagsHandler 202 { 203 my ($tag, $property, $value) = @_; 204 205 $tag =~ s/-/_/g; 206 207 # Initialize default property values. 208 $parsedTags{$tag} = { defaultTagPropertyHash($tag) } if !defined($parsedTags{$tag}); 209 210 if ($property) { 211 die "Unknown property $property for tag $tag\n" if !defined($parsedTags{$tag}{$property}); 212 213 # The code relies on JSInterfaceName deriving from interfaceName to check for custom JSInterfaceName. 214 # So override JSInterfaceName if it was not already set. 215 $parsedTags{$tag}{JSInterfaceName} = $value if $property eq "interfaceName" && $parsedTags{$tag}{JSInterfaceName} eq $parsedTags{$tag}{interfaceName}; 216 217 $parsedTags{$tag}{$property} = $value; 218 } 219 } 220 221 sub attrsHandler 222 { 223 my ($attr, $property, $value) = @_; 224 # Translate HTML5 extension attributes of the form 'x-webkit-feature' to 'webkitfeature'. 225 # We don't just check for the 'x-' prefix because there are attributes such as x-height 226 # which should follow the default path below. 227 if ($attr =~ m/^x-webkit-(.*)/) { 228 my $newAttr = "webkit$1"; 229 $extensionAttrs{$newAttr} = $attr; 230 $attr = $newAttr; 231 } 232 $attr =~ s/-/_/g; 233 234 # Initialize default properties' values. 235 $parsedAttrs{$attr} = {} if !defined($parsedAttrs{$attr}); 236 237 if ($property) { 238 die "Unknown property $property for attribute $attr\n" if !defined($parsedAttrs{$attr}{$property}); 239 $parsedAttrs{$attr}{$property} = $value; 240 } 241 } 242 243 sub parametersHandler 244 { 245 my ($parameter, $value) = @_; 246 247 # Initialize default properties' values. 248 %parameters = defaultParametersHash() if (!(keys %parameters) && $initDefaults); 249 250 # If the input is an array, we want the strings to have the same value as the key. 251 if ( $value eq 1) { 252 $value = $parameter; 253 } 254 255 die "Unknown parameter $parameter for tags/attrs\n" if (!defined($parameters{$parameter}) && $initDefaults); 256 $parameters{$parameter} = $value; 257 } 258 259 ## Support routines 260 261 sub preprocessorCommand() 262 { 263 return $preprocessor if $extraDefines eq 0; 264 return $preprocessor . " -D" . join(" -D", split(" ", $extraDefines)); 265 } 266 267 sub readNames($$$$) 268 { 269 my ($namesFile, $hashToFillRef, $handler, $usePreprocessor) = @_; 270 271 my $names = new IO::File; 272 if ($usePreprocessor) { 273 open($names, preprocessorCommand() . " " . $namesFile . "|") or die "Failed to open file: $namesFile"; 274 } else { 275 open($names, $namesFile) or die "Failed to open file: $namesFile"; 276 } 277 278 my $InParser = InFilesParser->new(); 279 $InParser->parse($names, \¶metersHandler, $handler); 280 281 close($names); 282 die "Failed to read names from file: $namesFile" if (keys %{$hashToFillRef} == 0); 283 return $hashToFillRef; 284 } 285 286 sub readAttrs($$) 287 { 288 my ($namesFile, $usePreprocessor) = @_; 289 %parsedAttrs = (); 290 return readNames($namesFile, \%parsedAttrs, \&attrsHandler, $usePreprocessor); 291 } 292 293 sub readTags($$) 294 { 295 my ($namesFile, $usePreprocessor) = @_; 296 %parsedTags = (); 297 return readNames($namesFile, \%parsedTags, \&tagsHandler, $usePreprocessor); 298 } 299 300 sub printMacros 301 { 302 my ($F, $macro, $suffix, $namesRef) = @_; 303 my %names = %$namesRef; 304 305 for my $name (sort keys %names) { 306 print F "$macro $name","$suffix;\n"; 307 } 308 } 309 310 sub usesDefaultWrapper 311 { 312 my $tagName = shift; 313 return $tagName eq $parameters{namespace} . "Element"; 314 } 315 316 # Build a direct mapping from the tags to the Element to create. 317 sub buildConstructorMap 318 { 319 my %tagConstructorMap = (); 320 for my $tagName (keys %enabledTags) { 321 my $interfaceName = $enabledTags{$tagName}{interfaceName}; 322 323 if ($enabledTags{$tagName}{mapToTagName}) { 324 die "Cannot handle multiple mapToTagName for $tagName\n" if $enabledTags{$enabledTags{$tagName}{mapToTagName}}{mapToTagName}; 325 $interfaceName = $enabledTags{ $enabledTags{$tagName}{mapToTagName} }{interfaceName}; 326 } 327 328 # Chop the string to keep the interesting part. 329 $interfaceName =~ s/$parameters{namespace}(.*)Element/$1/; 330 $tagConstructorMap{$tagName} = lc($interfaceName); 331 } 332 333 return %tagConstructorMap; 334 } 335 336 # Helper method that print the constructor's signature avoiding 337 # unneeded arguments. 338 sub printConstructorSignature 339 { 340 my ($F, $tagName, $constructorName, $constructorTagName) = @_; 341 342 print F "static PassRefPtr<$parameters{namespace}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document* document"; 343 if ($parameters{namespace} eq "HTML") { 344 print F ", HTMLFormElement*"; 345 print F " formElement" if $enabledTags{$tagName}{constructorNeedsFormElement}; 346 } 347 print F ", bool"; 348 print F " createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser}; 349 print F ")\n{\n"; 350 } 351 352 # Helper method to dump the constructor interior and call the 353 # Element constructor with the right arguments. 354 # The variable names should be kept in sync with the previous method. 355 sub printConstructorInterior 356 { 357 my ($F, $tagName, $interfaceName, $constructorTagName) = @_; 358 359 # Handle media elements. 360 if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) { 361 print F <<END 362 Settings* settings = document->settings(); 363 if (!RuntimeEnabledFeatures::mediaEnabled() || (settings && !settings->mediaEnabled())) 364 return 0; 365 366 END 367 ; 368 } 369 370 my $contextConditional = $enabledTags{$tagName}{contextConditional}; 371 if ($contextConditional) { 372 print F <<END 373 if (!ContextFeatures::${contextConditional}Enabled(document)) 374 return 0; 375 END 376 ; 377 } 378 379 my $runtimeConditional = $enabledTags{$tagName}{runtimeConditional}; 380 if ($runtimeConditional) { 381 print F <<END 382 if (!RuntimeEnabledFeatures::${runtimeConditional}Enabled()) 383 return 0; 384 END 385 ; 386 } 387 388 # Call the constructor with the right parameters. 389 print F " return ${interfaceName}::create($constructorTagName, document"; 390 print F ", formElement" if $enabledTags{$tagName}{constructorNeedsFormElement}; 391 print F ", createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser}; 392 print F ");\n}\n\n"; 393 } 394 395 sub printConstructors 396 { 397 my ($F, $tagConstructorMapRef) = @_; 398 my %tagConstructorMap = %$tagConstructorMapRef; 399 400 # This is to avoid generating the same constructor several times. 401 my %uniqueTags = (); 402 for my $tagName (sort keys %tagConstructorMap) { 403 my $interfaceName = $enabledTags{$tagName}{interfaceName}; 404 405 # Ignore the mapped tag 406 # FIXME: It could be moved inside this loop but was split for readibility. 407 next if (defined($uniqueTags{$interfaceName}) || $enabledTags{$tagName}{mapToTagName}); 408 # Tags can have wrappers without constructors. 409 # This is useful to make user-agent shadow elements internally testable 410 # while keeping them from being avaialble in the HTML markup. 411 next if $enabledTags{$tagName}{noConstructor}; 412 413 $uniqueTags{$interfaceName} = '1'; 414 415 my $conditional = $enabledTags{$tagName}{conditional}; 416 if ($conditional) { 417 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 418 print F "#if ${conditionalString}\n\n"; 419 } 420 421 printConstructorSignature($F, $tagName, $tagConstructorMap{$tagName}, "tagName"); 422 printConstructorInterior($F, $tagName, $interfaceName, "tagName"); 423 424 if ($conditional) { 425 print F "#endif\n"; 426 } 427 } 428 429 # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname. 430 for my $tagName (sort keys %tagConstructorMap) { 431 if ($enabledTags{$tagName}{mapToTagName}) { 432 my $mappedName = $enabledTags{$tagName}{mapToTagName}; 433 printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName"); 434 printConstructorInterior($F, $mappedName, $enabledTags{$mappedName}{interfaceName}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())"); 435 } 436 } 437 } 438 439 sub printFunctionInits 440 { 441 my ($F, $tagConstructorMap) = @_; 442 my %tagConstructorMap = %$tagConstructorMap; 443 444 for my $tagName (sort keys %tagConstructorMap) { 445 next if $enabledTags{$tagName}{noConstructor}; 446 447 my $conditional = $enabledTags{$tagName}{conditional}; 448 if ($conditional) { 449 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 450 print F "#if ${conditionalString}\n"; 451 } 452 453 if ($enabledTags{$tagName}{mapToTagName}) { 454 print F " addTag(${tagName}Tag, $enabledTags{$tagName}{mapToTagName}To${tagName}Constructor);\n"; 455 } else { 456 print F " addTag(${tagName}Tag, $tagConstructorMap{$tagName}Constructor);\n"; 457 } 458 459 if ($conditional) { 460 print F "#endif\n\n"; 461 } 462 } 463 } 464 465 sub svgCapitalizationHacks 466 { 467 my $name = shift; 468 469 $name = "FE" . ucfirst $1 if $name =~ /^fe(.+)$/; 470 471 return $name; 472 } 473 474 sub upperCaseName 475 { 476 my $name = shift; 477 478 $name = svgCapitalizationHacks($name) if ($parameters{namespace} eq "SVG"); 479 480 while ($name =~ /^(.*?)_(.*)/) { 481 $name = $1 . ucfirst $2; 482 } 483 484 return ucfirst $name; 485 } 486 487 sub printHeaderHead 488 { 489 my ($F, $prefix, $nsName, $includes) = @_; 490 491 print F "#ifndef ${prefix}_${nsName}Names_h\n"; 492 print F "#define ${prefix}_${nsName}Names_h\n\n"; 493 print F "$includes\n\n"; 494 495 print F "namespace WebCore {\n\n"; 496 print F "namespace ${nsName}Names {\n\n"; 497 498 print F "#ifndef ${prefix}_${nsName}NAMES_HIDE_GLOBALS\n"; 499 } 500 501 sub printCppHead 502 { 503 my ($F, $prefix, $nsName, $usedNamespace) = @_; 504 505 print F "#include \"config.h\"\n\n"; 506 print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n"; 507 print F "#define ${prefix}_${nsName}NAMES_HIDE_GLOBALS 1\n"; 508 print F "#else\n"; 509 print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n"; 510 print F "#endif\n\n"; 511 512 print F "#include \"${nsName}Names.h\"\n\n"; 513 print F "#include \"wtf/StaticConstructors.h\"\n"; 514 515 print F "namespace WebCore {\n\n"; 516 print F "namespace ${nsName}Names {\n\n"; 517 print F "using namespace $usedNamespace;\n\n"; 518 } 519 520 sub printInit 521 { 522 my ($F, $isDefinition) = @_; 523 524 if ($isDefinition) { 525 print F "\nvoid init();\n\n"; 526 print F "} }\n\n"; 527 print F "#endif\n\n"; 528 return; 529 } 530 531 print F "\nvoid init() 532 { 533 // Use placement new to initialize the globals. 534 535 "; 536 } 537 538 sub printLicenseHeader 539 { 540 my $F = shift; 541 print F "/* 542 * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. 543 * 544 * This file was generated by the core/scripts/make_names.pl script. 545 * 546 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 547 * 548 * Redistribution and use in source and binary forms, with or without 549 * modification, are permitted provided that the following conditions 550 * are met: 551 * 1. Redistributions of source code must retain the above copyright 552 * notice, this list of conditions and the following disclaimer. 553 * 2. Redistributions in binary form must reproduce the above copyright 554 * notice, this list of conditions and the following disclaimer in the 555 * documentation and/or other materials provided with the distribution. 556 * 557 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 558 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 559 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 560 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 561 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 562 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 563 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 564 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 565 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 566 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 567 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 568 */ 569 570 "; 571 } 572 573 sub printNamesHeaderFile 574 { 575 my ($headerPath) = shift; 576 my $F; 577 open F, ">$headerPath"; 578 579 printLicenseHeader($F); 580 printHeaderHead($F, "DOM", $parameters{namespace}, "#include \"core/dom/QualifiedName.h\""); 581 582 my $lowerNamespace = lc($parameters{namespacePrefix}); 583 print F "// Namespace\n"; 584 print F "extern const WTF::AtomicString ${lowerNamespace}NamespaceURI;\n\n"; 585 586 if (keys %allTags) { 587 print F "// Tags\n"; 588 printMacros($F, "extern const WebCore::QualifiedName", "Tag", \%allTags); 589 } 590 591 if (keys %allAttrs) { 592 print F "// Attributes\n"; 593 printMacros($F, "extern const WebCore::QualifiedName", "Attr", \%allAttrs); 594 } 595 print F "#endif\n\n"; 596 597 if (keys %allTags) { 598 print F "const unsigned $parameters{namespace}TagsCount = ", scalar(keys %allTags), ";\n"; 599 print F "WebCore::QualifiedName** get$parameters{namespace}Tags();\n"; 600 } 601 602 if (keys %allAttrs) { 603 print F "const unsigned $parameters{namespace}AttrsCount = ", scalar(keys %allAttrs), ";\n"; 604 print F "WebCore::QualifiedName** get$parameters{namespace}Attrs();\n"; 605 } 606 607 printInit($F, 1); 608 close F; 609 } 610 611 sub printNamesCppFile 612 { 613 my $cppPath = shift; 614 my $F; 615 open F, ">$cppPath"; 616 617 printLicenseHeader($F); 618 printCppHead($F, "DOM", $parameters{namespace}, "WebCore"); 619 620 my $lowerNamespace = lc($parameters{namespacePrefix}); 621 622 print F "DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI)\n\n"; 623 624 if (keys %allTags) { 625 print F "// Tags\n"; 626 for my $name (sort keys %allTags) { 627 print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Tag)\n"; 628 } 629 630 print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Tags()\n"; 631 print F "{\n static WebCore::QualifiedName* $parameters{namespace}Tags[] = {\n"; 632 for my $name (sort keys %allTags) { 633 print F " (WebCore::QualifiedName*)&${name}Tag,\n"; 634 } 635 print F " };\n"; 636 print F " return $parameters{namespace}Tags;\n"; 637 print F "}\n"; 638 } 639 640 if (keys %allAttrs) { 641 print F "\n// Attributes\n"; 642 for my $name (sort keys %allAttrs) { 643 print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Attr)\n"; 644 } 645 print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Attrs()\n"; 646 print F "{\n static WebCore::QualifiedName* $parameters{namespace}Attr[] = {\n"; 647 for my $name (sort keys %allAttrs) { 648 print F " (WebCore::QualifiedName*)&${name}Attr,\n"; 649 } 650 print F " };\n"; 651 print F " return $parameters{namespace}Attr;\n"; 652 print F "}\n"; 653 } 654 655 printInit($F, 0); 656 657 print(F " AtomicString ${lowerNamespace}NS(\"$parameters{namespaceURI}\", AtomicString::ConstructFromLiteral);\n\n"); 658 659 print(F " // Namespace\n"); 660 print(F " new ((void*)&${lowerNamespace}NamespaceURI) AtomicString(${lowerNamespace}NS);\n"); 661 print(F "\n"); 662 print F StaticString::GenerateStringImpls(\%allStrings); 663 664 if (keys %allTags) { 665 my $tagsNamespace = $parameters{tagsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS"; 666 printDefinitions($F, \%allTags, "tags", $tagsNamespace); 667 } 668 if (keys %allAttrs) { 669 my $attrsNamespace = $parameters{attrsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS"; 670 printDefinitions($F, \%allAttrs, "attributes", $attrsNamespace); 671 } 672 673 print F "}\n\n} }\n\n"; 674 close F; 675 } 676 677 sub printJSElementIncludes 678 { 679 my $F = shift; 680 681 my %tagsSeen; 682 for my $tagName (sort keys %enabledTags) { 683 my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName}; 684 next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName); 685 if ($enabledTags{$tagName}{conditional}) { 686 # We skip feature-define-specific #includes here since we handle them separately. 687 next; 688 } 689 $tagsSeen{$JSInterfaceName} = 1; 690 691 print F "#include \"V8${JSInterfaceName}.h\"\n"; 692 } 693 print F "#include \"V8$parameters{fallbackJSInterfaceName}.h\"\n"; 694 } 695 696 sub printElementIncludes 697 { 698 my $F = shift; 699 700 my %tagsSeen; 701 for my $tagName (sort keys %enabledTags) { 702 my $interfaceName = $enabledTags{$tagName}{interfaceName}; 703 next if defined($tagsSeen{$interfaceName}); 704 if ($enabledTags{$tagName}{conditional}) { 705 # We skip feature-define-specific #includes here since we handle them separately. 706 next; 707 } 708 $tagsSeen{$interfaceName} = 1; 709 710 print F "#include \"${interfaceName}.h\"\n"; 711 } 712 print F "#include \"$parameters{fallbackInterfaceName}.h\"\n"; 713 } 714 715 sub printConditionalElementIncludes 716 { 717 my ($F, $shouldIncludeV8Headers) = @_; 718 719 my %conditionals; 720 my %unconditionalElementIncludes; 721 my %unconditionalJSElementIncludes; 722 723 for my $tagName (keys %enabledTags) { 724 my $conditional = $enabledTags{$tagName}{conditional}; 725 my $interfaceName = $enabledTags{$tagName}{interfaceName}; 726 my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName}; 727 728 if ($conditional) { 729 $conditionals{$conditional}{interfaceNames}{$interfaceName} = 1; 730 $conditionals{$conditional}{JSInterfaceNames}{$JSInterfaceName} = 1; 731 } else { 732 $unconditionalElementIncludes{$interfaceName} = 1; 733 $unconditionalJSElementIncludes{$JSInterfaceName} = 1; 734 } 735 } 736 737 for my $conditional (sort keys %conditionals) { 738 print F "\n#if ENABLE($conditional)\n"; 739 for my $interfaceName (sort keys %{$conditionals{$conditional}{interfaceNames}}) { 740 next if $unconditionalElementIncludes{$interfaceName}; 741 print F "#include \"$interfaceName.h\"\n"; 742 } 743 if ($shouldIncludeV8Headers) { 744 for my $JSInterfaceName (sort keys %{$conditionals{$conditional}{JSInterfaceNames}}) { 745 next if $unconditionalJSElementIncludes{$JSInterfaceName}; 746 print F "#include \"V8$JSInterfaceName.h\"\n"; 747 } 748 } 749 print F "#endif\n"; 750 } 751 } 752 753 sub printDefinitions 754 { 755 my ($F, $namesRef, $type, $namespaceURI) = @_; 756 my $singularType = substr($type, 0, -1); 757 my $shortType = substr($singularType, 0, 4); 758 my $shortCamelType = ucfirst($shortType); 759 my $shortUpperType = uc($shortType); 760 761 print F " // " . ucfirst($type) . "\n"; 762 763 for my $name (sort keys %$namesRef) { 764 # To generate less code in init(), the common case of nullAtom for the namespace, we call createQualifiedName() without passing $namespaceURI. 765 if ($namespaceURI eq "nullAtom") { 766 print F " createQualifiedName((void*)&$name","${shortCamelType}, ${name}Impl);\n"; 767 } else { 768 print F " createQualifiedName((void*)&$name","${shortCamelType}, ${name}Impl, $namespaceURI);\n"; 769 } 770 } 771 } 772 773 ## ElementFactory routines 774 775 sub printFactoryCppFile 776 { 777 my $cppPath = shift; 778 my $F; 779 open F, ">$cppPath"; 780 781 printLicenseHeader($F); 782 783 print F <<END 784 #include "config.h" 785 END 786 ; 787 788 print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith}; 789 790 print F <<END 791 #include "$parameters{namespace}ElementFactory.h" 792 #include "$parameters{namespace}Names.h" 793 END 794 ; 795 796 printElementIncludes($F); 797 798 print F "\n#include <wtf/HashMap.h>\n"; 799 800 printConditionalElementIncludes($F); 801 802 print F <<END 803 804 #include "ContextFeatures.h" 805 #include "CustomElement.h" 806 #include "Document.h" 807 #include "RuntimeEnabledFeatures.h" 808 #include "Settings.h" 809 810 namespace WebCore { 811 812 using namespace $parameters{namespace}Names; 813 814 END 815 ; 816 817 print F "typedef PassRefPtr<$parameters{namespace}Element> (*ConstructorFunction)(const QualifiedName&, Document*"; 818 print F ", HTMLFormElement*" if $parameters{namespace} eq "HTML"; 819 print F ", bool createdByParser);\n"; 820 print F <<END 821 typedef HashMap<StringImpl*, ConstructorFunction> FunctionMap; 822 823 static FunctionMap* gFunctionMap = 0; 824 825 END 826 ; 827 828 my %tagConstructorMap = buildConstructorMap(); 829 830 printConstructors($F, \%tagConstructorMap); 831 832 print F <<END 833 static void addTag(const QualifiedName& tag, ConstructorFunction func) 834 { 835 gFunctionMap->set(tag.localName().impl(), func); 836 } 837 838 static void createFunctionMap() 839 { 840 ASSERT(!gFunctionMap); 841 842 // Create the table. 843 gFunctionMap = new FunctionMap; 844 845 // Populate it with constructor functions. 846 END 847 ; 848 849 printFunctionInits($F, \%tagConstructorMap); 850 851 print F "}\n"; 852 853 854 print F "\nPassRefPtr<$parameters{namespace}Element> $parameters{namespace}ElementFactory::create$parameters{namespace}Element(const QualifiedName& qName, Document* document"; 855 print F ", HTMLFormElement* formElement" if $parameters{namespace} eq "HTML"; 856 print F ", bool createdByParser)\n{\n"; 857 858 print F <<END 859 if (!document) 860 return 0; 861 862 if (CustomElement::isValidName(qName.localName()) && document->registrationContext()) { 863 RefPtr<Element> element = document->registrationContext()->createCustomTagElement(document, qName); 864 ASSERT_WITH_SECURITY_IMPLICATION(element->is$parameters{namespace}Element()); 865 return static_pointer_cast<$parameters{namespace}Element>(element.release()); 866 } 867 868 if (!gFunctionMap) 869 createFunctionMap(); 870 if (ConstructorFunction function = gFunctionMap->get(qName.localName().impl())) { 871 END 872 ; 873 874 if ($parameters{namespace} eq "HTML") { 875 print F " if (PassRefPtr<$parameters{namespace}Element> element = function(qName, document, formElement, createdByParser))\n"; 876 print F " return element;\n"; 877 } else { 878 print F " if (PassRefPtr<$parameters{namespace}Element> element = function(qName, document, createdByParser))\n"; 879 print F " return element;\n"; 880 } 881 print F <<END 882 } 883 884 return $parameters{fallbackInterfaceName}::create(qName, document); 885 } 886 887 } // namespace WebCore 888 889 END 890 ; 891 892 print F "#endif\n" if $parameters{guardFactoryWith}; 893 894 close F; 895 } 896 897 sub printFactoryHeaderFile 898 { 899 my $headerPath = shift; 900 my $F; 901 open F, ">$headerPath"; 902 903 printLicenseHeader($F); 904 905 print F<<END 906 #ifndef $parameters{namespace}ElementFactory_h 907 #define $parameters{namespace}ElementFactory_h 908 909 #include <wtf/Forward.h> 910 #include <wtf/PassRefPtr.h> 911 912 namespace WebCore { 913 class Element; 914 class Document; 915 class QualifiedName; 916 } 917 918 namespace WebCore { 919 920 class $parameters{namespace}Element; 921 END 922 ; 923 924 print F " class HTMLFormElement;\n" if $parameters{namespace} eq "HTML"; 925 926 print F<<END 927 // The idea behind this class is that there will eventually be a mapping from namespace URIs to ElementFactories that can dispense 928 // elements. In a compound document world, the generic createElement function (will end up being virtual) will be called. 929 class $parameters{namespace}ElementFactory { 930 public: 931 PassRefPtr<Element> createElement(const WebCore::QualifiedName&, WebCore::Document*, bool createdByParser = true); 932 END 933 ; 934 print F " static PassRefPtr<$parameters{namespace}Element> create$parameters{namespace}Element(const WebCore::QualifiedName&, WebCore::Document*"; 935 print F ", HTMLFormElement* = 0" if $parameters{namespace} eq "HTML"; 936 print F ", bool createdByParser = true);\n"; 937 938 printf F<<END 939 }; 940 } 941 942 #endif // $parameters{namespace}ElementFactory_h 943 944 END 945 ; 946 947 close F; 948 } 949 950 ## Wrapper Factory routines 951 952 sub usesDefaultJSWrapper 953 { 954 my $name = shift; 955 956 # A tag reuses the default wrapper if its JSInterfaceName matches the default namespace Element. 957 return $enabledTags{$name}{JSInterfaceName} eq $parameters{namespace} . "Element"; 958 } 959 960 sub printWrapperFunctions 961 { 962 my $F = shift; 963 964 my %tagsSeen; 965 for my $tagName (sort keys %enabledTags) { 966 # Avoid defining the same wrapper method twice. 967 my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName}; 968 next if defined($tagsSeen{$JSInterfaceName}) || (usesDefaultJSWrapper($tagName) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element")); 969 $tagsSeen{$JSInterfaceName} = 1; 970 971 my $conditional = $enabledTags{$tagName}{conditional}; 972 if ($conditional) { 973 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 974 print F "#if ${conditionalString}\n\n"; 975 } 976 977 if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) { 978 print F <<END 979 static v8::Handle<v8::Object> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 980 { 981 Settings* settings = element->document()->settings(); 982 if (!RuntimeEnabledFeatures::mediaEnabled() || (settings && !settings->mediaEnabled())) 983 return createV8$parameters{namespace}DirectWrapper(element, creationContext, isolate); 984 return wrap(static_cast<${JSInterfaceName}*>(element), creationContext, isolate); 985 } 986 987 END 988 ; 989 } elsif ($enabledTags{$tagName}{contextConditional}) { 990 my $contextConditional = $enabledTags{$tagName}{contextConditional}; 991 print F <<END 992 static v8::Handle<v8::Object> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 993 { 994 if (!ContextFeatures::${contextConditional}Enabled(element->document())) 995 return createV8$parameters{namespace}FallbackWrapper(to$parameters{fallbackInterfaceName}(element), creationContext, isolate); 996 return wrap(static_cast<${JSInterfaceName}*>(element), creationContext, isolate); 997 } 998 END 999 ; 1000 } elsif ($enabledTags{$tagName}{runtimeConditional}) { 1001 my $runtimeConditional = $enabledTags{$tagName}{runtimeConditional}; 1002 print F <<END 1003 static v8::Handle<v8::Object> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 1004 { 1005 if (!RuntimeEnabledFeatures::${runtimeConditional}Enabled()) 1006 return createV8$parameters{namespace}FallbackWrapper(to$parameters{fallbackInterfaceName}(element), creationContext, isolate); 1007 return wrap(static_cast<${JSInterfaceName}*>(element), creationContext, isolate); 1008 } 1009 END 1010 ; 1011 } elsif (${JSInterfaceName} eq "HTMLElement") { 1012 print F <<END 1013 static v8::Handle<v8::Object> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 1014 { 1015 ASSERT_NOT_REACHED(); 1016 return v8::Handle<v8::Object>(); 1017 } 1018 1019 END 1020 ; 1021 } else { 1022 print F <<END 1023 static v8::Handle<v8::Object> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 1024 { 1025 return wrap(static_cast<${JSInterfaceName}*>(element), creationContext, isolate); 1026 } 1027 1028 1029 END 1030 ; 1031 } 1032 1033 if ($conditional) { 1034 print F "#endif\n\n"; 1035 } 1036 } 1037 } 1038 1039 sub printWrapperFactoryCppFile 1040 { 1041 my $outputDir = shift; 1042 my $wrapperFactoryFileName = shift; 1043 my $F; 1044 open F, ">" . $outputDir . "/V8" . $wrapperFactoryFileName . ".cpp"; 1045 1046 printLicenseHeader($F); 1047 1048 print F "#include \"config.h\"\n"; 1049 print F "#include \"V8$parameters{namespace}ElementWrapperFactory.h\"\n"; 1050 1051 print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith}; 1052 1053 printJSElementIncludes($F); 1054 1055 print F "\n#include \"$parameters{namespace}Names.h\"\n\n"; 1056 1057 printElementIncludes($F); 1058 1059 print F "\n#include <wtf/StdLibExtras.h>\n"; 1060 1061 printConditionalElementIncludes($F, 1); 1062 1063 print F <<END 1064 1065 #include "ContextFeatures.h" 1066 #include "Document.h" 1067 #include "RuntimeEnabledFeatures.h" 1068 #include "Settings.h" 1069 1070 #include "V8$parameters{namespace}Element.h" 1071 1072 #include "bindings/v8/CustomElementWrapper.h" 1073 1074 #include <v8.h> 1075 1076 namespace WebCore { 1077 1078 using namespace $parameters{namespace}Names; 1079 1080 typedef v8::Handle<v8::Object> (*Create$parameters{namespace}ElementWrapperFunction)($parameters{namespace}Element*, v8::Handle<v8::Object> creationContext, v8::Isolate*); 1081 1082 END 1083 ; 1084 1085 printWrapperFunctions($F); 1086 1087 print F <<END 1088 v8::Handle<v8::Object> createV8$parameters{namespace}Wrapper($parameters{namespace}Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 1089 { 1090 typedef HashMap<WTF::StringImpl*, Create$parameters{namespace}ElementWrapperFunction> FunctionMap; 1091 DEFINE_STATIC_LOCAL(FunctionMap, map, ()); 1092 if (map.isEmpty()) { 1093 END 1094 ; 1095 1096 for my $tag (sort keys %enabledTags) { 1097 # Do not add the name to the map if it does not have a JS wrapper constructor or uses the default wrapper. 1098 next if (usesDefaultJSWrapper($tag, \%enabledTags) && ($parameters{fallbackJSInterfaceName} eq $parameters{namespace} . "Element")); 1099 1100 my $conditional = $enabledTags{$tag}{conditional}; 1101 if ($conditional) { 1102 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 1103 print F "#if ${conditionalString}\n"; 1104 } 1105 1106 my $ucTag = $enabledTags{$tag}{JSInterfaceName}; 1107 print F " map.set(${tag}Tag.localName().impl(), create${ucTag}Wrapper);\n"; 1108 1109 if ($conditional) { 1110 print F "#endif\n"; 1111 } 1112 } 1113 1114 print F <<END 1115 } 1116 1117 Create$parameters{namespace}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl()); 1118 END 1119 ; 1120 if ($parameters{namespace} eq "HTML") { 1121 print F <<END 1122 if (createWrapperFunction == createHTMLElementWrapper) 1123 createWrapperFunction = createV8HTMLDirectWrapper; 1124 END 1125 ; 1126 } 1127 print F <<END 1128 if (element->isCustomElement()) 1129 return CustomElementWrapper<$parameters{namespace}Element, V8$parameters{namespace}Element>::wrap(element, creationContext, isolate, createWrapperFunction); 1130 1131 if (createWrapperFunction) 1132 return createWrapperFunction(element, creationContext, isolate); 1133 END 1134 ; 1135 if ($parameters{namespace} eq "SVG") { 1136 print F <<END 1137 return V8SVGElement::createWrapper(element, creationContext, isolate); 1138 END 1139 ; 1140 } else { 1141 print F <<END 1142 return wrap(to$parameters{fallbackInterfaceName}(element), creationContext, isolate); 1143 END 1144 ; 1145 } 1146 print F <<END 1147 } 1148 1149 const QualifiedName* find$parameters{namespace}TagNameOfV8Type(const WrapperTypeInfo* type) 1150 { 1151 typedef HashMap<const WrapperTypeInfo*, const QualifiedName*> TypeNameMap; 1152 DEFINE_STATIC_LOCAL(TypeNameMap, map, ()); 1153 if (map.isEmpty()) { 1154 END 1155 ; 1156 1157 for my $tagName (sort keys %enabledTags) { 1158 if (!usesDefaultJSWrapper($tagName)) { 1159 my $conditional = $enabledTags{$tagName}{conditional}; 1160 if ($conditional) { 1161 my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; 1162 print F "#if ${conditionalString}\n"; 1163 } 1164 1165 my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName}; 1166 print F " map.set(WrapperTypeTraits<${JSInterfaceName}>::info(), &${tagName}Tag);\n"; 1167 1168 if ($conditional) { 1169 print F "#endif\n"; 1170 } 1171 } 1172 } 1173 1174 print F <<END 1175 } 1176 1177 return map.get(type); 1178 } 1179 1180 END 1181 ; 1182 1183 print F "}\n\n"; 1184 print F "#endif\n" if $parameters{guardFactoryWith}; 1185 1186 close F; 1187 } 1188 1189 sub printWrapperFactoryHeaderFile 1190 { 1191 my $outputDir = shift; 1192 my $wrapperFactoryFileName = shift; 1193 my $F; 1194 open F, ">" . $outputDir . "/V8" . $wrapperFactoryFileName . ".h"; 1195 1196 printLicenseHeader($F); 1197 1198 print F "#ifndef V8$parameters{namespace}ElementWrapperFactory_h\n"; 1199 print F "#define V8$parameters{namespace}ElementWrapperFactory_h\n\n"; 1200 1201 print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith}; 1202 1203 print F <<END 1204 #include <V8$parameters{namespace}Element.h> 1205 #include <V8$parameters{fallbackJSInterfaceName}.h> 1206 #include <v8.h> 1207 1208 namespace WebCore { 1209 1210 class $parameters{namespace}Element; 1211 1212 const QualifiedName* find$parameters{namespace}TagNameOfV8Type(const WrapperTypeInfo*); 1213 v8::Handle<v8::Object> createV8$parameters{namespace}Wrapper($parameters{namespace}Element*, v8::Handle<v8::Object> creationContext, v8::Isolate*); 1214 inline v8::Handle<v8::Object> createV8$parameters{namespace}DirectWrapper($parameters{namespace}Element* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 1215 { 1216 return V8$parameters{namespace}Element::createWrapper(element, creationContext, isolate); 1217 } 1218 inline v8::Handle<v8::Object> createV8$parameters{namespace}FallbackWrapper($parameters{fallbackJSInterfaceName}* element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) 1219 { 1220 return V8$parameters{fallbackJSInterfaceName}::createWrapper(element, creationContext, isolate); 1221 } 1222 } 1223 END 1224 ; 1225 print F "#endif // $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith}; 1226 1227 print F "#endif // V8$parameters{namespace}ElementWrapperFactory_h\n"; 1228 1229 close F; 1230 } 1231 1232 sub createGenericNamesFile 1233 { 1234 my $inputName = shift; 1235 my $baseName = shift; 1236 my $basePrefix = shift; 1237 1238 my $names = new IO::File; 1239 open($names, $inputName) or die "Failed to open file: $inputName"; 1240 1241 $initDefaults = 0; 1242 my $Parser = InFilesParser->new(); 1243 my $dummy; 1244 $Parser->parse($names, \¶metersHandler, \&dummy); 1245 1246 my $F; 1247 my $header = File::Spec->catfile($outputDir, "${baseName}Names.h"); 1248 open F, ">$header" or die "Unable to open $header for writing."; 1249 1250 printLicenseHeader($F); 1251 printHeaderHead($F, $basePrefix, $baseName, "#include \"wtf/text/AtomicString.h\""); 1252 1253 printMacros($F, "extern const WTF::AtomicString", "", \%parameters); 1254 print F "#endif\n\n"; 1255 1256 printInit($F, 1); 1257 close F; 1258 1259 my $source = File::Spec->catfile($outputDir, "${baseName}Names.cpp"); 1260 open F, ">$source" or die "Unable to open $source for writing."; 1261 1262 printLicenseHeader($F); 1263 printCppHead($F, $basePrefix, $baseName, "WTF"); 1264 1265 while ( my ($name, $identifier) = each %parameters ) { 1266 print F "DEFINE_GLOBAL(AtomicString, $name)\n"; 1267 } 1268 1269 printInit($F, 0); 1270 1271 print F "\n"; 1272 print F StaticString::GenerateStringImpls(\%parameters); 1273 1274 while ( my ($name, $identifier) = each %parameters ) { 1275 print F " new ((void*)&$name) AtomicString(${name}Impl);\n"; 1276 } 1277 1278 print F "}\n}\n}\n"; 1279 close F; 1280 exit 0; 1281 } 1282