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.
35 my $cppNamespace = "";
37 my $namespacePrefix = "";
38 my $namespaceURI = "";
44 my $tagsNullNamespace = 0;
45 my $attrsNullNamespace = 0;
47 my $preprocessor = "/usr/bin/gcc -E -P -x c++";
48 my $guardFactoryWith = 0;
50 GetOptions('tags=s' => \$tagsFile,
51 'attrs=s' => \$attrsFile,
52 'outputDir=s' => \$outputDir,
53 'namespace=s' => \$namespace,
54 'namespacePrefix=s' => \$namespacePrefix,
55 'namespaceURI=s' => \$namespaceURI,
56 'cppNamespace=s' => \$cppNamespace,
57 'factory' => \$printFactory,
58 'tagsNullNamespace' => \$tagsNullNamespace,
59 'attrsNullNamespace' => \$attrsNullNamespace,
60 'extraDefines=s' => \$extraDefines,
61 'preprocessor=s' => \$preprocessor,
62 'guardFactoryWith=s' => \$guardFactoryWith);
64 die "You must specify a namespace (e.g. SVG) for <namespace>Names.h" unless $namespace;
65 die "You must specify a namespaceURI (e.g. http://www.w3.org/2000/svg)" unless $namespaceURI;
66 die "You must specify a cppNamespace (e.g. DOM) used for <cppNamespace>::<namespace>Names::fooTag" unless $cppNamespace;
67 die "You must specify at least one of --tags <file> or --attrs <file>" unless (length($tagsFile) || length($attrsFile));
69 $namespacePrefix = $namespace unless $namespacePrefix;
71 @tags = readNames($tagsFile) if length($tagsFile);
72 @attrs = readNames($attrsFile) if length($attrsFile);
75 my $namesBasePath = "$outputDir/${namespace}Names";
76 my $factoryBasePath = "$outputDir/${namespace}ElementFactory";
78 printNamesHeaderFile("$namesBasePath.h");
79 printNamesCppFile("$namesBasePath.cpp");
81 printFactoryCppFile("$factoryBasePath.cpp");
82 printFactoryHeaderFile("$factoryBasePath.h");
90 my $namesFile = shift;
92 if ($extraDefines eq 0) {
93 die "Failed to open file: $namesFile" unless open NAMES, $preprocessor . " " . $namesFile . "|" or die;
95 die "Failed to open file: $namesFile" unless open NAMES, $preprocessor . " -D" . join(" -D", split(" ", $extraDefines)) . " " . $namesFile . "|" or die;
101 next if (m/^[ \t]*$/);
108 die "Failed to read names from file: $namesFile" unless (scalar(@names));
115 my ($F, $macro, $suffix, @names) = @_;
116 for my $name (@names) {
117 print F " $macro $name","$suffix;\n";
121 sub printConstructors
123 my ($F, @names) = @_;
124 print F "#if $guardFactoryWith\n" if $guardFactoryWith;
125 for my $name (@names) {
126 my $upperCase = upperCaseName($name);
128 print F "${namespace}Element *${name}Constructor(Document *doc, bool createdByParser)\n";
130 print F " return new ${namespace}${upperCase}Element(${name}Tag, doc);\n";
133 print F "#endif\n" if $guardFactoryWith;
136 sub printFunctionInits
138 my ($F, @names) = @_;
139 for my $name (@names) {
140 print F " gFunctionMap->set(${name}Tag.localName().impl(), ${name}Constructor);\n";
144 sub svgCapitalizationHacks
148 if ($name =~ /^fe(.+)$/) {
149 $name = "FE" . ucfirst $1;
151 $name =~ s/kern/Kern/;
152 $name =~ s/mpath/MPath/;
154 $name =~ s/tref/TRef/;
155 $name =~ s/tspan/TSpan/;
164 $name = svgCapitalizationHacks($name) if ($namespace eq "SVG");
166 while ($name =~ /^(.*?)_(.*)/) {
167 $name = $1 . ucfirst $2;
170 return ucfirst $name;
173 sub printLicenseHeader
177 * THIS FILE IS AUTOMATICALLY GENERATED, DO NOT EDIT.
180 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
182 * Redistribution and use in source and binary forms, with or without
183 * modification, are permitted provided that the following conditions
185 * 1. Redistributions of source code must retain the above copyright
186 * notice, this list of conditions and the following disclaimer.
187 * 2. Redistributions in binary form must reproduce the above copyright
188 * notice, this list of conditions and the following disclaimer in the
189 * documentation and/or other materials provided with the distribution.
191 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
192 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
193 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
194 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
195 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
196 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
197 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
198 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
199 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
200 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
201 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
208 sub printNamesHeaderFile
210 my ($headerPath) = shift;
212 open F, ">$headerPath";
214 printLicenseHeader($F);
215 print F "#ifndef DOM_${namespace}NAMES_H\n";
216 print F "#define DOM_${namespace}NAMES_H\n\n";
217 print F "#include \"QualifiedName.h\"\n\n";
219 print F "namespace $cppNamespace { namespace ${namespace}Names {\n\n";
221 my $lowerNamespace = lc($namespacePrefix);
222 print F "#ifndef DOM_${namespace}NAMES_HIDE_GLOBALS\n";
223 print F "// Namespace\n";
224 print F "extern const WebCore::AtomicString ${lowerNamespace}NamespaceURI;\n\n";
228 printMacros($F, "extern const WebCore::QualifiedName", "Tag", @tags);
229 print F "\n\nWebCore::QualifiedName** get${namespace}Tags(size_t* size);\n";
232 if (scalar(@attrs)) {
233 print F "// Attributes\n";
234 printMacros($F, "extern const WebCore::QualifiedName", "Attr", @attrs);
235 print F "\n\nWebCore::QualifiedName** get${namespace}Attr(size_t* size);\n";
237 print F "#endif\n\n";
238 print F "void init();\n\n";
240 print F "#endif\n\n";
245 sub printNamesCppFile
251 printLicenseHeader($F);
253 my $lowerNamespace = lc($namespacePrefix);
255 print F "#include \"config.h\"\n";
257 print F "#ifdef AVOID_STATIC_CONSTRUCTORS\n";
258 print F "#define DOM_${namespace}NAMES_HIDE_GLOBALS 1\n";
260 print F "#define QNAME_DEFAULT_CONSTRUCTOR 1\n";
261 print F "#endif\n\n";
264 print F "#include \"${namespace}Names.h\"\n\n";
265 print F "#include \"StaticConstructors.h\"\n";
267 print F "namespace $cppNamespace { namespace ${namespace}Names {
269 using namespace WebCore;
271 DEFINE_GLOBAL(AtomicString, ${lowerNamespace}NamespaceURI, \"$namespaceURI\")
276 for my $name (@tags) {
277 print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Tag, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n";
280 print F "\n\nWebCore::QualifiedName** get${namespace}Tags(size_t* size)\n";
281 print F "{\n static WebCore::QualifiedName* ${namespace}Tags[] = {\n";
282 for my $name (@tags) {
283 print F " (WebCore::QualifiedName*)&${name}Tag,\n";
286 print F " *size = ", scalar(@tags), ";\n";
287 print F " return ${namespace}Tags;\n";
292 if (scalar(@attrs)) {
293 print F "\n// Attributes\n";
294 for my $name (@attrs) {
295 print F "DEFINE_GLOBAL(QualifiedName, ", $name, "Attr, nullAtom, \"$name\", ${lowerNamespace}NamespaceURI);\n";
297 print F "\n\nWebCore::QualifiedName** get${namespace}Attrs(size_t* size)\n";
298 print F "{\n static WebCore::QualifiedName* ${namespace}Attr[] = {\n";
299 for my $name (@attrs) {
300 print F " (WebCore::QualifiedName*)&${name}Attr,\n";
303 print F " *size = ", scalar(@attrs), ";\n";
304 print F " return ${namespace}Attr;\n";
308 print F "\nvoid init()
310 static bool initialized = false;
315 // Use placement new to initialize the globals.
317 AtomicString::init();
320 print(F " AtomicString ${lowerNamespace}NS(\"$namespaceURI\");\n\n");
322 print(F " // Namespace\n");
323 print(F " new ((void*)&${lowerNamespace}NamespaceURI) AtomicString(${lowerNamespace}NS);\n\n");
325 my $tagsNamespace = $tagsNullNamespace ? "nullAtom" : "${lowerNamespace}NS";
326 printDefinitions($F, \@tags, "tags", $tagsNamespace);
328 if (scalar(@attrs)) {
329 my $attrsNamespace = $attrsNullNamespace ? "nullAtom" : "${lowerNamespace}NS";
330 printDefinitions($F, \@attrs, "attributes", $attrsNamespace);
333 print F "}\n\n} }\n\n";
337 sub printElementIncludes
339 my ($F, @names) = @_;
340 for my $name (@names) {
341 my $upperCase = upperCaseName($name);
342 print F "#include \"${namespace}${upperCase}Element.h\"\n";
348 my ($F, $namesRef, $type, $namespaceURI) = @_;
349 my $singularType = substr($type, 0, -1);
350 my $shortType = substr($singularType, 0, 4);
351 my $shortCamelType = ucfirst($shortType);
352 my $shortUpperType = uc($shortType);
354 print F " // " . ucfirst($type) . "\n";
356 for my $name (@$namesRef) {
357 print F " const char *$name","${shortCamelType}String = \"$name\";\n";
360 for my $name (@$namesRef) {
362 my $realName = $name;
363 $realName =~ s/_/-/g;
364 print F " ${name}${shortCamelType}String = \"$realName\";\n";
369 for my $name (@$namesRef) {
370 print F " new ((void*)&$name","${shortCamelType}) QualifiedName(nullAtom, $name","${shortCamelType}String, $namespaceURI);\n";
375 sub printFactoryCppFile
381 printLicenseHeader($F);
385 #include "${namespace}ElementFactory.h"
386 #include "${namespace}Names.h"
388 #include "Settings.h"
392 printElementIncludes($F, @tags);
395 #include <wtf/HashMap.h>
397 using namespace WebCore;
398 using namespace ${cppNamespace}::${namespace}Names;
400 typedef ${namespace}Element *(*ConstructorFunc)(Document *doc, bool createdByParser);
401 typedef WTF::HashMap<AtomicStringImpl*, ConstructorFunc> FunctionMap;
403 static FunctionMap *gFunctionMap = 0;
405 namespace ${cppNamespace} {
410 printConstructors($F, @tags);
412 print F "#if $guardFactoryWith\n" if $guardFactoryWith;
415 static inline void createFunctionMapIfNecessary()
420 gFunctionMap = new FunctionMap;
422 // Populate it with constructor functions.
426 printFunctionInits($F, @tags);
429 print F "#endif\n\n" if $guardFactoryWith;
432 ${namespace}Element *${namespace}ElementFactory::create${namespace}Element(const QualifiedName& qName, Document* doc, bool createdByParser)
437 print F "#if $guardFactoryWith\n" if $guardFactoryWith;
440 // Don't make elements without a document
444 #if ENABLE(DASHBOARD_SUPPORT)
445 Settings* settings = doc->settings();
446 if (settings && settings->usesDashboardBackwardCompatibilityMode())
450 createFunctionMapIfNecessary();
451 ConstructorFunc func = gFunctionMap->get(qName.localName().impl());
453 return func(doc, createdByParser);
455 return new ${namespace}Element(qName, doc);
459 if ($guardFactoryWith) {
481 sub printFactoryHeaderFile
483 my $headerPath = shift;
485 open F, ">$headerPath";
487 printLicenseHeader($F);
489 print F "#ifndef ${namespace}ELEMENTFACTORY_H\n";
490 print F "#define ${namespace}ELEMENTFACTORY_H\n\n";
500 namespace ${cppNamespace}
502 class ${namespace}Element;
504 // The idea behind this class is that there will eventually be a mapping from namespace URIs to ElementFactories that can dispense
505 // elements. In a compound document world, the generic createElement function (will end up being virtual) will be called.
506 class ${namespace}ElementFactory
509 WebCore::Element *createElement(const WebCore::QualifiedName& qName, WebCore::Document *doc, bool createdByParser = true);
510 static ${namespace}Element *create${namespace}Element(const WebCore::QualifiedName& qName, WebCore::Document *doc, bool createdByParser = true);