Home | History | Annotate | Download | only in scripts
      1 # Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl (at] lkcl.net>
      2 # Copyright (C) 2008 Martin Soto <soto (at] freedesktop.org>
      3 # Copyright (C) 2008 Alp Toker <alp (at] atoker.com>
      4 # Copyright (C) 2009 Adam Dingle <adam (at] yorba.org>
      5 # Copyright (C) 2009 Jim Nelson <jim (at] yorba.org>
      6 # Copyright (C) 2009, 2010 Igalia S.L.
      7 #
      8 # This library is free software; you can redistribute it and/or
      9 # modify it under the terms of the GNU Library General Public
     10 # License as published by the Free Software Foundation; either
     11 # version 2 of the License, or (at your option) any later version.
     12 #
     13 # This library is distributed in the hope that it will be useful,
     14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16 # Library General Public License for more details.
     17 #
     18 # You should have received a copy of the GNU Library General Public License
     19 # along with this library; see the file COPYING.LIB.  If not, write to
     20 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     21 # Boston, MA 02111-1307, USA.
     22 
     23 package CodeGeneratorGObject;
     24 
     25 # Global Variables
     26 my %implIncludes = ();
     27 my %hdrIncludes = ();
     28 
     29 my $defineTypeMacro = "G_DEFINE_TYPE";
     30 my $defineTypeInterfaceImplementation = ")";
     31 my @txtEventListeners = ();
     32 my @txtInstallEventListeners = ();
     33 my @txtInstallSignals = ();
     34 my @txtInstallProps = ();
     35 my @txtSetProps = ();
     36 my @txtGetProps = ();
     37 
     38 my $className = "";
     39 
     40 # Default constructor
     41 sub new {
     42     my $object = shift;
     43     my $reference = { };
     44 
     45     $codeGenerator = shift;
     46     $outputDir = shift;
     47     mkdir $outputDir;
     48 
     49     bless($reference, $object);
     50 }
     51 
     52 sub finish {
     53 }
     54 
     55 my $licenceTemplate = << "EOF";
     56 /*
     57     This file is part of the WebKit open source project.
     58     This file has been generated by generate-bindings.pl. DO NOT MODIFY!
     59 
     60     This library is free software; you can redistribute it and/or
     61     modify it under the terms of the GNU Library General Public
     62     License as published by the Free Software Foundation; either
     63     version 2 of the License, or (at your option) any later version.
     64 
     65     This library is distributed in the hope that it will be useful,
     66     but WITHOUT ANY WARRANTY; without even the implied warranty of
     67     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     68     Library General Public License for more details.
     69 
     70     You should have received a copy of the GNU Library General Public License
     71     along with this library; see the file COPYING.LIB.  If not, write to
     72     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     73     Boston, MA 02110-1301, USA.
     74 */
     75 EOF
     76 
     77 sub GenerateModule {
     78 }
     79 
     80 sub GetParentClassName {
     81     my $dataNode = shift;
     82 
     83     return "WebKitDOMObject" if @{$dataNode->parents} eq 0;
     84     return "WebKitDOM" . $codeGenerator->StripModule($dataNode->parents(0));
     85 }
     86 
     87 # From String::CamelCase 0.01
     88 sub camelize
     89 {
     90         my $s = shift;
     91         join('', map{ ucfirst $_ } split(/(?<=[A-Za-z])_(?=[A-Za-z])|\b/, $s));
     92 }
     93 
     94 sub decamelize
     95 {
     96         my $s = shift;
     97         $s =~ s{([^a-zA-Z]?)([A-Z]*)([A-Z])([a-z]?)}{
     98                 my $fc = pos($s)==0;
     99                 my ($p0,$p1,$p2,$p3) = ($1,lc$2,lc$3,$4);
    100                 my $t = $p0 || $fc ? $p0 : '_';
    101                 $t .= $p3 ? $p1 ? "${p1}_$p2$p3" : "$p2$p3" : "$p1$p2";
    102                 $t;
    103         }ge;
    104         $s;
    105 }
    106 
    107 sub FixUpDecamelizedName {
    108     my $classname = shift;
    109 
    110     # FIXME: try to merge this somehow with the fixes in ClassNameToGobjectType
    111     $classname =~ s/x_path/xpath/;
    112     $classname =~ s/web_kit/webkit/;
    113     $classname =~ s/htmli_frame/html_iframe/;
    114 
    115     return $classname;
    116 }
    117 
    118 sub ClassNameToGObjectType {
    119     my $className = shift;
    120     my $CLASS_NAME = uc(decamelize($className));
    121     # Fixup: with our prefix being 'WebKitDOM' decamelize can't get
    122     # WebKitDOMCSS and similar names right, so we have to fix it
    123     # manually.
    124     $CLASS_NAME =~ s/DOMCSS/DOM_CSS/;
    125     $CLASS_NAME =~ s/DOMHTML/DOM_HTML/;
    126     $CLASS_NAME =~ s/DOMDOM/DOM_DOM/;
    127     $CLASS_NAME =~ s/DOMCDATA/DOM_CDATA/;
    128     $CLASS_NAME =~ s/DOMX_PATH/DOM_XPATH/;
    129     $CLASS_NAME =~ s/DOM_WEB_KIT/DOM_WEBKIT/;
    130     $CLASS_NAME =~ s/DOMUI/DOM_UI/;
    131     $CLASS_NAME =~ s/HTMLI_FRAME/HTML_IFRAME/;
    132     return $CLASS_NAME;
    133 }
    134 
    135 sub GetParentGObjType {
    136     my $dataNode = shift;
    137 
    138     return "WEBKIT_TYPE_DOM_OBJECT" if @{$dataNode->parents} eq 0;
    139     return "WEBKIT_TYPE_DOM_" . ClassNameToGObjectType($codeGenerator->StripModule($dataNode->parents(0)));
    140 }
    141 
    142 sub GetClassName {
    143     my $name = $codeGenerator->StripModule(shift);
    144 
    145     return "WebKitDOM$name";
    146 }
    147 
    148 sub GetCoreObject {
    149     my ($interfaceName, $name, $parameter) = @_;
    150 
    151     return "WebCore::${interfaceName}* $name = WebKit::core($parameter);";
    152 }
    153 
    154 sub SkipAttribute {
    155     my $attribute = shift;
    156     
    157     if ($attribute->signature->extendedAttributes->{"CustomGetter"} ||
    158         $attribute->signature->extendedAttributes->{"CustomSetter"} ||
    159         $attribute->signature->extendedAttributes->{"Replaceable"}) {
    160         return 1;
    161     }
    162     
    163     my $propType = $attribute->signature->type;
    164     if ($propType =~ /Constructor$/) {
    165         return 1;
    166     }
    167 
    168     # This is for DOMWindow.idl location attribute
    169     if ($attribute->signature->name eq "location") {
    170         return 1;
    171     }
    172 
    173     # This is for HTMLInput.idl valueAsDate
    174     if ($attribute->signature->name eq "valueAsDate") {
    175         return 1;
    176     }
    177 
    178     # This is for DOMWindow.idl Crypto attribute
    179     if ($attribute->signature->type eq "Crypto") {
    180         return 1;
    181     }
    182 
    183     return 0;
    184 }
    185 
    186 sub SkipFunction {
    187     my $function = shift;
    188     my $decamelize = shift;
    189     my $prefix = shift;
    190 
    191     my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($function->signature->name);
    192     my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"} ||
    193         $function->signature->extendedAttributes->{"CustomArgumentHandling"};
    194 
    195     if ($isCustomFunction &&
    196         $functionName ne "webkit_dom_node_replace_child" &&
    197         $functionName ne "webkit_dom_node_insert_before" &&
    198         $functionName ne "webkit_dom_node_remove_child" &&
    199         $functionName ne "webkit_dom_node_append_child" &&
    200         $functionName ne "webkit_dom_html_collection_item" &&
    201         $functionName ne "webkit_dom_html_collection_named_item") {
    202         return 1;
    203     }
    204 
    205     if ($function->signature->name eq "getSVGDocument") {
    206         return 1;
    207     }
    208 
    209     if ($function->signature->name eq "getCSSCanvasContext") {
    210         return 1;
    211     }
    212 
    213     # Skip functions that have ["Callback"] parameters, because this
    214     # code generator doesn't know how to auto-generate callbacks.
    215     # Skip functions that have "MediaQueryListListener" parameters, because this
    216     # code generator doesn't know how to auto-generate MediaQueryListListener.
    217     foreach my $param (@{$function->parameters}) {
    218         if ($param->extendedAttributes->{"Callback"} ||
    219             $param->type eq "MediaQueryListListener") {
    220             return 1;
    221         }
    222     }
    223 
    224     return 0;
    225 }
    226 
    227 # Name type used in the g_value_{set,get}_* functions
    228 sub GetGValueTypeName {
    229     my $type = shift;
    230 
    231     my %types = ("DOMString", "string",
    232                  "DOMTimeStamp", "uint",
    233                  "float", "float",
    234                  "double", "double",
    235                  "boolean", "boolean",
    236                  "char", "char",
    237                  "long", "long",
    238                  "long long", "int64",
    239                  "short", "int",
    240                  "uchar", "uchar",
    241                  "unsigned", "uint",
    242                  "int", "int",
    243                  "unsigned int", "uint",
    244                  "unsigned long long", "uint64", 
    245                  "unsigned long", "ulong",
    246                  "unsigned short", "ushort");
    247 
    248     return $types{$type} ? $types{$type} : "object";
    249 }
    250 
    251 # Name type used in C declarations
    252 sub GetGlibTypeName {
    253     my $type = shift;
    254     my $name = GetClassName($type);
    255 
    256     my %types = ("DOMString", "gchar*",
    257                  "DOMTimeStamp", "guint32",
    258                  "CompareHow", "gushort",
    259                  "float", "gfloat",
    260                  "double", "gdouble",
    261                  "boolean", "gboolean",
    262                  "char", "gchar",
    263                  "long", "glong",
    264                  "long long", "gint64",
    265                  "short", "gshort",
    266                  "uchar", "guchar",
    267                  "unsigned", "guint",
    268                  "int", "gint",
    269                  "unsigned int", "guint",
    270                  "unsigned long", "gulong",
    271                  "unsigned long long", "guint64",
    272                  "unsigned short", "gushort",
    273                  "void", "void");
    274 
    275     return $types{$type} ? $types{$type} : "$name*";
    276 }
    277 
    278 sub IsGDOMClassType {
    279     my $type = shift;
    280 
    281     return 0 if $codeGenerator->IsNonPointerType($type) || $codeGenerator->IsStringType($type);
    282     return 1;
    283 }
    284 
    285 sub GetReadableProperties {
    286     my $properties = shift;
    287 
    288     my @result = ();
    289 
    290     foreach my $property (@{$properties}) {
    291         if (!SkipAttribute($property)) {
    292             push(@result, $property);
    293         }
    294     }
    295 
    296     return @result;
    297 }
    298 
    299 sub GetWriteableProperties {
    300     my $properties = shift;
    301     my @result = ();
    302 
    303     foreach my $property (@{$properties}) {
    304         my $writeable = $property->type !~ /^readonly/;
    305         my $gtype = GetGValueTypeName($property->signature->type);
    306         my $hasGtypeSignature = ($gtype eq "boolean" || $gtype eq "float" || $gtype eq "double" ||
    307                                  $gtype eq "uint64" || $gtype eq "ulong" || $gtype eq "long" || 
    308                                  $gtype eq "uint" || $gtype eq "ushort" || $gtype eq "uchar" ||
    309                                  $gtype eq "char" || $gtype eq "string");
    310         if ($writeable && $hasGtypeSignature) {
    311             push(@result, $property);
    312         }
    313     }
    314 
    315     return @result;
    316 }
    317 
    318 sub GenerateConditionalString
    319 {
    320     my $node = shift;
    321     my $conditional = $node->extendedAttributes->{"Conditional"};
    322     if ($conditional) {
    323         if ($conditional =~ /&/) {
    324             return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")";
    325         } elsif ($conditional =~ /\|/) {
    326             return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")";
    327         } else {
    328             return "ENABLE(" . $conditional . ")";
    329         }
    330     } else {
    331         return "";
    332     }
    333 }
    334 
    335 sub GenerateProperty {
    336     my $attribute = shift;
    337     my $interfaceName = shift;
    338     my @writeableProperties = @{shift @_};
    339 
    340     my $conditionalString = GenerateConditionalString($attribute->signature);
    341     my $camelPropName = $attribute->signature->name;
    342     my $setPropNameFunction = $codeGenerator->WK_ucfirst($camelPropName);
    343     my $getPropNameFunction = $codeGenerator->WK_lcfirst($camelPropName);
    344 
    345     my $propName = decamelize($camelPropName);
    346     my $propNameCaps = uc($propName);
    347     $propName =~ s/_/-/g;
    348     my ${propEnum} = "PROP_${propNameCaps}";
    349     push(@cBodyPriv, "#if ${conditionalString}\n") if $conditionalString;
    350     push(@cBodyPriv, "    ${propEnum},\n");
    351     push(@cBodyPriv, "#endif /* ${conditionalString} */\n") if $conditionalString;
    352 
    353     my $propType = $attribute->signature->type;
    354     my ${propGType} = decamelize($propType);
    355     my ${ucPropGType} = uc($propGType);
    356 
    357     my $gtype = GetGValueTypeName($propType);
    358     my $gparamflag = "WEBKIT_PARAM_READABLE";
    359     my $writeable = $attribute->type !~ /^readonly/;
    360     my $const = "read-only ";
    361     my $custom = $attribute->signature->extendedAttributes->{"Custom"};
    362     if ($writeable && $custom) {
    363         $const = "read-only (due to custom functions needed in webkitdom)";
    364         return;
    365     }
    366     if ($writeable && !$custom) {
    367         $gparamflag = "WEBKIT_PARAM_READWRITE";
    368         $const = "read-write ";
    369     }
    370 
    371     my $type = GetGlibTypeName($propType);
    372     $nick = decamelize("${interfaceName}_${propName}");
    373     $long = "${const} ${type} ${interfaceName}.${propName}";
    374 
    375     my $convertFunction = "";
    376     if ($gtype eq "string") {
    377         $convertFunction = "WTF::String::fromUTF8";
    378     }
    379 
    380     my $getterExpressionPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
    381     my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute);
    382 
    383     my $getterContentHead = "coreSelf->$getterExpressionPrefix";
    384     my $setterContentHead = "coreSelf->$setterExpressionPrefix${convertFunction}(g_value_get_$gtype(value))";
    385 
    386     if (grep {$_ eq $attribute} @writeableProperties) {
    387         push(@txtSetProps, "#if ${conditionalString}\n") if $conditionalString;
    388         push(@txtSetProps, "    case ${propEnum}:\n    {\n");
    389         push(@txtSetProps, "        WebCore::ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
    390         push(@txtSetProps, "        ${setterContentHead}");
    391         push(@txtSetProps, ", ec") if @{$attribute->setterExceptions};
    392         push(@txtSetProps, ");\n");
    393         push(@txtSetProps, "        break;\n    }\n");
    394         push(@txtSetProps, "#endif /* ${conditionalString} */\n") if $conditionalString;
    395     }
    396 
    397     push(@txtGetProps, "#if ${conditionalString}\n") if $conditionalString;
    398     push(@txtGetProps, "    case ${propEnum}:\n    {\n");
    399 
    400     my $exception = "";
    401     if (@{$attribute->getterExceptions}) {
    402         $exception = "ec";
    403         push(@txtGetProps, "        WebCore::ExceptionCode ec = 0;\n");
    404     }
    405 
    406     my $postConvertFunction = "";
    407     my $done = 0;
    408     if ($gtype eq "string") {
    409         push(@txtGetProps, "        g_value_take_string(value, convertToUTF8String(${getterContentHead}${exception})));\n");
    410         $done = 1;
    411     } elsif ($gtype eq "object") {
    412         $txtGetProp = << "EOF";
    413         RefPtr<WebCore::${propType}> ptr = coreSelf->${getPropNameFunction}(${exception});
    414         g_value_set_object(value, WebKit::kit(ptr.get()));
    415 EOF
    416         push(@txtGetProps, $txtGetProp);
    417         $done = 1;
    418     }
    419 
    420     # FIXME: get rid of this glitch?
    421     my $_gtype = $gtype;
    422     if ($gtype eq "ushort") {
    423         $_gtype = "uint";
    424     }
    425 
    426     if (!$done) {
    427         push(@txtGetProps, "        g_value_set_$_gtype(value, ${convertFunction}coreSelf->${getterExpressionPrefix}${exception})${postConvertFunction});\n");
    428     }
    429 
    430     push(@txtGetProps, "        break;\n    }\n");
    431     push(@txtGetProps, "#endif /* ${conditionalString} */\n") if $conditionalString;
    432 
    433     my %param_spec_options = ("int", "G_MININT, /* min */\nG_MAXINT, /* max */\n0, /* default */",
    434                               "boolean", "FALSE, /* default */",
    435                               "float", "-G_MAXFLOAT, /* min */\nG_MAXFLOAT, /* max */\n0.0, /* default */",
    436                               "double", "-G_MAXDOUBLE, /* min */\nG_MAXDOUBLE, /* max */\n0.0, /* default */",
    437                               "uint64", "0, /* min */\nG_MAXUINT64, /* min */\n0, /* default */",
    438                               "long", "G_MINLONG, /* min */\nG_MAXLONG, /* max */\n0, /* default */",
    439                               "int64", "G_MININT64, /* min */\nG_MAXINT64, /* max */\n0, /* default */",
    440                               "ulong", "0, /* min */\nG_MAXULONG, /* max */\n0, /* default */",
    441                               "uint", "0, /* min */\nG_MAXUINT, /* max */\n0, /* default */",
    442                               "ushort", "0, /* min */\nG_MAXUINT16, /* max */\n0, /* default */",
    443                               "uchar", "G_MININT8, /* min */\nG_MAXINT8, /* max */\n0, /* default */",
    444                               "char", "0, /* min */\nG_MAXUINT8, /* max */\n0, /* default */",
    445                               "string", "\"\", /* default */",
    446                               "object", "WEBKIT_TYPE_DOM_${ucPropGType}, /* gobject type */");
    447 
    448     my $txtInstallProp = << "EOF";
    449     g_object_class_install_property(gobjectClass,
    450                                     ${propEnum},
    451                                     g_param_spec_${_gtype}("${propName}", /* name */
    452                                                            "$nick", /* short description */
    453                                                            "$long", /* longer - could do with some extra doc stuff here */
    454                                                            $param_spec_options{$gtype}
    455                                                            ${gparamflag}));
    456 EOF
    457     push(@txtInstallProps, "#if ${conditionalString}\n") if $conditionalString;
    458     push(@txtInstallProps, $txtInstallProp);
    459     push(@txtInstallProps, "#endif /* ${conditionalString} */\n") if $conditionalString;
    460 }
    461 
    462 sub GenerateProperties {
    463     my ($object, $interfaceName, $dataNode) = @_;
    464 
    465     my $clsCaps = substr(ClassNameToGObjectType($className), 12);
    466     my $lowerCaseIfaceName = "webkit_dom_" . (FixUpDecamelizedName(decamelize($interfaceName)));
    467 
    468     # Properties
    469     my $implContent = "";
    470 
    471     # Properties
    472     $implContent = << "EOF";
    473 enum {
    474     PROP_0,
    475 EOF
    476     push(@cBodyPriv, $implContent);
    477 
    478     my @readableProperties = GetReadableProperties($dataNode->attributes);
    479 
    480     my $privFunction = GetCoreObject($interfaceName, "coreSelf", "self");
    481 
    482     my $txtGetProp = << "EOF";
    483 static void ${lowerCaseIfaceName}_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
    484 {
    485     WebCore::JSMainThreadNullState state;
    486 EOF
    487     push(@txtGetProps, $txtGetProp);
    488     if (scalar @readableProperties > 0) {
    489         $txtGetProp = << "EOF";
    490     ${className}* self = WEBKIT_DOM_${clsCaps}(object);
    491     $privFunction
    492 EOF
    493     push(@txtGetProps, $txtGetProp);
    494     }
    495 
    496     $txtGetProp = << "EOF";
    497     switch (prop_id) {
    498 EOF
    499     push(@txtGetProps, $txtGetProp);
    500 
    501     my @writeableProperties = GetWriteableProperties(\@readableProperties);
    502 
    503     my $txtSetProps = << "EOF";
    504 static void ${lowerCaseIfaceName}_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
    505 {
    506     WebCore::JSMainThreadNullState state;
    507 EOF
    508     push(@txtSetProps, $txtSetProps);
    509 
    510     if (scalar @writeableProperties > 0) {
    511         $txtSetProps = << "EOF";
    512     ${className}* self = WEBKIT_DOM_${clsCaps}(object);
    513     $privFunction
    514 EOF
    515         push(@txtSetProps, $txtSetProps);
    516     }
    517 
    518     $txtSetProps = << "EOF";
    519     switch (prop_id) {
    520 EOF
    521     push(@txtSetProps, $txtSetProps);
    522 
    523     foreach my $attribute (@readableProperties) {
    524         if ($attribute->signature->type ne "EventListener" &&
    525             $attribute->signature->type ne "MediaQueryListListener") {
    526             GenerateProperty($attribute, $interfaceName, \@writeableProperties);
    527         }
    528     }
    529 
    530     push(@cBodyPriv, "};\n\n");
    531 
    532     $txtGetProp = << "EOF";
    533     default:
    534         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    535         break;
    536     }
    537 }
    538 EOF
    539     push(@txtGetProps, $txtGetProp);
    540 
    541     $txtSetProps = << "EOF";
    542     default:
    543         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    544         break;
    545     }
    546 }
    547 EOF
    548     push(@txtSetProps, $txtSetProps);
    549 
    550     # Do not insert extra spaces when interpolating array variables
    551     $" = "";
    552 
    553     $implContent = << "EOF";
    554 
    555 static void ${lowerCaseIfaceName}_finalize(GObject* object)
    556 {
    557     WebKitDOMObject* dom_object = WEBKIT_DOM_OBJECT(object);
    558     
    559     if (dom_object->coreObject) {
    560         WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName} *>(dom_object->coreObject);
    561 
    562         WebKit::DOMObjectCache::forget(coreObject);
    563         coreObject->deref();
    564 
    565         dom_object->coreObject = NULL;
    566     }
    567 
    568     G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->finalize(object);
    569 }
    570 
    571 @txtSetProps
    572 
    573 @txtGetProps
    574 
    575 static void ${lowerCaseIfaceName}_constructed(GObject* object)
    576 {
    577 EOF
    578     push(@cBodyPriv, $implContent);
    579 
    580     $implContent = << "EOF";
    581 @txtInstallEventListeners
    582     if (G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->constructed)
    583         G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->constructed(object);
    584 }
    585 
    586 static void ${lowerCaseIfaceName}_class_init(${className}Class* requestClass)
    587 {
    588     GObjectClass *gobjectClass = G_OBJECT_CLASS(requestClass);
    589     gobjectClass->finalize = ${lowerCaseIfaceName}_finalize;
    590     gobjectClass->set_property = ${lowerCaseIfaceName}_set_property;
    591     gobjectClass->get_property = ${lowerCaseIfaceName}_get_property;
    592     gobjectClass->constructed = ${lowerCaseIfaceName}_constructed;
    593 
    594 @txtInstallProps
    595 @txtInstallSignals
    596 }
    597 
    598 static void ${lowerCaseIfaceName}_init(${className}* request)
    599 {
    600 }
    601 
    602 EOF
    603     push(@cBodyPriv, $implContent);
    604 }
    605 
    606 sub GenerateHeader {
    607     my ($object, $interfaceName, $parentClassName) = @_;
    608 
    609     my $implContent = "";
    610 
    611     # Add the default header template
    612     @hPrefix = split("\r", $licenceTemplate);
    613     push(@hPrefix, "\n");
    614 
    615     #Header guard
    616     my $guard = $className . "_h";
    617 
    618     @hPrefixGuard = << "EOF";
    619 #ifndef $guard
    620 #define $guard
    621 
    622 EOF
    623 
    624     $implContent = << "EOF";
    625 G_BEGIN_DECLS
    626 EOF
    627 
    628     push(@hBodyPre, $implContent);
    629 
    630     my $decamelize = FixUpDecamelizedName(decamelize($interfaceName));
    631     my $clsCaps = uc($decamelize);
    632     my $lowerCaseIfaceName = "webkit_dom_" . ($decamelize);
    633 
    634     $implContent = << "EOF";
    635 #define WEBKIT_TYPE_DOM_${clsCaps}            (${lowerCaseIfaceName}_get_type())
    636 #define WEBKIT_DOM_${clsCaps}(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className}))
    637 #define WEBKIT_DOM_${clsCaps}_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class)
    638 #define WEBKIT_DOM_IS_${clsCaps}(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_${clsCaps}))
    639 #define WEBKIT_DOM_IS_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_DOM_${clsCaps}))
    640 #define WEBKIT_DOM_${clsCaps}_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class))
    641 
    642 struct _${className} {
    643     ${parentClassName} parent_instance;
    644 };
    645 
    646 struct _${className}Class {
    647     ${parentClassName}Class parent_class;
    648 };
    649 
    650 WEBKIT_API GType
    651 ${lowerCaseIfaceName}_get_type (void);
    652 
    653 EOF
    654 
    655     push(@hBody, $implContent);
    656 }
    657 
    658 sub getIncludeHeader {
    659     my $type = shift;
    660     my $name = GetClassName($type);
    661 
    662     return "" if $type eq "int";
    663     return "" if $type eq "long";
    664     return "" if $type eq "long long";
    665     return "" if $type eq "short";
    666     return "" if $type eq "char";
    667     return "" if $type eq "float";
    668     return "" if $type eq "double";
    669     return "" if $type eq "unsigned";
    670     return "" if $type eq "unsigned int";
    671     return "" if $type eq "unsigned long";
    672     return "" if $type eq "unsigned long long";
    673     return "" if $type eq "unsigned short";
    674     return "" if $type eq "DOMTimeStamp";
    675     return "" if $type eq "EventListener";
    676     return "" if $type eq "MediaQueryListListener";
    677     return "" if $type eq "unsigned char";
    678     return "" if $type eq "DOMString";
    679     return "" if $type eq "float";
    680     return "" if $type eq "boolean";
    681     return "" if $type eq "void";
    682     return "" if $type eq "CompareHow";
    683 
    684     return "$name.h";
    685 }
    686 
    687 sub addIncludeInBody {
    688     my $type = shift;
    689 
    690     if ($type eq "DOMObject") {
    691         return;
    692     }
    693 
    694     my $header = getIncludeHeader($type);
    695     if ($header eq "") {
    696         return;
    697     }
    698     
    699     if (IsGDOMClassType($type)) {
    700         $implIncludes{"webkit/$header"} = 1;
    701     } else {
    702         $implIncludes{$header} = 1
    703     }
    704 }
    705 
    706 sub GenerateFunction {
    707     my ($object, $interfaceName, $function, $prefix) = @_;
    708 
    709     my $decamelize = FixUpDecamelizedName(decamelize($interfaceName));
    710 
    711     if ($object eq "MediaQueryListListener") {
    712         return;
    713     }
    714 
    715     if (SkipFunction($function, $decamelize, $prefix)) {
    716         return;
    717     }
    718 
    719     my $functionSigName = $function->signature->name;
    720     my $functionSigType = $prefix eq "set_" ? "void" : $function->signature->type;
    721     my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($functionSigName);
    722     my $returnType = GetGlibTypeName($functionSigType);
    723     my $returnValueIsGDOMType = IsGDOMClassType($functionSigType);
    724     my $conditionalString = GenerateConditionalString($function->signature);
    725 
    726     my $functionSig = "${className}* self";
    727 
    728     my $callImplParams = "";
    729 
    730     # skip some custom functions for now
    731     my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"} ||
    732                        $function->signature->extendedAttributes->{"CustomArgumentHandling"};
    733 
    734     foreach my $param (@{$function->parameters}) {
    735         my $paramIDLType = $param->type;
    736         if ($paramIDLType eq "EventListener" || $paramIDLType eq "MediaQueryListListener") {
    737             # EventListeners are handled elsewhere.
    738             return;
    739         }
    740         addIncludeInBody($paramIDLType);
    741         my $paramType = GetGlibTypeName($paramIDLType);
    742         my $const = $paramType eq "gchar*" ? "const " : "";
    743         my $paramName = decamelize($param->name);
    744 
    745         $functionSig .= ", ${const}$paramType $paramName";
    746 
    747         my $paramIsGDOMType = IsGDOMClassType($paramIDLType);
    748         if ($paramIsGDOMType) {
    749             if ($paramIDLType ne "DOMObject") {
    750                 $implIncludes{"webkit/WebKitDOM${paramIDLType}Private.h"} = 1;
    751             }
    752         }
    753         if ($paramIsGDOMType || ($paramIDLType eq "DOMString") || ($paramIDLType eq "CompareHow")) {
    754             $paramName = "converted_" . $paramName;
    755         }
    756         if ($callImplParams) {
    757             $callImplParams .= ", $paramName";
    758         } else {
    759             $callImplParams = "$paramName";
    760         }
    761     }
    762 
    763     # Not quite sure what to do with this yet, but we need to take into
    764     # account the difference in parameters between the IDL file and the
    765     # actual implementation.
    766     if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) {
    767         $functionSig .= ", gboolean isUserGesture";
    768         $callImplParams .= ", " if $callImplParams;
    769         $callImplParams .= "false";
    770     }
    771 
    772     if ($returnType ne "void" && $returnValueIsGDOMType && $functionSigType ne "DOMObject") {
    773         if ($functionSigType ne "EventTarget") {
    774             $implIncludes{"webkit/WebKitDOM${functionSigType}Private.h"} = 1;
    775             $implIncludes{"webkit/WebKitDOM${functionSigType}.h"} = 1;
    776         } else {
    777             $implIncludes{"WebKitDOM${functionSigType}.h"} = 1;
    778         }
    779 
    780         $implIncludes{"${functionSigType}.h"} = 1;
    781     }
    782 
    783     if(@{$function->raisesExceptions}) {
    784         $functionSig .= ", GError **error";
    785     }
    786 
    787     push(@hBody, "WEBKIT_API $returnType\n$functionName($functionSig);\n");
    788     push(@hBody, "\n");
    789 
    790     push(@cBody, "$returnType\n$functionName($functionSig)\n{\n");
    791     push(@cBody, "#if ${conditionalString}\n") if $conditionalString;
    792 
    793     if ($returnType ne "void") {
    794         # TODO: return proper default result
    795         push(@cBody, "    g_return_val_if_fail(self, 0);\n");
    796     } else {
    797         push(@cBody, "    g_return_if_fail(self);\n");
    798     }
    799 
    800     push(@cBody, "    WebCore::JSMainThreadNullState state;\n");
    801 
    802     # The WebKit::core implementations check for NULL already; no need to
    803     # duplicate effort.
    804     push(@cBody, "    WebCore::${interfaceName} * item = WebKit::core(self);\n");
    805 
    806     foreach my $param (@{$function->parameters}) {
    807         my $paramName = decamelize($param->name);
    808         my $paramIDLType = $param->type;
    809         my $paramTypeIsPrimitive = $codeGenerator->IsPrimitiveType($paramIDLType);
    810         my $paramIsGDOMType = IsGDOMClassType($paramIDLType);
    811         if (!$paramTypeIsPrimitive) {
    812             if ($returnType ne "void") {
    813                 # TODO: return proper default result
    814                 # FIXME: Temporary hack for generating a proper implementation
    815                 #        of the webkit_dom_document_evaluate function (Bug-ID: 42115)
    816                 if (!(($functionName eq "webkit_dom_document_evaluate") && ($paramIDLType eq "XPathResult"))) {
    817                     push(@cBody, "    g_return_val_if_fail($paramName, 0);\n");
    818                 }
    819             } else {
    820                 push(@cBody, "    g_return_if_fail($paramName);\n");
    821             }
    822         }
    823     }
    824 
    825     $returnParamName = "";
    826     foreach my $param (@{$function->parameters}) {
    827         my $paramIDLType = $param->type;
    828         my $paramName = decamelize($param->name);
    829 
    830         my $paramIsGDOMType = IsGDOMClassType($paramIDLType);
    831         if ($paramIDLType eq "DOMString") {
    832             push(@cBody, "    WTF::String converted_${paramName} = WTF::String::fromUTF8($paramName);\n");
    833         } elsif ($paramIDLType eq "CompareHow") {
    834             push(@cBody, "    WebCore::Range::CompareHow converted_${paramName} = static_cast<WebCore::Range::CompareHow>($paramName);\n");
    835         } elsif ($paramIsGDOMType) {
    836             push(@cBody, "    WebCore::${paramIDLType} * converted_${paramName} = NULL;\n");
    837             push(@cBody, "    if (${paramName} != NULL) {\n");
    838             push(@cBody, "        converted_${paramName} = WebKit::core($paramName);\n");
    839 
    840             if ($returnType ne "void") {
    841                 # TODO: return proper default result
    842                 push(@cBody, "        g_return_val_if_fail(converted_${paramName}, 0);\n");
    843             } else {
    844                 push(@cBody, "        g_return_if_fail(converted_${paramName});\n");
    845             }
    846 
    847             push(@cBody, "    }\n");
    848         }
    849         $returnParamName = "converted_".$paramName if $param->extendedAttributes->{"Return"};
    850     }
    851 
    852     my $assign = "";
    853     my $assignPre = "";
    854     my $assignPost = "";
    855 
    856     # We need to special-case these Node methods because their C++
    857     # signature is different from what we'd expect given their IDL
    858     # description; see Node.h.
    859     my $functionHasCustomReturn = $functionName eq "webkit_dom_node_append_child" ||
    860         $functionName eq "webkit_dom_node_insert_before" ||
    861         $functionName eq "webkit_dom_node_replace_child" ||
    862         $functionName eq "webkit_dom_node_remove_child";
    863         
    864     if ($returnType ne "void" && !$functionHasCustomReturn) {
    865         if ($returnValueIsGDOMType) {
    866             $assign = "PassRefPtr<WebCore::${functionSigType}> g_res = ";
    867             $assignPre = "WTF::getPtr(";
    868             $assignPost = ")";
    869         } else {
    870             $assign = "${returnType} res = ";
    871         }
    872     }
    873     my $exceptions = "";
    874     if (@{$function->raisesExceptions}) {
    875         push(@cBody, "    WebCore::ExceptionCode ec = 0;\n");
    876         if (${callImplParams} ne "") {
    877             $exceptions = ", ec";
    878         } else {
    879             $exceptions = "ec";
    880         }
    881     }
    882 
    883     if ($functionHasCustomReturn) {
    884         my $customNodeAppendChild = << "EOF";
    885     bool ok = item->${functionSigName}(${callImplParams}${exceptions});
    886     if (ok)
    887     {
    888         ${returnType} res = WebKit::kit($returnParamName);
    889         return res;
    890     }
    891 EOF
    892         push(@cBody, $customNodeAppendChild);
    893     
    894         if(@{$function->raisesExceptions}) {
    895             my $exceptionHandling = << "EOF";
    896 
    897     WebCore::ExceptionCodeDescription ecdesc;
    898     WebCore::getExceptionCodeDescription(ec, ecdesc);
    899     g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name);
    900 EOF
    901             push(@cBody, $exceptionHandling);
    902         }
    903         push(@cBody, "return NULL;");
    904         push(@cBody, "}\n\n");
    905         return;
    906     } elsif ($functionSigType eq "DOMString") {
    907         my $getterContentHead;
    908         if ($prefix) {
    909             my $getterExpressionPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $function);
    910             $getterContentHead = "${assign}convertToUTF8String(item->$getterExpressionPrefix${exceptions}));\n";
    911         } else {
    912             $getterContentHead = "${assign}convertToUTF8String(item->${functionSigName}(${callImplParams}${exceptions}));\n";
    913         }
    914         push(@cBody, "    ${getterContentHead}");
    915     } else {
    916         my $contentHead;
    917         if ($prefix eq "get_") {
    918             my $getterExpressionPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $function);
    919             $contentHead = "${assign}${assignPre}item->$getterExpressionPrefix${callImplParams}${exceptions}${assignPost});\n";
    920         } elsif ($prefix eq "set_") {
    921             my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $function);
    922             $contentHead = "${assign}${assignPre}item->$setterExpressionPrefix${callImplParams}${exceptions}${assignPost});\n";
    923         } else {
    924             $contentHead = "${assign}${assignPre}item->${functionSigName}(${callImplParams}${exceptions}${assignPost});\n";
    925         }
    926         push(@cBody, "    ${contentHead}");
    927         
    928         if(@{$function->raisesExceptions}) {
    929             my $exceptionHandling = << "EOF";
    930     if (ec) {
    931         WebCore::ExceptionCodeDescription ecdesc;
    932         WebCore::getExceptionCodeDescription(ec, ecdesc);
    933         g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name);
    934     }
    935 EOF
    936             push(@cBody, $exceptionHandling);
    937         }
    938     }
    939 
    940     if ($returnType ne "void" && !$functionHasCustomReturn) {
    941         if ($functionSigType ne "DOMObject") {
    942             if ($returnValueIsGDOMType) {
    943                 push(@cBody, "    ${returnType} res = WebKit::kit(g_res.get());\n");
    944             }
    945         }
    946         if ($functionSigType eq "DOMObject") {
    947             push(@cBody, "    return NULL; /* TODO: return canvas object */\n");
    948         } else {
    949             push(@cBody, "    return res;\n");
    950         }
    951     }
    952 
    953     if ($conditionalString) {
    954         if ($returnType ne "void") {
    955             push(@cBody, "#else\n");
    956             if ($codeGenerator->IsNonPointerType($functionSigType)) {
    957                 push(@cBody, "    return static_cast<${returnType}>(0);\n");
    958             } else {
    959                 push(@cBody, "    return NULL;\n");
    960             }
    961         }
    962         push(@cBody, "#endif /* ${conditionalString} */\n") if $conditionalString;
    963     }
    964 
    965     push(@cBody, "}\n\n");
    966 }
    967 
    968 sub ClassHasFunction {
    969     my ($class, $name) = @_;
    970 
    971     foreach my $function (@{$class->functions}) {
    972         if ($function->signature->name eq $name) {
    973             return 1;
    974         }
    975     }
    976 
    977     return 0;
    978 }
    979 
    980 sub GenerateFunctions {
    981     my ($object, $interfaceName, $dataNode) = @_;
    982 
    983     foreach my $function (@{$dataNode->functions}) {
    984         $object->GenerateFunction($interfaceName, $function, "");
    985     }
    986 
    987     TOP:
    988     foreach my $attribute (@{$dataNode->attributes}) {
    989         if (SkipAttribute($attribute) ||
    990             $attribute->signature->type eq "EventListener" ||
    991             $attribute->signature->type eq "MediaQueryListListener") {
    992             next TOP;
    993         }
    994         
    995         if ($attribute->signature->name eq "type"
    996             # This will conflict with the get_type() function we define to return a GType
    997             # according to GObject conventions.  Skip this for now.
    998             || $attribute->signature->name eq "URL"     # TODO: handle this
    999             ) {
   1000             next TOP;
   1001         }
   1002             
   1003         my $attrNameUpper = $codeGenerator->WK_ucfirst($attribute->signature->name);
   1004         my $getname = "get${attrNameUpper}";
   1005         my $setname = "set${attrNameUpper}";
   1006         if (ClassHasFunction($dataNode, $getname) || ClassHasFunction($dataNode, $setname)) {
   1007             # Very occasionally an IDL file defines getter/setter functions for one of its
   1008             # attributes; in this case we don't need to autogenerate the getter/setter.
   1009             next TOP;
   1010         }
   1011         
   1012         # Generate an attribute getter.  For an attribute "foo", this is a function named
   1013         # "get_foo" which calls a DOM class method named foo().
   1014         my $function = new domFunction();
   1015         $function->signature($attribute->signature);
   1016         $function->raisesExceptions($attribute->getterExceptions);
   1017         $object->GenerateFunction($interfaceName, $function, "get_");
   1018         
   1019         if ($attribute->type =~ /^readonly/) {
   1020             next TOP;
   1021         }
   1022         
   1023         # Generate an attribute setter.  For an attribute, "foo", this is a function named
   1024         # "set_foo" which calls a DOM class method named setFoo().
   1025         $function = new domFunction();
   1026         
   1027         $function->signature(new domSignature());
   1028         $function->signature->name($attribute->signature->name);
   1029         $function->signature->type($attribute->signature->type);
   1030         $function->signature->extendedAttributes($attribute->signature->extendedAttributes);
   1031         
   1032         my $param = new domSignature();
   1033         $param->name("value");
   1034         $param->type($attribute->signature->type);
   1035         my %attributes = ();
   1036         $param->extendedAttributes(attributes);
   1037         my $arrayRef = $function->parameters;
   1038         push(@$arrayRef, $param);
   1039         
   1040         $function->raisesExceptions($attribute->setterExceptions);
   1041         
   1042         $object->GenerateFunction($interfaceName, $function, "set_");
   1043     }
   1044 }
   1045 
   1046 sub GenerateCFile {
   1047     my ($object, $interfaceName, $parentClassName, $parentGObjType, $dataNode) = @_;
   1048 
   1049     if ($dataNode->extendedAttributes->{"EventTarget"}) {
   1050         $object->GenerateEventTargetIface($dataNode);
   1051     }
   1052 
   1053     my $implContent = "";
   1054 
   1055     my $clsCaps = uc(FixUpDecamelizedName(decamelize($interfaceName)));
   1056     my $lowerCaseIfaceName = "webkit_dom_" . FixUpDecamelizedName(decamelize($interfaceName));
   1057 
   1058     $implContent = << "EOF";
   1059 ${defineTypeMacro}(${className}, ${lowerCaseIfaceName}, ${parentGObjType}${defineTypeInterfaceImplementation}
   1060 
   1061 namespace WebKit {
   1062 
   1063 WebCore::${interfaceName}* core(${className}* request)
   1064 {
   1065     g_return_val_if_fail(request, 0);
   1066 
   1067     WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(request)->coreObject);
   1068     g_return_val_if_fail(coreObject, 0);
   1069 
   1070     return coreObject;
   1071 }
   1072 
   1073 } // namespace WebKit
   1074 EOF
   1075 
   1076     push(@cBodyPriv, $implContent);
   1077     $object->GenerateProperties($interfaceName, $dataNode);
   1078     $object->GenerateFunctions($interfaceName, $dataNode);
   1079 
   1080     my $wrapMethod = << "EOF";
   1081 namespace WebKit {
   1082 ${className}* wrap${interfaceName}(WebCore::${interfaceName}* coreObject)
   1083 {
   1084     g_return_val_if_fail(coreObject, 0);
   1085 
   1086     /* We call ref() rather than using a C++ smart pointer because we can't store a C++ object
   1087      * in a C-allocated GObject structure.  See the finalize() code for the
   1088      * matching deref().
   1089      */
   1090     coreObject->ref();
   1091 
   1092     return  WEBKIT_DOM_${clsCaps}(g_object_new(WEBKIT_TYPE_DOM_${clsCaps},
   1093                                                "core-object", coreObject, NULL));
   1094 }
   1095 } // namespace WebKit
   1096 EOF
   1097     push(@cBodyPriv, $wrapMethod);
   1098 }
   1099 
   1100 sub GenerateEndHeader {
   1101     my ($object) = @_;
   1102 
   1103     #Header guard
   1104     my $guard = $className . "_h";
   1105 
   1106     push(@hBody, "G_END_DECLS\n\n");
   1107     push(@hPrefixGuardEnd, "#endif /* $guard */\n");
   1108 }
   1109 
   1110 sub GeneratePrivateHeader {
   1111     my $object = shift;
   1112     my $dataNode = shift;
   1113 
   1114     my $interfaceName = $dataNode->name;
   1115     my $filename = "$outputDir/" . $className . "Private.h";
   1116     my $guard = uc(decamelize($className)) . "_PRIVATE_H";
   1117     my $parentClassName = GetParentClassName($dataNode);
   1118     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
   1119     my $hasRealParent = @{$dataNode->parents} > 0;
   1120     my $hasParent = $hasLegacyParent || $hasRealParent;
   1121     
   1122     open(PRIVHEADER, ">$filename") or die "Couldn't open file $filename for writing";
   1123     
   1124     print PRIVHEADER split("\r", $licenceTemplate);
   1125     print PRIVHEADER "\n";
   1126     
   1127     my $text = << "EOF";
   1128 #ifndef $guard
   1129 #define $guard
   1130 
   1131 #include <glib-object.h>
   1132 #include <webkit/${parentClassName}.h>
   1133 #include "${interfaceName}.h"
   1134 EOF
   1135 
   1136     print PRIVHEADER $text;
   1137     
   1138     print PRIVHEADER map { "#include \"$_\"\n" } sort keys(%hdrPropIncludes);
   1139     print PRIVHEADER "\n" if keys(%hdrPropIncludes);
   1140     
   1141     $text = << "EOF";
   1142 namespace WebKit {
   1143     ${className} *
   1144     wrap${interfaceName}(WebCore::${interfaceName} *coreObject);
   1145 
   1146     WebCore::${interfaceName} *
   1147     core(${className} *request);
   1148 
   1149 EOF
   1150 
   1151     print PRIVHEADER $text;
   1152 
   1153     if ($className ne "WebKitDOMNode") {
   1154         $text = << "EOF";
   1155     ${className}*
   1156     kit(WebCore::${interfaceName}* node);
   1157 
   1158 EOF
   1159         print PRIVHEADER $text;
   1160     }
   1161 
   1162     $text = << "EOF";
   1163 } // namespace WebKit
   1164 
   1165 #endif /* ${guard} */
   1166 EOF
   1167     print PRIVHEADER $text;
   1168 
   1169     close(PRIVHEADER);
   1170 }
   1171 
   1172 sub UsesManualKitImplementation {
   1173     my $type = shift;
   1174 
   1175     return 1 if $type eq "Node" or $type eq "Element" or $type eq "Event";
   1176     return 0;
   1177 }
   1178 
   1179 sub GenerateEventTargetIface {
   1180     my $object = shift;
   1181     my $dataNode = shift;
   1182 
   1183     my $interfaceName = $dataNode->name;
   1184     my $decamelize = FixUpDecamelizedName(decamelize($interfaceName));
   1185 
   1186     $implIncludes{"GObjectEventListener.h"} = 1;
   1187     $implIncludes{"WebKitDOMEventTarget.h"} = 1;
   1188     $implIncludes{"WebKitDOMEventPrivate.h"} = 1;
   1189 
   1190     my $impl = << "EOF";
   1191 static void webkit_dom_${decamelize}_dispatch_event(WebKitDOMEventTarget* target, WebKitDOMEvent* event, GError** error)
   1192 {
   1193     WebCore::Event* coreEvent = WebKit::core(event);
   1194     WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);
   1195 
   1196     WebCore::ExceptionCode ec = 0;
   1197     coreTarget->dispatchEvent(coreEvent, ec);
   1198     if (ec) {
   1199         WebCore::ExceptionCodeDescription description;
   1200         WebCore::getExceptionCodeDescription(ec, description);
   1201         g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.code, description.name);
   1202     }
   1203 }
   1204 
   1205 static gboolean webkit_dom_${decamelize}_add_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble, gpointer userData)
   1206 {
   1207     WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);
   1208     return WebCore::GObjectEventListener::addEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble, userData);
   1209 }
   1210 
   1211 static gboolean webkit_dom_${decamelize}_remove_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble)
   1212 {
   1213     WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject);
   1214     return WebCore::GObjectEventListener::removeEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble);
   1215 }
   1216 
   1217 static void webkit_dom_event_target_init(WebKitDOMEventTargetIface* iface)
   1218 {
   1219     iface->dispatch_event = webkit_dom_${decamelize}_dispatch_event;
   1220     iface->add_event_listener = webkit_dom_${decamelize}_add_event_listener;
   1221     iface->remove_event_listener = webkit_dom_${decamelize}_remove_event_listener;
   1222 }
   1223 
   1224 EOF
   1225 
   1226     push(@cBody, $impl);
   1227 
   1228     $defineTypeMacro = "G_DEFINE_TYPE_WITH_CODE";
   1229     $defineTypeInterfaceImplementation = ", G_IMPLEMENT_INTERFACE(WEBKIT_TYPE_DOM_EVENT_TARGET, webkit_dom_event_target_init))";
   1230 }
   1231 
   1232 sub Generate {
   1233     my ($object, $dataNode) = @_;
   1234 
   1235     my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
   1236     my $hasRealParent = @{$dataNode->parents} > 0;
   1237     my $hasParent = $hasLegacyParent || $hasRealParent;
   1238     my $parentClassName = GetParentClassName($dataNode);
   1239     my $parentGObjType = GetParentGObjType($dataNode);
   1240     my $interfaceName = $dataNode->name;
   1241 
   1242     # Add the guard if the 'Conditional' extended attribute exists
   1243     my $conditionalString = GenerateConditionalString($dataNode);
   1244     push(@conditionGuardStart, "#if ${conditionalString}\n\n") if $conditionalString;
   1245     push(@conditionGuardEnd, "#endif /* ${conditionalString} */\n") if $conditionalString;
   1246 
   1247     # Add the default impl header template
   1248     @cPrefix = split("\r", $licenceTemplate);
   1249     push(@cPrefix, "\n");
   1250 
   1251     $implIncludes{"webkitdefines.h"} = 1;
   1252     $implIncludes{"webkitglobalsprivate.h"} = 1;
   1253     $implIncludes{"webkitmarshal.h"} = 1;
   1254     $implIncludes{"DOMObjectCache.h"} = 1;
   1255     $implIncludes{"WebKitDOMBinding.h"} = 1;
   1256     $implIncludes{"gobject/ConvertToUTF8String.h"} = 1;
   1257     $implIncludes{"webkit/$className.h"} = 1;
   1258     $implIncludes{"webkit/${className}Private.h"} = 1;
   1259     $implIncludes{"${interfaceName}.h"} = 1;
   1260     $implIncludes{"JSMainThreadExecState.h"} = 1;
   1261     $implIncludes{"ExceptionCode.h"} = 1;
   1262 
   1263     $hdrIncludes{"webkit/${parentClassName}.h"} = 1;
   1264 
   1265     if (!UsesManualKitImplementation($interfaceName)) {
   1266         my $converter = << "EOF";
   1267 namespace WebKit {
   1268     
   1269 ${className}* kit(WebCore::$interfaceName* obj)
   1270 {
   1271     g_return_val_if_fail(obj, 0);
   1272 
   1273     if (gpointer ret = DOMObjectCache::get(obj))
   1274         return static_cast<${className}*>(ret);
   1275 
   1276     return static_cast<${className}*>(DOMObjectCache::put(obj, WebKit::wrap${interfaceName}(obj)));
   1277 }
   1278     
   1279 } // namespace WebKit //
   1280 
   1281 EOF
   1282     push(@cBody, $converter);
   1283     }
   1284 
   1285     $object->GenerateHeader($interfaceName, $parentClassName);
   1286     $object->GenerateCFile($interfaceName, $parentClassName, $parentGObjType, $dataNode);
   1287     $object->GenerateEndHeader();
   1288     $object->GeneratePrivateHeader($dataNode);
   1289 
   1290 }
   1291 
   1292 # Internal helper
   1293 sub WriteData {
   1294     my ($object, $name) = @_;
   1295 
   1296     # Write public header.
   1297     my $hdrFName = "$outputDir/" . $name . ".h";
   1298     open(HEADER, ">$hdrFName") or die "Couldn't open file $hdrFName";
   1299 
   1300     print HEADER @hPrefix;
   1301     print HEADER @hPrefixGuard;
   1302     print HEADER "#include \"webkit/webkitdomdefines.h\"\n";
   1303     print HEADER "#include <glib-object.h>\n";
   1304     print HEADER "#include <webkit/webkitdefines.h>\n";
   1305     print HEADER map { "#include \"$_\"\n" } sort keys(%hdrIncludes);
   1306     print HEADER "\n" if keys(%hdrIncludes);
   1307     print HEADER "\n";
   1308     print HEADER @hBodyPre;
   1309     print HEADER @hBody;
   1310     print HEADER @hPrefixGuardEnd;
   1311 
   1312     close(HEADER);
   1313 
   1314     # Write the implementation sources
   1315     my $implFileName = "$outputDir/" . $name . ".cpp";
   1316     open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName";
   1317 
   1318     print IMPL @cPrefix;
   1319     print IMPL "#include <glib-object.h>\n";
   1320     print IMPL "#include \"config.h\"\n\n";
   1321     print IMPL @conditionGuardStart;
   1322     print IMPL "#include <wtf/GetPtr.h>\n";
   1323     print IMPL "#include <wtf/RefPtr.h>\n";
   1324     print IMPL map { "#include \"$_\"\n" } sort keys(%implIncludes);
   1325     print IMPL "\n" if keys(%implIncludes);
   1326     print IMPL @cBody;
   1327 
   1328     print IMPL "\n";
   1329     print IMPL @cBodyPriv;
   1330     print IMPL @conditionGuardEnd;
   1331 
   1332     close(IMPL);
   1333 
   1334     %implIncludes = ();
   1335     %hdrIncludes = ();
   1336     @hPrefix = ();
   1337     @hBody = ();
   1338 
   1339     @cPrefix = ();
   1340     @cBody = ();
   1341     @cBodyPriv = ();
   1342 }
   1343 
   1344 sub GenerateInterface {
   1345     my ($object, $dataNode, $defines) = @_;
   1346     my $name = $dataNode->name;
   1347 
   1348     # Set up some global variables
   1349     $className = GetClassName($dataNode->name);
   1350     $object->Generate($dataNode);
   1351 
   1352     # Write changes
   1353     my $fname = "WebKitDOM_" . $name;
   1354     $fname =~ s/_//g;
   1355     $object->WriteData($fname);
   1356 }
   1357