2008-11-06 Julien Chaffraix <jchaffraix@pleyo.com>
[WebKit-https.git] / WebCore / dom / make_names.pl
1 #!/usr/bin/perl -w
2
3 # Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #
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. 
17 #
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.
28
29 use strict;
30
31 use Config;
32 use Getopt::Long;
33 use File::Path;
34 use IO::File;
35 use InFilesParser;
36 use Switch;
37
38 my $printFactory = 0; 
39 my $printWrapperFactory = 0;
40 my $tagsFile = "";
41 my $attrsFile = "";
42 my $outputDir = ".";
43 my %tags = ();
44 my %attrs = ();
45 my %parameters = ();
46 my $extraDefines = 0;
47 my $preprocessor = "/usr/bin/gcc -E -P -x c++";
48 my %svgCustomMappings = ();
49 my %htmlCustomMappings = ();
50
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);
58
59 die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile));
60
61 readNames($tagsFile, "tags") if length($tagsFile);
62 readNames($attrsFile, "attrs") if length($attrsFile);
63
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'};
66
67 $parameters{'namespacePrefix'} = $parameters{'namespace'} unless $parameters{'namespacePrefix'};
68
69 mkpath($outputDir);
70 my $namesBasePath = "$outputDir/$parameters{'namespace'}Names";
71 my $factoryBasePath = "$outputDir/$parameters{'namespace'}ElementFactory";
72 my $wrapperFactoryBasePath = "$outputDir/JS$parameters{'namespace'}ElementWrapperFactory";
73
74 printNamesHeaderFile("$namesBasePath.h");
75 printNamesCppFile("$namesBasePath.cpp");
76
77 if ($printFactory) {
78     printFactoryCppFile("$factoryBasePath.cpp");
79     printFactoryHeaderFile("$factoryBasePath.h");
80 }
81
82 if ($printWrapperFactory) {
83     printWrapperFactoryCppFile("$wrapperFactoryBasePath.cpp");
84     printWrapperFactoryHeaderFile("$wrapperFactoryBasePath.h");
85 }
86
87 ### Hash initialization
88
89 sub initializeTagPropertyHash
90 {
91     return ('interfaceName' => defaultInterfaceName($_[0]),
92             'applyAudioHack' => 0,
93             'exportString' => 0);
94 }
95
96 sub initializeAttrPropertyHash
97 {
98     return ('exportString' => 0);
99 }
100
101 sub initializeParametersHash
102 {
103     return ('namespace' => '',
104             'namespacePrefix' => '',
105             'namespaceURI' => '',
106             'guardFactoryWith' => '',
107             'tagsNullNamespace' => 0,
108             'attrsNullNamespace' => 0,
109             'exportStrings' => 0);
110 }
111
112 ### Parsing handlers
113
114 sub tagsHandler
115 {
116     my ($tag, $property, $value) = @_;
117
118     $tag =~ s/-/_/g;
119
120     # Initialize default properties' values.
121     $tags{$tag} = { initializeTagPropertyHash($tag) } if !defined($tags{$tag});
122
123     if ($property) {
124         die "Unknown property $property for tag $tag\n" if !defined($tags{$tag}{$property});
125         $tags{$tag}{$property} = $value;
126     }
127 }
128
129 sub attrsHandler
130 {
131     my ($attr, $property, $value) = @_;
132
133     $attr =~ s/-/_/g;
134
135     # Initialize default properties' values.
136     $attrs{$attr} = { initializeAttrPropertyHash($attr) } if !defined($attrs{$attr});
137
138     if ($property) {
139         die "Unknown property $property for attribute $attr\n" if !defined($attrs{$attr}{$property});
140         $attrs{$attr}{$property} = $value;
141     }
142 }
143
144 sub parametersHandler
145 {
146     my ($parameter, $value) = @_;
147
148     # Initialize default properties' values.
149     %parameters = initializeParametersHash() if !(keys %parameters);
150
151     die "Unknown parameter $parameter for tags/attrs\n" if !defined($parameters{$parameter});
152     $parameters{$parameter} = $value;
153 }
154
155 ## Support routines
156
157 sub readNames
158 {
159     my ($namesFile, $type) = @_;
160
161     my $names = new IO::File;
162
163     if ($extraDefines eq 0) {
164         open($names, $preprocessor . " " . $namesFile . "|") or die "Failed to open file: $namesFile";
165     } else {
166         open($names, $preprocessor . " -D" . join(" -D", split(" ", $extraDefines)) . " " . $namesFile . "|") or die "Failed to open file: $namesFile";
167     }
168
169     # Store hashes keys count to know if some insertion occured.
170     my $tagsCount = keys %tags;
171     my $attrsCount = keys %attrs;
172
173     my $InParser = InFilesParser->new();
174
175     switch ($type) {
176         case "tags" {
177             $InParser->parse($names, \&parametersHandler, \&tagsHandler);
178         }
179         case "attrs" {
180             $InParser->parse($names, \&parametersHandler, \&attrsHandler);
181         }
182         else {
183             die "Do not know how to parse $type";
184         }
185     }
186
187     close($names);
188
189     die "Failed to read names from file: $namesFile" if ((keys %tags == $tagsCount) && (keys %attrs == $attrsCount));
190 }
191
192 sub printMacros
193 {
194     my ($F, $macro, $suffix, $namesRef) = @_;
195     my %names = %$namesRef;
196
197     for my $name (sort keys %$namesRef) {
198         print F "$macro $name","$suffix;\n";
199
200         if ($parameters{'exportStrings'} or $names{$name}{"exportString"}) { 
201             print F "extern char $name", "${suffix}String[];\n";
202         }
203     }
204 }
205
206 sub printConstructors
207 {
208     my ($F, $namesRef) = @_;
209     my %names = %$namesRef;
210
211     print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
212     for my $name (sort keys %names) {
213         my $ucName = $names{$name}{'interfaceName'};
214
215         print F "$parameters{'namespace'}Element* ${name}Constructor(Document* doc, bool createdByParser)\n";
216         print F "{\n";
217         print F "    return new ${ucName}($parameters{'namespace'}Names::${name}Tag, doc);\n";
218         print F "}\n\n";
219     }
220     print F "#endif\n" if $parameters{'guardFactoryWith'};
221 }
222
223 sub printFunctionInits
224 {
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";
228     }
229 }
230
231 sub svgCapitalizationHacks
232 {
233     my $name = shift;
234
235     if ($name =~ /^fe(.+)$/) {
236         $name = "FE" . ucfirst $1;
237     }
238
239     return $name;
240 }
241
242 sub upperCaseName
243 {
244     my $name = shift;
245     
246     $name = svgCapitalizationHacks($name) if ($parameters{'namespace'} eq "SVG");
247
248     while ($name =~ /^(.*?)_(.*)/) {
249         $name = $1 . ucfirst $2;
250     }
251     
252     return ucfirst $name;
253 }
254
255 sub printLicenseHeader
256 {
257     my $F = shift;
258     print F "/*
259  * THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT.
260  *
261  *
262  * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
263  *
264  * Redistribution and use in source and binary forms, with or without
265  * modification, are permitted provided that the following conditions
266  * are met:
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.
272  *
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. 
284  */
285
286
287 ";
288 }
289
290 sub printNamesHeaderFile
291 {
292     my ($headerPath) = shift;
293     my $F;
294     open F, ">$headerPath";
295     
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";
300     
301     print F "namespace WebCore {\n\n namespace $parameters{'namespace'}Names {\n\n";
302     
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";
307
308     if (keys %tags) {
309         print F "// Tags\n";
310         printMacros($F, "extern const WebCore::QualifiedName", "Tag", \%tags);
311         print F "\n\nWebCore::QualifiedName** get$parameters{'namespace'}Tags(size_t* size);\n";
312     }
313     
314     if (keys %attrs) {
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";
318     }
319     print F "#endif\n\n";
320     print F "void init();\n\n";
321     print F "} }\n\n";
322     print F "#endif\n\n";
323     
324     close F;
325 }
326
327 sub printNamesCppFile
328 {
329     my $cppPath = shift;
330     my $F;
331     open F, ">$cppPath";
332     
333     printLicenseHeader($F);
334     
335     my $lowerNamespace = lc($parameters{'namespacePrefix'});
336
337 print F "#include \"config.h\"\n";
338
339 print F "#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC\n";
340 print F "#define DOM_$parameters{'namespace'}NAMES_HIDE_GLOBALS 1\n";
341 print F "#else\n";
342 print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n";
343 print F "#endif\n\n";
344
345
346 print F "#include \"$parameters{'namespace'}Names.h\"\n\n";
347 print F "#include \"StaticConstructors.h\"\n";
348
349 print F "namespace WebCore {\n\n namespace $parameters{'namespace'}Names {
350
351 using namespace WebCore;
352
353 DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$parameters{'namespaceURI'}\")
354 ";
355
356     if (keys %tags) {
357         print F "// Tags\n";
358         for my $name (sort keys %tags) {
359             print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Tag, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n";
360         }
361         
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";
366         }
367         print F "    };\n";
368         print F "    *size = ", scalar(keys %tags), ";\n";
369         print F "    return $parameters{'namespace'}Tags;\n";
370         print F "}\n";
371     }
372
373     if (keys %attrs) {
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";
377         }
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";
382         }
383         print F "    };\n";
384         print F "    *size = ", scalar(keys %attrs), ";\n";
385         print F "    return $parameters{'namespace'}Attr;\n";
386         print F "}\n";
387     }
388
389     if (keys %tags) {
390         printDefinitionStrings($F, \%tags, "tags");
391     }
392
393     if (keys %attrs) {
394         printDefinitionStrings($F, \%attrs, "attributes");
395     }
396
397 print F "\nvoid init()
398 {
399     static bool initialized = false;
400     if (initialized)
401         return;
402     initialized = true;
403     
404     // Use placement new to initialize the globals.
405     
406     AtomicString::init();
407 ";
408     
409     print(F "    AtomicString ${lowerNamespace}NS(\"$parameters{'namespaceURI'}\");\n\n");
410
411     print(F "    // Namespace\n");
412     print(F "    new ((void*)&${lowerNamespace}NamespaceURI) AtomicString(${lowerNamespace}NS);\n\n");
413     if (keys %tags) {
414         my $tagsNamespace = $parameters{'tagsNullNamespace'} ? "nullAtom" : "${lowerNamespace}NS";
415         printDefinitions($F, \%tags, "tags", $tagsNamespace);
416     }
417     if (keys %attrs) {
418         my $attrsNamespace = $parameters{'attrsNullNamespace'} ? "nullAtom" : "${lowerNamespace}NS";
419         printDefinitions($F, \%attrs, "attributes", $attrsNamespace);
420     }
421
422     print F "}\n\n} }\n\n";
423     close F;
424 }
425
426 sub printJSElementIncludes
427 {
428     my ($F, $namesRef) = @_;
429     my %names = %$namesRef;
430     for my $name (sort keys %names) {
431         next if (hasCustomMapping($name));
432
433         my $ucName = $names{$name}{"interfaceName"};
434         print F "#include \"JS${ucName}.h\"\n";
435     }
436 }
437
438 sub printElementIncludes
439 {
440     my ($F, $namesRef, $shouldSkipCustomMappings) = @_;
441     my %names = %$namesRef;
442     for my $name (sort keys %names) {
443         next if ($shouldSkipCustomMappings && hasCustomMapping($name));
444
445         my $ucName = $names{$name}{"interfaceName"};
446         print F "#include \"${ucName}.h\"\n";
447     }
448 }
449
450 sub printDefinitionStrings
451 {
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";
457
458     my %names = %$namesRef;
459     for my $name (sort keys %$namesRef) {
460         next if (!$parameters{'exportStrings'} and !$names{$name}{"exportString"});
461
462         my $realName = $name;
463         $realName =~ s/_/-/g;
464
465         print F "char $name","${shortCamelType}String[] = \"$realName\";\n";
466     }
467
468
469 sub printDefinitions
470 {
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);
476     
477     print F "    // " . ucfirst($type) . "\n";
478
479     my %names = %$namesRef;
480     for my $name (sort keys %$namesRef) {
481         next if ($parameters{'exportStrings'} or $names{$name}{"exportString"});
482
483         my $realName = $name;
484         $realName =~ s/_/-/g;
485         print F "    const char *$name","${shortCamelType}String = \"$realName\";\n";
486     }
487
488     print "\n";
489
490     for my $name (sort keys %$namesRef) {
491         print F "    new ((void*)&$name","${shortCamelType}) QualifiedName(nullAtom, $name","${shortCamelType}String, $namespaceURI);\n";
492     }
493 }
494
495 ## ElementFactory routines
496
497 sub printFactoryCppFile
498 {
499     my $cppPath = shift;
500     my $F;
501     open F, ">$cppPath";
502
503 printLicenseHeader($F);
504
505 print F <<END
506 #include "config.h"
507 #include "$parameters{'namespace'}ElementFactory.h"
508
509 #include "$parameters{'namespace'}Names.h"
510 #if ENABLE(DASHBOARD_SUPPORT)
511 #include "Document.h"
512 #include "Settings.h"
513 #endif
514
515 END
516 ;
517
518 printElementIncludes($F, \%tags, 0);
519
520 print F <<END
521 #include <wtf/HashMap.h>
522
523 using namespace WebCore;
524
525 typedef $parameters{'namespace'}Element* (*ConstructorFunc)(Document* doc, bool createdByParser);
526 typedef WTF::HashMap<AtomicStringImpl*, ConstructorFunc> FunctionMap;
527
528 static FunctionMap* gFunctionMap = 0;
529
530 namespace WebCore {
531
532 END
533 ;
534
535 printConstructors($F, \%tags);
536
537 print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
538
539 print F <<END
540 static inline void createFunctionMapIfNecessary()
541 {
542     if (gFunctionMap)
543         return;
544     // Create the table.
545     gFunctionMap = new FunctionMap;
546     
547     // Populate it with constructor functions.
548 END
549 ;
550
551 printFunctionInits($F, \%tags);
552
553 print F "}\n";
554 print F "#endif\n\n" if $parameters{'guardFactoryWith'};
555
556 print F <<END
557 $parameters{'namespace'}Element* $parameters{'namespace'}ElementFactory::create$parameters{'namespace'}Element(const QualifiedName& qName, Document* doc, bool createdByParser)
558 {
559 END
560 ;
561
562 print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
563
564 print F <<END
565     // Don't make elements without a document
566     if (!doc)
567         return 0;
568
569 #if ENABLE(DASHBOARD_SUPPORT)
570     Settings* settings = doc->settings();
571     if (settings && settings->usesDashboardBackwardCompatibilityMode())
572         return 0;
573 #endif
574
575     createFunctionMapIfNecessary();
576     ConstructorFunc func = gFunctionMap->get(qName.localName().impl());
577     if (func)
578         return func(doc, createdByParser);
579
580     return new $parameters{'namespace'}Element(qName, doc);
581 END
582 ;
583
584 if ($parameters{'guardFactoryWith'}) {
585
586 print F <<END
587 #else
588     return 0;
589 #endif
590 END
591 ;
592
593 }
594
595 print F <<END
596 }
597
598 } // namespace WebCore
599
600 END
601 ;
602
603     close F;
604 }
605
606 sub printFactoryHeaderFile
607 {
608     my $headerPath = shift;
609     my $F;
610     open F, ">$headerPath";
611
612     printLicenseHeader($F);
613
614 print F "#ifndef $parameters{'namespace'}ELEMENTFACTORY_H\n";
615 print F "#define $parameters{'namespace'}ELEMENTFACTORY_H\n\n";
616
617 print F "
618 namespace WebCore {
619     class Element;
620     class Document;
621     class QualifiedName;
622     class AtomicString;
623 }
624
625 namespace WebCore {
626
627     class $parameters{'namespace'}Element;
628
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
632     {
633     public:
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);
636     };
637 }
638
639 #endif
640
641 ";
642
643     close F;
644 }
645
646 ## Wrapper Factory routines
647
648 sub defaultInterfaceName
649 {
650     die "No namespace found" if !$parameters{'namespace'};
651     return $parameters{'namespace'} . upperCaseName($_[0]) . "Element"
652 }
653
654 sub initializeCustomMappings
655 {
656     if (!keys %svgCustomMappings) {
657         # These are used to map a tag to another one in WrapperFactory
658         # (for example, "h2" is mapped to "h1" so that they use the same JS Wrapper ("h1" wrapper))
659         # Mapping to an empty string will not generate a wrapper
660         %svgCustomMappings = ('animateMotion' => '',
661                               'hkern' => '',
662                               'mpath' => '');
663         %htmlCustomMappings = ('abbr' => '',
664                                'acronym' => '',
665                                'address' => '',
666                                'b' => '',
667                                'bdo' => '',
668                                'big' => '',
669                                'center' => '',
670                                'cite' => '',
671                                'code' => '',
672                                'colgroup' => 'col',
673                                'dd' => '',
674                                'dfn' => '',
675                                'dt' => '',
676                                'em' => '',
677                                'h2' => 'h1',
678                                'h3' => 'h1',
679                                'h4' => 'h1',
680                                'h5' => 'h1',
681                                'h6' => 'h1',
682                                'i' => '',
683                                'image' => 'img',
684                                'ins' => 'del',
685                                'kbd' => '',
686                                'keygen' => 'select',
687                                'listing' => 'pre',
688                                'layer' => '',
689                                'nobr' => '',
690                                'noembed' => '',
691                                'noframes' => '',
692                                'nolayer' => '',
693                                'noscript' => '',
694                                'plaintext' => '',
695                                's' => '',
696                                'samp' => '',
697                                'small' => '',
698                                'span' => '',
699                                'strike' => '',
700                                'strong' => '',
701                                'sub' => '',
702                                'sup' => '',
703                                'tfoot' => 'tbody',
704                                'th' => 'td',
705                                'thead' => 'tbody',
706                                'tt' => '',
707                                'u' => '',
708                                'var' => '',
709                                'wbr' => '',
710                                'xmp' => 'pre');
711     }
712 }
713
714 sub hasCustomMapping
715 {
716     my $name = shift;
717     initializeCustomMappings();
718     return 1 if $parameters{'namespace'} eq "HTML" && exists($htmlCustomMappings{$name});
719     return 1 if $parameters{'namespace'} eq "SVG" && exists($svgCustomMappings{$name});
720     return 0;
721 }
722
723 sub printWrapperFunctions
724 {
725     my ($F, $namesRef) = @_;
726     my %names = %$namesRef;
727     for my $name (sort keys %names) {
728         # Custom mapping do not need a JS wrapper
729         next if (hasCustomMapping($name));
730
731         my $ucName = $names{$name}{"interfaceName"};
732         # Hack for the media tags
733         if ($names{$name}{"applyAudioHack"}) {
734             print F <<END
735 static JSNode* create${ucName}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element)
736 {
737     if (!MediaPlayer::isAvailable())
738         return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}Element, element.get());
739     return CREATE_DOM_NODE_WRAPPER(exec, ${ucName}, element.get());
740 }
741
742 END
743 ;
744         } else {
745             print F <<END
746 static JSNode* create${ucName}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element)
747 {
748     return CREATE_DOM_NODE_WRAPPER(exec, ${ucName}, element.get());
749 }
750
751 END
752 ;
753         }
754     }
755 }
756
757 sub printWrapperFactoryCppFile
758 {
759     my $cppPath = shift;
760     my $F;
761     open F, ">$cppPath";
762
763     printLicenseHeader($F);
764
765     print F "#include \"config.h\"\n\n";
766
767     print F "#if $parameters{'guardFactoryWith'}\n\n" if $parameters{'guardFactoryWith'};
768
769     print F "#include \"JS$parameters{'namespace'}ElementWrapperFactory.h\"\n";
770
771     printJSElementIncludes($F, \%tags);
772
773     print F "\n#include \"$parameters{'namespace'}Names.h\"\n\n";
774
775     printElementIncludes($F, \%tags, 1);
776
777     print F <<END
778 using namespace JSC;
779
780 namespace WebCore {
781
782 using namespace $parameters{'namespace'}Names;
783
784 typedef JSNode* (*Create$parameters{'namespace'}ElementWrapperFunction)(ExecState*, PassRefPtr<$parameters{'namespace'}Element>);
785
786 END
787 ;
788
789     printWrapperFunctions($F, \%tags);
790
791     print F <<END
792 JSNode* createJS$parameters{'namespace'}Wrapper(ExecState* exec, PassRefPtr<$parameters{'namespace'}Element> element)
793 {   
794     static HashMap<WebCore::AtomicStringImpl*, Create$parameters{'namespace'}ElementWrapperFunction> map;
795     if (map.isEmpty()) {
796 END
797 ;
798
799     for my $tag (sort keys %tags) {
800         next if (hasCustomMapping($tag));
801
802         my $ucTag = $tags{$tag}{"interfaceName"};
803         print F "       map.set(${tag}Tag.localName().impl(), create${ucTag}Wrapper);\n";
804     }
805
806     if ($parameters{'namespace'} eq "HTML") {
807         for my $tag (sort keys %htmlCustomMappings) {
808             next if !$htmlCustomMappings{$tag};
809
810             my $ucCustomTag = $tags{$htmlCustomMappings{$tag}}{"interfaceName"};
811             print F "       map.set(${tag}Tag.localName().impl(), create${ucCustomTag}Wrapper);\n";
812         }
813     }
814
815     # Currently SVG has no need to add custom map.set as it only has empty elements
816
817     print F <<END
818     }
819     Create$parameters{'namespace'}ElementWrapperFunction createWrapperFunction = map.get(element->localName().impl());
820     if (createWrapperFunction)
821         return createWrapperFunction(exec, element);
822     return CREATE_DOM_NODE_WRAPPER(exec, $parameters{'namespace'}Element, element.get());
823 }
824
825 }
826
827 END
828 ;
829
830     print F "#endif\n" if $parameters{'guardFactoryWith'};
831
832     close F;
833 }
834
835 sub printWrapperFactoryHeaderFile
836 {
837     my $headerPath = shift;
838     my $F;
839     open F, ">$headerPath";
840
841     printLicenseHeader($F);
842
843     print F "#ifndef JS$parameters{'namespace'}ElementWrapperFactory_h\n";
844     print F "#define JS$parameters{'namespace'}ElementWrapperFactory_h\n\n";
845
846     print F "#if $parameters{'guardFactoryWith'}\n" if $parameters{'guardFactoryWith'};
847
848     print F <<END
849 #include <wtf/Forward.h>
850
851 namespace JSC {
852     class ExecState;
853 }                                            
854                                              
855 namespace WebCore {
856
857     class JSNode;
858     class $parameters{'namespace'}Element;
859
860     JSNode* createJS$parameters{'namespace'}Wrapper(JSC::ExecState*, PassRefPtr<$parameters{'namespace'}Element>);
861
862 }
863  
864 END
865 ;
866
867     print F "#endif // $parameters{'guardFactoryWith'}\n\n" if $parameters{'guardFactoryWith'};
868
869     print F "#endif // JS$parameters{'namespace'}ElementWrapperFactory_h\n";
870
871     close F;
872 }