WebCore/dom/make_names.pl
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebCore/dom/make_names.pl	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,1093 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
+# Copyright (C) 2009, Julien Chaffraix <jchaffraix@webkit.org>
+# Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer. 
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution. 
+# 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+#     its contributors may be used to endorse or promote products derived
+#     from this software without specific prior written permission. 
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+
+use Config;
+use Getopt::Long;
+use File::Path;
+use IO::File;
+use InFilesParser;
+use Switch;
+
+sub readTags($$);
+sub readAttrs($$);
+
+my $printFactory = 0; 
+my $printWrapperFactory = 0; 
+my $printWrapperFactoryV8 = 0; 
+my $tagsFile = "";
+my $attrsFile = "";
+my $outputDir = ".";
+my %parsedTags = ();
+my %parsedAttrs = ();
+my %enabledTags = ();
+my %enabledAttrs = ();
+my %allTags = ();
+my %allAttrs = ();
+my %parameters = ();
+my $extraDefines = 0;
+
+require Config;
+
+my $gccLocation = "";
+if ($ENV{CC}) {
+    $gccLocation = $ENV{CC};
+} elsif (($Config::Config{'osname'}) =~ /solaris/i) {
+    $gccLocation = "/usr/sfw/bin/gcc";
+} else {
+    $gccLocation = "/usr/bin/gcc";
+}
+my $preprocessor = $gccLocation . " -E -P -x c++";
+
+GetOptions(
+    'tags=s' => \$tagsFile, 
+    'attrs=s' => \$attrsFile,
+    'factory' => \$printFactory,
+    'outputDir=s' => \$outputDir,
+    'extraDefines=s' => \$extraDefines,
+    'preprocessor=s' => \$preprocessor,
+    'wrapperFactory' => \$printWrapperFactory,
+    'wrapperFactoryV8' => \$printWrapperFactoryV8
+);
+
+die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile));
+
+if (length($tagsFile)) {
+    %allTags = %{readTags($tagsFile, 0)};
+    %enabledTags = %{readTags($tagsFile, 1)};
+}
+
+if (length($attrsFile)) {
+    %allAttrs = %{readAttrs($attrsFile, 0)};
+    %enabledAttrs = %{readAttrs($attrsFile, 1)};
+}
+
+die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $parameters{namespace};
+die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $parameters{namespaceURI};
+
+$parameters{namespacePrefix} = $parameters{namespace} unless $parameters{namespacePrefix};
+
+mkpath($outputDir);
+my $namesBasePath = "$outputDir/$parameters{namespace}Names";
+my $factoryBasePath = "$outputDir/$parameters{namespace}ElementFactory";
+my $wrapperFactoryFileName = "$parameters{namespace}ElementWrapperFactory";
+
+printNamesHeaderFile("$namesBasePath.h");
+printNamesCppFile("$namesBasePath.cpp");
+
+if ($printFactory) {
+    printFactoryCppFile("$factoryBasePath.cpp");
+    printFactoryHeaderFile("$factoryBasePath.h");
+}
+
+die "You cannot specify both --wrapperFactory and --wrapperFactoryV8" if $printWrapperFactory && $printWrapperFactoryV8;
+my $wrapperFactoryType = "";
+if ($printWrapperFactory) {
+    $wrapperFactoryType = "JS";
+} elsif ($printWrapperFactoryV8) {
+    $wrapperFactoryType = "V8";
+}
+
+if ($wrapperFactoryType) {
+    printWrapperFactoryCppFile($outputDir, $wrapperFactoryType, $wrapperFactoryFileName);
+    printWrapperFactoryHeaderFile($outputDir, $wrapperFactoryType, $wrapperFactoryFileName);
+}
+
+### Hash initialization
+
+sub defaultTagPropertyHash
+{
+    return (
+        'constructorNeedsCreatedByParser' => 0,
+        'constructorNeedsFormElement' => 0,
+        'createWithNew' => 0,
+        'interfaceName' => defaultInterfaceName($_[0]),
+        # By default, the JSInterfaceName is the same as the interfaceName.
+        'JSInterfaceName' => defaultInterfaceName($_[0]),
+        'mapToTagName' => '',
+        'wrapperOnlyIfMediaIsAvailable' => 0,
+        'conditional' => 0
+    );
+}
+
+sub defaultParametersHash
+{
+    return (
+        'namespace' => '',
+        'namespacePrefix' => '',
+        'namespaceURI' => '',
+        'guardFactoryWith' => '',
+        'tagsNullNamespace' => 0,
+        'attrsNullNamespace' => 0
+    );
+}
+
+sub defaultInterfaceName
+{
+    die "No namespace found" if !$parameters{namespace};
+    return $parameters{namespace} . upperCaseName($_[0]) . "Element"
+}
+
+### Parsing handlers
+
+sub tagsHandler
+{
+    my ($tag, $property, $value) = @_;
+
+    $tag =~ s/-/_/g;
+
+    # Initialize default property values.
+    $parsedTags{$tag} = { defaultTagPropertyHash($tag) } if !defined($parsedTags{$tag});
+
+    if ($property) {
+        die "Unknown property $property for tag $tag\n" if !defined($parsedTags{$tag}{$property});
+
+        # The code relies on JSInterfaceName deriving from interfaceName to check for custom JSInterfaceName.
+        # So override JSInterfaceName if it was not already set.
+        $parsedTags{$tag}{JSInterfaceName} = $value if $property eq "interfaceName" && $parsedTags{$tag}{JSInterfaceName} eq $parsedTags{$tag}{interfaceName};
+
+        $parsedTags{$tag}{$property} = $value;
+    }
+}
+
+sub attrsHandler
+{
+    my ($attr, $property, $value) = @_;
+
+    $attr =~ s/-/_/g;
+
+    # Initialize default properties' values.
+    $parsedAttrs{$attr} = {} if !defined($parsedAttrs{$attr});
+
+    if ($property) {
+        die "Unknown property $property for attribute $attr\n" if !defined($parsedAttrs{$attr}{$property});
+        $parsedAttrs{$attr}{$property} = $value;
+    }
+}
+
+sub parametersHandler
+{
+    my ($parameter, $value) = @_;
+
+    # Initialize default properties' values.
+    %parameters = defaultParametersHash() if !(keys %parameters);
+
+    die "Unknown parameter $parameter for tags/attrs\n" if !defined($parameters{$parameter});
+    $parameters{$parameter} = $value;
+}
+
+## Support routines
+
+sub preprocessorCommand()
+{
+    return $preprocessor if $extraDefines eq 0;
+    return $preprocessor . " -D" . join(" -D", split(" ", $extraDefines));
+}
+
+sub readNames($$$$)
+{
+    my ($namesFile, $hashToFillRef, $handler, $usePreprocessor) = @_;
+
+    my $names = new IO::File;
+    if ($usePreprocessor) {
+        open($names, preprocessorCommand() . " " . $namesFile . "|") or die "Failed to open file: $namesFile";
+    } else {
+        open($names, $namesFile) or die "Failed to open file: $namesFile";
+    }
+
+    my $InParser = InFilesParser->new();
+    $InParser->parse($names, \&parametersHandler, $handler);
+
+    close($names);
+    die "Failed to read names from file: $namesFile" if (keys %{$hashToFillRef} == 0);
+    return $hashToFillRef;
+}
+
+sub readAttrs($$)
+{
+    my ($namesFile, $usePreprocessor) = @_;
+    %parsedAttrs = ();
+    return readNames($namesFile, \%parsedAttrs, \&attrsHandler, $usePreprocessor);
+}
+
+sub readTags($$)
+{
+    my ($namesFile, $usePreprocessor) = @_;
+    %parsedTags = ();
+    return readNames($namesFile, \%parsedTags, \&tagsHandler, $usePreprocessor);
+}
+
+sub printMacros
+{
+    my ($F, $macro, $suffix, $namesRef) = @_;
+    my %names = %$namesRef;
+
+    for my $name (sort keys %$namesRef) {
+        print F "$macro $name","$suffix;\n";
+    }
+}
+
+sub usesDefaultWrapper
+{
+    my $tagName = shift;
+    return $tagName eq $parameters{namespace} . "Element";
+}
+
+# Build a direct mapping from the tags to the Element to create, excluding
+# Element that have not constructor.
+sub buildConstructorMap
+{
+    my %tagConstructorMap = ();
+    for my $tagName (keys %enabledTags) {
+        my $interfaceName = $enabledTags{$tagName}{interfaceName};
+        next if (usesDefaultWrapper($interfaceName));
+
+        if ($enabledTags{$tagName}{mapToTagName}) {
+            die "Cannot handle multiple mapToTagName for $tagName\n" if $enabledTags{$enabledTags{$tagName}{mapToTagName}}{mapToTagName};
+            $interfaceName = $enabledTags{ $enabledTags{$tagName}{mapToTagName} }{interfaceName};
+        }
+
+        # Chop the string to keep the interesting part.
+        $interfaceName =~ s/$parameters{namespace}(.*)Element/$1/;
+        $tagConstructorMap{$tagName} = lc($interfaceName);
+    }
+
+    return %tagConstructorMap;
+}
+
+# Helper method that print the constructor's signature avoiding
+# unneeded arguments.
+sub printConstructorSignature
+{
+    my ($F, $tagName, $constructorName, $constructorTagName) = @_;
+
+    print F "static PassRefPtr<$parameters{namespace}Element> ${constructorName}Constructor(const QualifiedName& $constructorTagName, Document* document";
+    if ($parameters{namespace} eq "HTML") {
+        print F ", HTMLFormElement*";
+        print F " formElement" if $enabledTags{$tagName}{constructorNeedsFormElement};
+    }
+    print F ", bool";
+    print F " createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser};
+    print F ")\n{\n";
+}
+
+# Helper method to dump the constructor interior and call the 
+# Element constructor with the right arguments.
+# The variable names should be kept in sync with the previous method.
+sub printConstructorInterior
+{
+    my ($F, $tagName, $interfaceName, $constructorTagName) = @_;
+
+    # Handle media elements.
+    if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
+        print F <<END
+    Settings* settings = document->settings();
+    if (!MediaPlayer::isAvailable() || (settings && !settings->isMediaEnabled()))
+        return HTMLElement::create($constructorTagName, document);
+    
+END
+;
+    }
+
+    my $newPrefix = "";
+    my $createSuffix = "::create";
+
+    if ($enabledTags{$tagName}{createWithNew}) {
+        $newPrefix = "new ";
+        $createSuffix = "";
+    }
+
+    # Call the constructor with the right parameters.
+    print F "    return $newPrefix$interfaceName${createSuffix}($constructorTagName, document";
+    print F ", formElement" if $enabledTags{$tagName}{constructorNeedsFormElement};
+    print F ", createdByParser" if $enabledTags{$tagName}{constructorNeedsCreatedByParser};
+    print F ");\n}\n\n";
+}
+
+sub printConstructors
+{
+    my ($F, $tagConstructorMapRef) = @_;
+    my %tagConstructorMap = %$tagConstructorMapRef;
+
+    # This is to avoid generating the same constructor several times.
+    my %uniqueTags = ();
+    for my $tagName (sort keys %tagConstructorMap) {
+        my $interfaceName = $enabledTags{$tagName}{interfaceName};
+
+        # Ignore the mapped tag
+        # FIXME: It could be moved inside this loop but was split for readibility.
+        next if (defined($uniqueTags{$interfaceName}) || $enabledTags{$tagName}{mapToTagName});
+
+        $uniqueTags{$interfaceName} = '1';
+
+        my $conditional = $enabledTags{$tagName}{conditional};
+        if ($conditional) {
+            my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
+            print F "#if ${conditionalString}\n\n";
+        }
+
+        printConstructorSignature($F, $tagName, $tagConstructorMap{$tagName}, "tagName");
+        printConstructorInterior($F, $tagName, $interfaceName, "tagName");
+
+        if ($conditional) {
+            print F "#endif\n";
+        }
+    }
+
+    # Mapped tag name uses a special wrapper to keep their prefix and namespaceURI while using the mapped localname.
+    for my $tagName (sort keys %tagConstructorMap) {
+        if ($enabledTags{$tagName}{mapToTagName}) {
+            my $mappedName = $enabledTags{$tagName}{mapToTagName};
+            printConstructorSignature($F, $mappedName, $mappedName . "To" . $tagName, "tagName");
+            printConstructorInterior($F, $mappedName, $enabledTags{$mappedName}{interfaceName}, "QualifiedName(tagName.prefix(), ${mappedName}Tag.localName(), tagName.namespaceURI())");
+        }
+    }
+}
+
+sub printFunctionInits
+{
+    my ($F, $tagConstructorMap) = @_;
+    my %tagConstructorMap = %$tagConstructorMap;
+
+    for my $tagName (sort keys %tagConstructorMap) {
+
+        my $conditional = $enabledTags{$tagName}{conditional};
+        if ($conditional) {
+            my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
+            print F "#if ${conditionalString}\n";
+        }
+
+        if ($enabledTags{$tagName}{mapToTagName}) {
+            print F "    addTag(${tagName}Tag, $enabledTags{$tagName}{mapToTagName}To${tagName}Constructor);\n";
+        } else {
+            print F "    addTag(${tagName}Tag, $tagConstructorMap{$tagName}Constructor);\n";
+        }
+
+        if ($conditional) {
+            print F "#endif\n\n";
+        }
+    }
+}
+
+sub svgCapitalizationHacks
+{
+    my $name = shift;
+
+    $name = "FE" . ucfirst $1 if $name =~ /^fe(.+)$/;
+
+    return $name;
+}
+
+sub upperCaseName
+{
+    my $name = shift;
+    
+    $name = svgCapitalizationHacks($name) if ($parameters{namespace} eq "SVG");
+
+    while ($name =~ /^(.*?)_(.*)/) {
+        $name = $1 . ucfirst $2;
+    }
+    
+    return ucfirst $name;
+}
+
+sub printLicenseHeader
+{
+    my $F = shift;
+    print F "/*
+ * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT.
+ *
+ * This file was generated by the dom/make_names.pl script.
+ *
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+";
+}
+
+sub printNamesHeaderFile
+{
+    my ($headerPath) = shift;
+    my $F;
+    open F, ">$headerPath";
+
+    printLicenseHeader($F);
+    print F "#ifndef DOM_$parameters{namespace}NAMES_H\n";
+    print F "#define DOM_$parameters{namespace}NAMES_H\n\n";
+    print F "#include \"QualifiedName.h\"\n\n";
+
+    print F "namespace WebCore {\n\n namespace $parameters{namespace}Names {\n\n";
+
+    my $lowerNamespace = lc($parameters{namespacePrefix});
+    print F "#ifndef DOM_$parameters{namespace}NAMES_HIDE_GLOBALS\n";
+    print F "// Namespace\n";
+    print F "extern const WebCore::AtomicString ${lowerNamespace}NamespaceURI;\n\n";
+
+    if (keys %allTags) {
+        print F "// Tags\n";
+        printMacros($F, "extern const WebCore::QualifiedName", "Tag", \%allTags);
+    }
+    
+    if (keys %allAttrs) {
+        print F "// Attributes\n";
+        printMacros($F, "extern const WebCore::QualifiedName", "Attr", \%allAttrs);
+    }
+    print F "#endif\n\n";
+
+    if (keys %allTags) {
+        print F "WebCore::QualifiedName** get$parameters{namespace}Tags(size_t* size);\n";
+    }
+
+    if (keys %allAttrs) {
+        print F "WebCore::QualifiedName** get$parameters{namespace}Attrs(size_t* size);\n";
+    }
+
+    print F "\nvoid init();\n\n";
+    print F "} }\n\n";
+    print F "#endif\n\n";
+
+    close F;
+}
+
+sub printNamesCppFile
+{
+    my $cppPath = shift;
+    my $F;
+    open F, ">$cppPath";
+    
+    printLicenseHeader($F);
+    
+    my $lowerNamespace = lc($parameters{namespacePrefix});
+
+print F "#include \"config.h\"\n";
+
+print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n";
+print F "#define DOM_$parameters{namespace}NAMES_HIDE_GLOBALS 1\n";
+print F "#else\n";
+print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n";
+print F "#endif\n\n";
+
+
+print F "#include \"$parameters{namespace}Names.h\"\n\n";
+print F "#include <wtf/StaticConstructors.h>\n";
+
+print F "namespace WebCore {\n\n namespace $parameters{namespace}Names {
+
+using namespace WebCore;
+
+DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{namespaceURI}\")
+";
+
+    if (keys %allTags) {
+        print F "// Tags\n";
+        for my $name (sort keys %allTags) {
+            print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Tag, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n";
+        }
+        
+        print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Tags(size_t* size)\n";
+        print F "{\n    static WebCore::QualifiedName* $parameters{namespace}Tags[] = {\n";
+        for my $name (sort keys %allTags) {
+            print F "        (WebCore::QualifiedName*)&${name}Tag,\n";
+        }
+        print F "    };\n";
+        print F "    *size = ", scalar(keys %allTags), ";\n";
+        print F "    return $parameters{namespace}Tags;\n";
+        print F "}\n";
+    }
+
+    if (keys %allAttrs) {
+        print F "\n// Attributes\n";
+        for my $name (sort keys %allAttrs) {
+            print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Attr, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n";
+        }
+        print F "\n\nWebCore::QualifiedName** get$parameters{namespace}Attrs(size_t* size)\n";
+        print F "{\n    static WebCore::QualifiedName* $parameters{namespace}Attr[] = {\n";
+        for my $name (sort keys %allAttrs) {
+            print F "        (WebCore::QualifiedName*)&${name}Attr,\n";
+        }
+        print F "    };\n";
+        print F "    *size = ", scalar(keys %allAttrs), ";\n";
+        print F "    return $parameters{namespace}Attr;\n";
+        print F "}\n";
+    }
+
+print F "\nvoid init()
+{
+    static bool initialized = false;
+    if (initialized)
+        return;
+    initialized = true;
+    
+    // Use placement new to initialize the globals.
+    
+    AtomicString::init();
+";
+    
+    print(F "    AtomicString ${lowerNamespace}NS(\"$parameters{namespaceURI}\");\n\n");
+
+    print(F "    // Namespace\n");
+    print(F "    new ((void*)&${lowerNamespace}NamespaceURI) AtomicString(${lowerNamespace}NS);\n\n");
+    if (keys %allTags) {
+        my $tagsNamespace = $parameters{tagsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS";
+        printDefinitions($F, \%allTags, "tags", $tagsNamespace);
+    }
+    if (keys %allAttrs) {
+        my $attrsNamespace = $parameters{attrsNullNamespace} ? "nullAtom" : "${lowerNamespace}NS";
+        printDefinitions($F, \%allAttrs, "attributes", $attrsNamespace);
+    }
+
+    print F "}\n\n} }\n\n";
+    close F;
+}
+
+sub printJSElementIncludes
+{
+    my $F = shift;
+    my $wrapperFactoryType = shift;
+
+    my %tagsSeen;
+    for my $tagName (sort keys %enabledTags) {
+        my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
+        next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName);
+        $tagsSeen{$JSInterfaceName} = 1;
+
+        print F "#include \"${wrapperFactoryType}${JSInterfaceName}.h\"\n";
+    }
+}
+
+sub printElementIncludes
+{
+    my $F = shift;
+
+    my %tagsSeen;
+    for my $tagName (sort keys %enabledTags) {
+        my $interfaceName = $enabledTags{$tagName}{interfaceName};
+        next if defined($tagsSeen{$interfaceName});
+        $tagsSeen{$interfaceName} = 1;
+
+        print F "#include \"${interfaceName}.h\"\n";
+    }
+}
+
+sub printDefinitions
+{
+    my ($F, $namesRef, $type, $namespaceURI) = @_;
+    my $singularType = substr($type, 0, -1);
+    my $shortType = substr($singularType, 0, 4);
+    my $shortCamelType = ucfirst($shortType);
+    my $shortUpperType = uc($shortType);
+    
+    print F "    // " . ucfirst($type) . "\n";
+
+    for my $name (sort keys %$namesRef) {
+        my $realName = $name;
+        $realName =~ s/_/-/g;
+        print F "    new ((void*)&$name","${shortCamelType}) QualifiedName(nullAtom, \"$realName\", $namespaceURI);\n";
+    }
+}
+
+## ElementFactory routines
+
+sub printFactoryCppFile
+{
+    my $cppPath = shift;
+    my $F;
+    open F, ">$cppPath";
+
+printLicenseHeader($F);
+
+print F <<END
+#include "config.h"
+#include "$parameters{namespace}ElementFactory.h"
+#include "$parameters{namespace}Names.h"
+END
+;
+
+print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
+
+printElementIncludes($F);
+
+print F <<END
+#include <wtf/HashMap.h>
+
+#if ENABLE(DASHBOARD_SUPPORT) || ENABLE(VIDEO)
+#include "Document.h"
+#include "Settings.h"
+#endif
+
+namespace WebCore {
+
+using namespace $parameters{namespace}Names;
+
+END
+;
+
+print F "typedef PassRefPtr<$parameters{namespace}Element> (*ConstructorFunction)(const QualifiedName&, Document*";
+print F ", HTMLFormElement*" if $parameters{namespace} eq "HTML";
+print F ", bool createdByParser);\n";
+print F <<END
+typedef HashMap<AtomicStringImpl*, ConstructorFunction> FunctionMap;
+
+static FunctionMap* gFunctionMap = 0;
+
+END
+;
+
+my %tagConstructorMap = buildConstructorMap();
+
+printConstructors($F, \%tagConstructorMap);
+
+print F <<END
+static void addTag(const QualifiedName& tag, ConstructorFunction func)
+{
+    gFunctionMap->set(tag.localName().impl(), func);
+}
+
+static void createFunctionMap()
+{
+    ASSERT(!gFunctionMap);
+
+    // Create the table.
+    gFunctionMap = new FunctionMap;
+    
+    // Populate it with constructor functions.
+END
+;
+
+printFunctionInits($F, \%tagConstructorMap);
+
+print F "}\n";
+
+print F "\nPassRefPtr<$parameters{namespace}Element> $parameters{namespace}ElementFactory::create$parameters{namespace}Element(const QualifiedName& qName, Document* document";
+print F ", HTMLFormElement* formElement" if $parameters{namespace} eq "HTML";
+print F ", bool createdByParser)\n{\n";
+
+print F <<END
+    if (!document)
+        return 0;
+
+END
+;
+
+if ($parameters{namespace} ne "HTML") {
+print F <<END
+#if ENABLE(DASHBOARD_SUPPORT)
+    Settings* settings = document->settings();
+    if (settings && settings->usesDashboardBackwardCompatibilityMode())
+        return 0;
+#endif
+END
+;
+
+}
+
+print F <<END
+    if (!gFunctionMap)
+        createFunctionMap();
+    if (ConstructorFunction function = gFunctionMap->get(qName.localName().impl()))
+END
+;
+
+if ($parameters{namespace} eq "HTML") {
+    print F "        return function(qName, document, formElement, createdByParser);\n";
+} else {
+    print F "        return function(qName, document, createdByParser);\n";
+}
+
+print F "    return $parameters{namespace}Element::create(qName, document);\n";
+
+print F <<END
+}
+
+} // namespace WebCore
+
+END
+;
+
+    print F "#endif\n" if $parameters{guardFactoryWith};
+
+    close F;
+}
+
+sub printFactoryHeaderFile
+{
+    my $headerPath = shift;
+    my $F;
+    open F, ">$headerPath";
+
+    printLicenseHeader($F);
+
+    print F<<END
+#ifndef $parameters{namespace}ElementFactory_h
+#define $parameters{namespace}ElementFactory_h
+
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+    class Element;
+    class Document;
+    class QualifiedName;
+    class AtomicString;
+}
+
+namespace WebCore {
+
+    class $parameters{namespace}Element;
+END
+;
+
+print F "     class HTMLFormElement;\n" if $parameters{namespace} eq "HTML";
+
+print F<<END
+    // The idea behind this class is that there will eventually be a mapping from namespace URIs to ElementFactories that can dispense
+    // elements. In a compound document world, the generic createElement function (will end up being virtual) will be called.
+    class $parameters{namespace}ElementFactory {
+    public:
+        PassRefPtr<Element> createElement(const WebCore::QualifiedName&, WebCore::Document*, bool createdByParser = true);
+END
+;
+print F "        static PassRefPtr<$parameters{namespace}Element> create$parameters{namespace}Element(const WebCore::QualifiedName&, WebCore::Document*";
+print F ", HTMLFormElement* = 0" if $parameters{namespace} eq "HTML";
+print F ", bool createdByParser = true);\n";
+
+printf F<<END
+    };
+}
+
+#endif // $parameters{namespace}ElementFactory_h
+
+END
+;
+
+    close F;
+}
+
+## Wrapper Factory routines
+
+sub usesDefaultJSWrapper
+{
+    my $name = shift;
+
+    # A tag reuses the default wrapper if its JSInterfaceName matches the default namespace Element.
+    return $enabledTags{$name}{JSInterfaceName} eq $parameters{namespace} . "Element" || $enabledTags{$name}{JSInterfaceName} eq "HTMLNoScriptElement";
+}
+
+sub printWrapperFunctions
+{
+    my $F = shift;
+    my $wrapperFactoryType = shift;
+
+    my %tagsSeen;
+    for my $tagName (sort keys %enabledTags) {
+        # Avoid defining the same wrapper method twice.
+        my $JSInterfaceName = $enabledTags{$tagName}{JSInterfaceName};
+        next if defined($tagsSeen{$JSInterfaceName}) || usesDefaultJSWrapper($tagName);
+        $tagsSeen{$JSInterfaceName} = 1;
+
+        my $conditional = $enabledTags{$tagName}{conditional};
+        if ($conditional) {
+            my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
+            print F "#if ${conditionalString}\n\n";
+        }
+
+        if ($wrapperFactoryType eq "JS") {
+            # Hack for the media tags
+            # FIXME: This should have been done via a CustomWrapper attribute and a separate *Custom file.
+            if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
+                print F <<END
+static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
+{
+    Settings* settings = element->document()->settings();
+    if (!MediaPlayer::isAvailable() || (settings && !settings->isMediaEnabled()))
+        return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{namespace}Element, element.get());
+    return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get());
+}
+
+END
+;
+            } else {
+                print F <<END
+static JSNode* create${JSInterfaceName}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
+{
+    return CREATE_DOM_NODE_WRAPPER(exec, globalObject, ${JSInterfaceName}, element.get());
+}
+
+END
+;
+            }
+        } elsif ($wrapperFactoryType eq "V8") {
+            if ($enabledTags{$tagName}{wrapperOnlyIfMediaIsAvailable}) {
+                print F <<END
+static v8::Handle<v8::Value> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element)
+{
+    Settings* settings = element->document()->settings();
+    if (!MediaPlayer::isAvailable() || (settings && !settings->isMediaEnabled()))
+        return V8$parameters{namespace}Element::wrap(element);
+    return toV8(static_cast<${JSInterfaceName}*>(element));
+}
+
+END
+;
+            } else {
+            print F <<END
+static v8::Handle<v8::Value> create${JSInterfaceName}Wrapper($parameters{namespace}Element* element)
+{
+    return toV8(static_cast<${JSInterfaceName}*>(element));
+}
+
+
+END
+;
+            }
+        }
+
+        if ($conditional) {
+            print F "#endif\n\n";
+        }
+    }
+}
+
+sub printWrapperFactoryCppFile
+{
+    my $outputDir = shift;
+    my $wrapperFactoryType = shift;
+    my $wrapperFactoryFileName = shift;
+    my $F;
+    open F, ">" . $outputDir . "/" . $wrapperFactoryType . $wrapperFactoryFileName . ".cpp";
+
+    printLicenseHeader($F);
+
+    print F "#include \"config.h\"\n";
+    print F "#include \"$wrapperFactoryType$parameters{namespace}ElementWrapperFactory.h\"\n";
+
+    print F "\n#if $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
+
+    printJSElementIncludes($F, $wrapperFactoryType);
+
+    print F "\n#include \"$parameters{namespace}Names.h\"\n\n";
+
+    printElementIncludes($F);
+
+    print F <<END
+#include <wtf/StdLibExtras.h>
+
+#if ENABLE(VIDEO)
+#include "Document.h"
+#include "Settings.h"
+#endif
+
+END
+;
+
+    if ($wrapperFactoryType eq "JS") {    
+        print F <<END
+using namespace JSC;
+END
+;
+    } elsif ($wrapperFactoryType eq "V8") {
+        print F <<END
+#include "V8$parameters{namespace}Element.h"
+        
+#include <v8.h>
+END
+;
+    }
+
+    print F <<END
+
+namespace WebCore {
+
+using namespace $parameters{namespace}Names;
+
+END
+;
+    if ($wrapperFactoryType eq "JS") {
+        print F <<END
+typedef JSNode* (*Create$parameters{namespace}ElementWrapperFunction)(ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>);
+
+END
+;
+    } elsif ($wrapperFactoryType eq "V8") {
+        print F <<END
+typedef v8::Handle<v8::Value> (*Create$parameters{namespace}ElementWrapperFunction)($parameters{namespace}Element*);
+
+END
+;
+    }
+
+    printWrapperFunctions($F, $wrapperFactoryType);
+
+    if ($wrapperFactoryType eq "JS") {
+        print F <<END
+JSNode* createJS$parameters{namespace}Wrapper(ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<$parameters{namespace}Element> element)
+{
+    typedef HashMap<WebCore::AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction> FunctionMap;
+    DEFINE_STATIC_LOCAL(FunctionMap, map, ());
+    if (map.isEmpty()) {
+END
+;
+    } elsif ($wrapperFactoryType eq "V8") {
+        print F <<END
+v8::Handle<v8::Value> createV8$parameters{namespace}Wrapper($parameters{namespace}Element* element, bool forceNewObject)
+{
+    typedef HashMap<WebCore::AtomicStringImpl*, Create$parameters{namespace}ElementWrapperFunction> FunctionMap;
+    DEFINE_STATIC_LOCAL(FunctionMap, map, ());
+    if (map.isEmpty()) {
+END
+;
+    }
+
+    for my $tag (sort keys %enabledTags) {
+        # Do not add the name to the map if it does not have a JS wrapper constructor or uses the default wrapper.
+        next if usesDefaultJSWrapper($tag, \%enabledTags);
+
+        my $conditional = $enabledTags{$tag}{conditional};
+        if ($conditional) {
+            my $conditionalString = "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
+            print F "#if ${conditionalString}\n";
+        }
+
+        my $ucTag = $enabledTags{$tag}{JSInterfaceName};
+        print F "       map.set(${tag}Tag.localName().impl(), create${ucTag}Wrapper);\n";
+
+        if ($conditional) {
+            print F "#endif\n";
+        }
+    }
+
+    print F <<END
+    }
+    Create$parameters{namespace}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl());
+    if (createWrapperFunction)
+END
+;
+    if ($wrapperFactoryType eq "JS") {
+        print F <<END
+        return createWrapperFunction(exec, globalObject, element);
+    return CREATE_DOM_NODE_WRAPPER(exec, globalObject, $parameters{namespace}Element, element.get());
+END
+;
+    } elsif ($wrapperFactoryType eq "V8") {
+        print F <<END
+        return createWrapperFunction(element);
+    return V8$parameters{namespace}Element::wrap(element, forceNewObject);
+END
+;
+    }
+    print F <<END
+}
+
+}
+
+END
+;
+
+    print F "#endif\n" if $parameters{guardFactoryWith};
+
+    close F;
+}
+
+sub printWrapperFactoryHeaderFile
+{
+    my $outputDir = shift;
+    my $wrapperFactoryType = shift;
+    my $wrapperFactoryFileName = shift;
+    my $F;
+    open F, ">" . $outputDir . "/" . $wrapperFactoryType . $wrapperFactoryFileName . ".h";
+
+    printLicenseHeader($F);
+
+    print F "#ifndef $wrapperFactoryType$parameters{namespace}ElementWrapperFactory_h\n";
+    print F "#define $wrapperFactoryType$parameters{namespace}ElementWrapperFactory_h\n\n";
+
+    print F "#if $parameters{guardFactoryWith}\n" if $parameters{guardFactoryWith};
+
+    if ($wrapperFactoryType eq "JS") {
+        print F <<END
+#include <wtf/Forward.h>
+
+namespace JSC {
+    class ExecState;
+}                                            
+                                             
+namespace WebCore {
+
+    class JSNode;
+    class JSDOMGlobalObject;
+    class $parameters{namespace}Element;
+
+    JSNode* createJS$parameters{namespace}Wrapper(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<$parameters{namespace}Element>);
+
+}
+ 
+END
+;
+    } elsif ($wrapperFactoryType eq "V8") {
+        print F <<END
+#include <v8.h>
+
+namespace WebCore {
+
+    class $parameters{namespace}Element;
+
+    v8::Handle<v8::Value> createV8$parameters{namespace}Wrapper($parameters{namespace}Element*, bool);
+}
+END
+;
+    }
+
+    print F "#endif // $parameters{guardFactoryWith}\n\n" if $parameters{guardFactoryWith};
+
+    print F "#endif // $wrapperFactoryType$parameters{namespace}ElementWrapperFactory_h\n";
+
+    close F;
+}