3 # Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 # its contributors may be used to endorse or promote products derived
16 # from this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 my $printWrapperFactory = 0;
47 my $preprocessor = "/usr/bin/gcc -E -P -x c++";
48 my %svgCustomMappings = ();
49 my %htmlCustomMappings = ();
51 GetOptions
('tags=s' => \
$tagsFile,
52 'attrs=s' => \
$attrsFile,
53 'factory' => \
$printFactory,
54 'outputDir=s' => \
$outputDir,
55 'extraDefines=s' => \
$extraDefines,
56 'preprocessor=s' => \
$preprocessor,
57 'wrapperFactory' => \
$printWrapperFactory);
59 die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile));
61 readNames
($tagsFile, "tags") if length($tagsFile);
62 readNames
($attrsFile, "attrs") if length($attrsFile);
64 die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $parameters{'namespace'};
65 die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $parameters{'namespaceURI'};
67 $parameters{'namespacePrefix'} = $parameters{'namespace'} unless $parameters{'namespacePrefix'};
70 my $namesBasePath = "$outputDir/$parameters{'namespace'}Names";
71 my $factoryBasePath = "$outputDir/$parameters{'namespace'}ElementFactory";
72 my $wrapperFactoryBasePath = "$outputDir/JS$parameters{'namespace'}ElementWrapperFactory";
74 printNamesHeaderFile
("$namesBasePath.h");
75 printNamesCppFile
("$namesBasePath.cpp");
78 printFactoryCppFile
("$factoryBasePath.cpp");
79 printFactoryHeaderFile
("$factoryBasePath.h");
82 if ($printWrapperFactory) {
83 printWrapperFactoryCppFile
("$wrapperFactoryBasePath.cpp");
84 printWrapperFactoryHeaderFile
("$wrapperFactoryBasePath.h");
87 ### Hash initialization
89 sub initializeTagPropertyHash
91 return ('interfaceName' => upperCaseName
($_[0])."Element",
92 'applyAudioHack' => 0,
96 sub initializeAttrPropertyHash
98 return ('exportString' => 0);
101 sub initializeParametersHash
103 return ('namespace' => '',
104 'namespacePrefix' => '',
105 'namespaceURI' => '',
106 'guardFactoryWith' => '',
107 'tagsNullNamespace' => 0,
108 'attrsNullNamespace' => 0,
109 'exportStrings' => 0);
116 my ($tag, $property, $value) = @_;
120 # Initialize default properties' values.
121 $tags{$tag} = { initializeTagPropertyHash
($tag) } if !defined($tags{$tag});
124 die "Unknown property $property for tag $tag\n" if !defined($tags{$tag}{$property});
125 $tags{$tag}{$property} = $value;
131 my ($attr, $property, $value) = @_;
135 # Initialize default properties' values.
136 $attrs{$attr} = { initializeAttrPropertyHash
($attr) } if !defined($attrs{$attr});
139 die "Unknown property $property for attribute $attr\n" if !defined($attrs{$attr}{$property});
140 $attrs{$attr}{$property} = $value;
144 sub parametersHandler
146 my ($parameter, $value) = @_;
148 # Initialize default properties' values.
149 %parameters = initializeParametersHash
() if !(keys %parameters);
151 die "Unknown parameter $parameter for tags/attrs\n" if !defined($parameters{$parameter});
152 $parameters{$parameter} = $value;
159 my ($namesFile, $type) = @_;
161 my $names = new IO
::File
;
163 if ($extraDefines eq 0) {
164 open($names, $preprocessor . " " . $namesFile . "|") or die "Failed to open file: $namesFile";
166 open($names, $preprocessor . " -D" . join(" -D", split(" ", $extraDefines)) . " " . $namesFile . "|") or die "Failed to open file: $namesFile";
169 # Store hashes keys count to know if some insertion occured.
170 my $tagsCount = keys %tags;
171 my $attrsCount = keys %attrs;
173 my $InParser = InFilesParser
->new();
177 $InParser->parse($names, \
¶metersHandler
, \
&tagsHandler
);
180 $InParser->parse($names, \
¶metersHandler
, \
&attrsHandler
);
183 die "Do not know how to parse $type";
189 die "Failed to read names from file: $namesFile" if ((keys %tags == $tagsCount) && (keys %attrs == $attrsCount));
194 my ($F, $macro, $suffix, $namesRef) = @_;
195 my %names = %$namesRef;
197 for my $name (sort keys %$namesRef) {
198 print F
"$macro $name","$suffix;\n";
200 if ($parameters{'exportStrings'} or $names{$name}{"exportString"}) {
201 print F
"extern char $name", "${suffix}String[];\n";
206 sub printConstructors
208 my ($F, $namesRef) = @_;
209 my %names = %$namesRef;
211 print F
"#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
212 for my $name (sort keys %names) {
213 my $ucName = $names{$name}{"interfaceName"};
215 print F
"$parameters{'namespace'}Element* ${name}Constructor(Document* doc, bool createdByParser)\n";
217 print F
" return new $parameters{'namespace'}${ucName}($parameters{'namespace'}Names::${name}Tag, doc);\n";
220 print F
"#endif\n" if $parameters{'guardFactoryWith'};
223 sub printFunctionInits
225 my ($F, $namesRef) = @_;
226 for my $name (sort keys %$namesRef) {
227 print F
" gFunctionMap->set($parameters{'namespace'}Names::${name}Tag.localName().impl(), ${name}Constructor);\n";
231 sub svgCapitalizationHacks
235 if ($name =~ /^fe(.+)$/) {
236 $name = "FE" . ucfirst $1;
246 $name = svgCapitalizationHacks
($name) if ($parameters{'namespace'} eq "SVG");
248 while ($name =~ /^(.*?)_(.*)/) {
249 $name = $1 . ucfirst $2;
252 return ucfirst $name;
255 sub printLicenseHeader
259 * THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT.
262 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
264 * Redistribution and use in source and binary forms, with or without
265 * modification, are permitted provided that the following conditions
267 * 1. Redistributions of source code must retain the above copyright
268 * notice, this list of conditions and the following disclaimer.
269 * 2. Redistributions in binary form must reproduce the above copyright
270 * notice, this list of conditions and the following disclaimer in the
271 * documentation and/or other materials provided with the distribution.
273 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
274 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
275 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
276 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
277 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
278 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
279 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
280 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
281 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
282 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
283 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
290 sub printNamesHeaderFile
292 my ($headerPath) = shift;
294 open F
, ">$headerPath";
296 printLicenseHeader
($F);
297 print F
"#ifndef DOM_$parameters{'namespace'}NAMES_H\n";
298 print F
"#define DOM_$parameters{'namespace'}NAMES_H\n\n";
299 print F
"#include \"QualifiedName.h\"\n\n";
301 print F
"namespace WebCore {\n\n namespace $parameters{'namespace'}Names {\n\n";
303 my $lowerNamespace = lc($parameters{'namespacePrefix'});
304 print F
"#ifndef DOM_$parameters{'namespace'}NAMES_HIDE_GLOBALS\n";
305 print F
"// Namespace\n";
306 print F
"extern const WebCore::AtomicString ${lowerNamespace}NamespaceURI;\n\n";
310 printMacros
($F, "extern const WebCore::QualifiedName", "Tag", \
%tags);
311 print F
"\n\nWebCore::QualifiedName** get$parameters{'namespace'}Tags(size_t* size);\n";
315 print F
"// Attributes\n";
316 printMacros
($F, "extern const WebCore::QualifiedName", "Attr", \
%attrs);
317 print F
"\n\nWebCore::QualifiedName** get$parameters{'namespace'}Attr(size_t* size);\n";
319 print F
"#endif\n\n";
320 print F
"void init();\n\n";
322 print F
"#endif\n\n";
327 sub printNamesCppFile
333 printLicenseHeader
($F);
335 my $lowerNamespace = lc($parameters{'namespacePrefix'});
337 print F
"#include \"config.h\"\n";
339 print F
"#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n";
340 print F
"#define DOM_$parameters{'namespace'}NAMES_HIDE_GLOBALS 1\n";
342 print F
"#define QNAME_DEFAULT_CONSTRUCTOR 1\n";
343 print F
"#endif\n\n";
346 print F
"#include \"$parameters{'namespace'}Names.h\"\n\n";
347 print F
"#include \"StaticConstructors.h\"\n";
349 print F
"namespace WebCore {\n\n namespace $parameters{'namespace'}Names {
351 using namespace WebCore;
353 DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{'namespaceURI'}\")
358 for my $name (sort keys %tags) {
359 print F
"DEFINE_GLOBAL(QualifiedName, ", $name, "Tag, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n";
362 print F
"\n\nWebCore::QualifiedName** get$parameters{'namespace'}Tags(size_t* size)\n";
363 print F
"{\n static WebCore::QualifiedName* $parameters{'namespace'}Tags[] = {\n";
364 for my $name (sort keys %tags) {
365 print F
" (WebCore::QualifiedName*)&${name}Tag,\n";
368 print F
" *size = ", scalar(keys %tags), ";\n";
369 print F
" return $parameters{'namespace'}Tags;\n";
374 print F
"\n// Attributes\n";
375 for my $name (sort keys %attrs) {
376 print F
"DEFINE_GLOBAL(QualifiedName, ", $name, "Attr, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n";
378 print F
"\n\nWebCore::QualifiedName** get$parameters{'namespace'}Attrs(size_t* size)\n";
379 print F
"{\n static WebCore::QualifiedName* $parameters{'namespace'}Attr[] = {\n";
380 for my $name (sort keys %attrs) {
381 print F
" (WebCore::QualifiedName*)&${name}Attr,\n";
384 print F
" *size = ", scalar(keys %attrs), ";\n";
385 print F
" return $parameters{'namespace'}Attr;\n";
390 printDefinitionStrings
($F, \
%tags, "tags");
394 printDefinitionStrings
($F, \
%attrs, "attributes");
397 print F
"\nvoid init()
399 static bool initialized = false;
404 // Use placement new to initialize the globals.
406 AtomicString::init();
409 print(F
" AtomicString ${lowerNamespace}NS(\"$parameters{'namespaceURI'}\");\n\n");
411 print(F
" // Namespace\n");
412 print(F
" new ((void*)&${lowerNamespace}NamespaceURI) AtomicString(${lowerNamespace}NS);\n\n");
414 my $tagsNamespace = $parameters{'tagsNullNamespace'} ?
"nullAtom" : "${lowerNamespace}NS";
415 printDefinitions
($F, \
%tags, "tags", $tagsNamespace);
418 my $attrsNamespace = $parameters{'attrsNullNamespace'} ?
"nullAtom" : "${lowerNamespace}NS";
419 printDefinitions
($F, \
%attrs, "attributes", $attrsNamespace);
422 print F
"}\n\n} }\n\n";
426 sub printJSElementIncludes
428 my ($F, $namesRef) = @_;
429 my %names = %$namesRef;
430 for my $name (sort keys %names) {
431 next if (hasCustomMapping
($name));
433 my $ucName = $names{$name}{"interfaceName"};
434 print F
"#include \"JS$parameters{'namespace'}${ucName}.h\"\n";
438 sub printElementIncludes
440 my ($F, $namesRef, $shouldSkipCustomMappings) = @_;
441 my %names = %$namesRef;
442 for my $name (sort keys %names) {
443 next if ($shouldSkipCustomMappings && hasCustomMapping
($name));
445 my $ucName = $names{$name}{"interfaceName"};
446 print F
"#include \"$parameters{'namespace'}${ucName}.h\"\n";
450 sub printDefinitionStrings
452 my ($F, $namesRef, $type) = @_;
453 my $singularType = substr($type, 0, -1);
454 my $shortType = substr($singularType, 0, 4);
455 my $shortCamelType = ucfirst($shortType);
456 print F
"\n// " . ucfirst($type) . " as strings\n";
458 my %names = %$namesRef;
459 for my $name (sort keys %$namesRef) {
460 next if (!$parameters{'exportStrings'} and !$names{$name}{"exportString"});
462 my $realName = $name;
463 $realName =~ s/_/-/g;
465 print F
"char $name","${shortCamelType}String[] = \"$realName\";\n";
471 my ($F, $namesRef, $type, $namespaceURI) = @_;
472 my $singularType = substr($type, 0, -1);
473 my $shortType = substr($singularType, 0, 4);
474 my $shortCamelType = ucfirst($shortType);
475 my $shortUpperType = uc($shortType);
477 print F
" // " . ucfirst($type) . "\n";
479 my %names = %$namesRef;
480 for my $name (sort keys %$namesRef) {
481 next if ($parameters{'exportStrings'} or $names{$name}{"exportString"});
483 my $realName = $name;
484 $realName =~ s/_/-/g;
485 print F
" const char *$name","${shortCamelType}String = \"$realName\";\n";
490 for my $name (sort keys %$namesRef) {
491 print F
" new ((void*)&$name","${shortCamelType}) QualifiedName(nullAtom, $name","${shortCamelType}String, $namespaceURI);\n";
495 ## ElementFactory routines
497 sub printFactoryCppFile
503 printLicenseHeader
($F);
507 #include "$parameters{'namespace'}ElementFactory.h"
509 #include "$parameters{'namespace'}Names.h"
510 #if ENABLE(DASHBOARD_SUPPORT)
511 #include "Document.h"
512 #include "Settings.h"
518 printElementIncludes
($F, \
%tags, 0);
521 #include <wtf/HashMap.h>
523 using namespace WebCore;
525 typedef $parameters{'namespace'}Element* (*ConstructorFunc)(Document* doc, bool createdByParser);
526 typedef WTF::HashMap<AtomicStringImpl*, ConstructorFunc> FunctionMap;
528 static FunctionMap* gFunctionMap = 0;
535 printConstructors
($F, \
%tags);
537 print F
"#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
540 static inline void createFunctionMapIfNecessary()
545 gFunctionMap = new FunctionMap;
547 // Populate it with constructor functions.
551 printFunctionInits
($F, \
%tags);
554 print F
"#endif\n\n" if $parameters{'guardFactoryWith'};
557 $parameters{'namespace'}Element* $parameters{'namespace'}ElementFactory::create$parameters{'namespace'}Element(const QualifiedName& qName, Document* doc, bool createdByParser)
562 print F
"#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
565 // Don't make elements without a document
569 #if ENABLE(DASHBOARD_SUPPORT)
570 Settings* settings = doc->settings();
571 if (settings && settings->usesDashboardBackwardCompatibilityMode())
575 createFunctionMapIfNecessary();
576 ConstructorFunc func = gFunctionMap->get(qName.localName().impl());
578 return func(doc, createdByParser);
580 return new $parameters{'namespace'}Element(qName, doc);
584 if ($parameters{'guardFactoryWith'}) {
606 sub printFactoryHeaderFile
608 my $headerPath = shift;
610 open F
, ">$headerPath";
612 printLicenseHeader
($F);
614 print F
"#ifndef $parameters{'namespace'}ELEMENTFACTORY_H\n";
615 print F
"#define $parameters{'namespace'}ELEMENTFACTORY_H\n\n";
627 class $parameters{'namespace'}Element;
629 // The idea behind this class is that there will eventually be a mapping from namespace URIs to ElementFactories that can dispense
630 // elements. In a compound document world, the generic createElement function (will end up being virtual) will be called.
631 class $parameters{'namespace'}ElementFactory
634 WebCore::Element* createElement(const WebCore::QualifiedName& qName, WebCore::Document* doc, bool createdByParser = true);
635 static $parameters{'namespace'}Element* create$parameters{'namespace'}Element(const WebCore::QualifiedName& qName, WebCore::Document* doc, bool createdByParser = true);
646 ## Wrapper Factory routines
648 sub initializeCustomMappings
650 if (!keys %svgCustomMappings) {
651 # These are used to map a tag to another one in WrapperFactory
652 # (for example, "h2" is mapped to "h1" so that they use the same JS Wrapper ("h1" wrapper))
653 # Mapping to an empty string will not generate a wrapper
654 %svgCustomMappings = ('animateMotion' => '',
657 %htmlCustomMappings = ('abbr' => '',
680 'keygen' => 'select',
711 initializeCustomMappings
();
712 return 1 if $parameters{'namespace'} eq "HTML" && exists($htmlCustomMappings{$name});
713 return 1 if $parameters{'namespace'} eq "SVG" && exists($svgCustomMappings{$name});
717 sub printWrapperFunctions
719 my ($F, $namesRef) = @_;
720 my %names = %$namesRef;
721 for my $name (sort keys %names) {
722 # Custom mapping do not need a JS wrapper
723 next if (hasCustomMapping
($name));
725 my $ucName = $names{$name}{"interfaceName"};
726 # Hack for the media tags
727 if ($names{$name}{"applyAudioHack"}) {
729 static JSNode* create${ucName}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element)
731 if (!MediaPlayer::isAvailable())
732 return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}Element, element.get());
733 return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}${ucName}, element.get());
740 static JSNode* create${ucName}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element)
742 return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}${ucName}, element.get());
751 sub printWrapperFactoryCppFile
757 printLicenseHeader
($F);
759 print F
"#include \"config.h\"\n\n";
761 print F
"#if $parameters{'guardFactoryWith'}\n\n" if $parameters{'guardFactoryWith'};
763 print F
"#include \"JS$parameters{'namespace'}ElementWrapperFactory.h\"\n";
765 printJSElementIncludes
($F, \
%tags);
767 print F
"\n#include \"$parameters{'namespace'}Names.h\"\n\n";
769 printElementIncludes
($F, \
%tags, 1);
776 using namespace $parameters{'namespace'}Names;
778 typedef JSNode* (*Create$parameters{'namespace'}ElementWrapperFunction)(ExecState*, PassRefPtr<$parameters{'namespace'}Element>);
783 printWrapperFunctions
($F, \
%tags);
786 JSNode* createJS$parameters{'namespace'}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element)
788 static HashMap<WebCore::AtomicStringImpl*, Create$parameters{'namespace'}ElementWrapperFunction> map;
793 for my $tag (sort keys %tags) {
794 next if (hasCustomMapping
($tag));
796 my $ucTag = $tags{$tag}{"interfaceName"};
797 print F
" map.set(${tag}Tag.localName().impl(), create${ucTag}Wrapper);\n";
800 if ($parameters{'namespace'} eq "HTML") {
801 for my $tag (sort keys %htmlCustomMappings) {
802 next if !$htmlCustomMappings{$tag};
804 my $ucCustomTag = $tags{$htmlCustomMappings{$tag}}{"interfaceName"};
805 print F
" map.set(${tag}Tag.localName().impl(), create${ucCustomTag}Wrapper);\n";
809 # Currently SVG has no need to add custom map.set as it only has empty elements
813 Create$parameters{'namespace'}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl());
814 if (createWrapperFunction)
815 return createWrapperFunction(exec, element);
816 return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}Element, element.get());
824 print F
"#endif\n" if $parameters{'guardFactoryWith'};
829 sub printWrapperFactoryHeaderFile
831 my $headerPath = shift;
833 open F
, ">$headerPath";
835 printLicenseHeader
($F);
837 print F
"#ifndef JS$parameters{'namespace'}ElementWrapperFactory_h\n";
838 print F
"#define JS$parameters{'namespace'}ElementWrapperFactory_h\n\n";
840 print F
"#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
843 #include <wtf/Forward.h>
852 class $parameters{'namespace'}Element;
854 JSNode* createJS$parameters{'namespace'}Wrapper(JSC::ExecState*, PassRefPtr<$parameters{'namespace'}Element>);
861 print F
"#endif // $parameters{'guardFactoryWith'}\n\n" if $parameters{'guardFactoryWith'};
863 print F
"#endif // JS$parameters{'namespace'}ElementWrapperFactory_h\n";