| # Copyright (C) 2008 Luke Kenneth Casson Leighton <lkcl@lkcl.net> |
| # Copyright (C) 2008 Martin Soto <soto@freedesktop.org> |
| # Copyright (C) 2008 Alp Toker <alp@atoker.com> |
| # Copyright (C) 2009 Adam Dingle <adam@yorba.org> |
| # Copyright (C) 2009 Jim Nelson <jim@yorba.org> |
| # Copyright (C) 2009, 2010 Igalia S.L. |
| # |
| # This library is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU Library General Public |
| # License as published by the Free Software Foundation; either |
| # version 2 of the License, or (at your option) any later version. |
| # |
| # This library is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| # Library General Public License for more details. |
| # |
| # You should have received a copy of the GNU Library General Public License |
| # along with this library; see the file COPYING.LIB. If not, write to |
| # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| # Boston, MA 02111-1307, USA. |
| |
| package CodeGeneratorGObject; |
| |
| # Global Variables |
| my %implIncludes = (); |
| my %hdrIncludes = (); |
| |
| my $defineTypeMacro = "G_DEFINE_TYPE"; |
| my $defineTypeInterfaceImplementation = ")"; |
| my @txtEventListeners = (); |
| my @txtInstallEventListeners = (); |
| my @txtInstallSignals = (); |
| my @txtInstallProps = (); |
| my @txtSetProps = (); |
| my @txtGetProps = (); |
| |
| my $className = ""; |
| |
| # Default constructor |
| sub new { |
| my $object = shift; |
| my $reference = { }; |
| |
| $codeGenerator = shift; |
| $outputDir = shift; |
| mkdir $outputDir; |
| |
| bless($reference, $object); |
| } |
| |
| sub finish { |
| } |
| |
| my $licenceTemplate = << "EOF"; |
| /* |
| This file is part of the WebKit open source project. |
| This file has been generated by generate-bindings.pl. DO NOT MODIFY! |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Library General Public |
| License as published by the Free Software Foundation; either |
| version 2 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Library General Public License for more details. |
| |
| You should have received a copy of the GNU Library General Public License |
| along with this library; see the file COPYING.LIB. If not, write to |
| the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| Boston, MA 02110-1301, USA. |
| */ |
| EOF |
| |
| sub GenerateModule { |
| } |
| |
| sub GetParentClassName { |
| my $dataNode = shift; |
| |
| return "WebKitDOMObject" if @{$dataNode->parents} eq 0; |
| return "WebKitDOM" . $codeGenerator->StripModule($dataNode->parents(0)); |
| } |
| |
| # From String::CamelCase 0.01 |
| sub camelize |
| { |
| my $s = shift; |
| join('', map{ ucfirst $_ } split(/(?<=[A-Za-z])_(?=[A-Za-z])|\b/, $s)); |
| } |
| |
| sub decamelize |
| { |
| my $s = shift; |
| $s =~ s{([^a-zA-Z]?)([A-Z]*)([A-Z])([a-z]?)}{ |
| my $fc = pos($s)==0; |
| my ($p0,$p1,$p2,$p3) = ($1,lc$2,lc$3,$4); |
| my $t = $p0 || $fc ? $p0 : '_'; |
| $t .= $p3 ? $p1 ? "${p1}_$p2$p3" : "$p2$p3" : "$p1$p2"; |
| $t; |
| }ge; |
| $s; |
| } |
| |
| sub FixUpDecamelizedName { |
| my $classname = shift; |
| |
| # FIXME: try to merge this somehow with the fixes in ClassNameToGobjectType |
| $classname =~ s/x_path/xpath/; |
| $classname =~ s/web_kit/webkit/; |
| $classname =~ s/htmli_frame/html_iframe/; |
| |
| return $classname; |
| } |
| |
| sub ClassNameToGObjectType { |
| my $className = shift; |
| my $CLASS_NAME = uc(decamelize($className)); |
| # Fixup: with our prefix being 'WebKitDOM' decamelize can't get |
| # WebKitDOMCSS and similar names right, so we have to fix it |
| # manually. |
| $CLASS_NAME =~ s/DOMCSS/DOM_CSS/; |
| $CLASS_NAME =~ s/DOMHTML/DOM_HTML/; |
| $CLASS_NAME =~ s/DOMDOM/DOM_DOM/; |
| $CLASS_NAME =~ s/DOMCDATA/DOM_CDATA/; |
| $CLASS_NAME =~ s/DOMX_PATH/DOM_XPATH/; |
| $CLASS_NAME =~ s/DOM_WEB_KIT/DOM_WEBKIT/; |
| $CLASS_NAME =~ s/DOMUI/DOM_UI/; |
| $CLASS_NAME =~ s/HTMLI_FRAME/HTML_IFRAME/; |
| return $CLASS_NAME; |
| } |
| |
| sub GetParentGObjType { |
| my $dataNode = shift; |
| |
| return "WEBKIT_TYPE_DOM_OBJECT" if @{$dataNode->parents} eq 0; |
| return "WEBKIT_TYPE_DOM_" . ClassNameToGObjectType($codeGenerator->StripModule($dataNode->parents(0))); |
| } |
| |
| sub GetClassName { |
| my $name = $codeGenerator->StripModule(shift); |
| |
| return "WebKitDOM$name"; |
| } |
| |
| sub GetCoreObject { |
| my ($interfaceName, $name, $parameter) = @_; |
| |
| return "WebCore::${interfaceName}* $name = WebKit::core($parameter);"; |
| } |
| |
| sub SkipAttribute { |
| my $attribute = shift; |
| |
| if ($attribute->signature->extendedAttributes->{"CustomGetter"} || |
| $attribute->signature->extendedAttributes->{"CustomSetter"}) { |
| return 1; |
| } |
| |
| my $propType = $attribute->signature->type; |
| if ($propType =~ /Constructor$/) { |
| return 1; |
| } |
| |
| # This is for DOMWindow.idl location attribute |
| if ($attribute->signature->name eq "location") { |
| return 1; |
| } |
| |
| # This is for HTMLInput.idl valueAsDate |
| if ($attribute->signature->name eq "valueAsDate") { |
| return 1; |
| } |
| |
| # This is for DOMWindow.idl Crypto attribute |
| if ($attribute->signature->type eq "Crypto") { |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| sub SkipFunction { |
| my $function = shift; |
| my $decamelize = shift; |
| my $prefix = shift; |
| |
| my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($function->signature->name); |
| my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"} || |
| $function->signature->extendedAttributes->{"CustomArgumentHandling"}; |
| |
| if ($isCustomFunction && |
| $functionName ne "webkit_dom_node_replace_child" && |
| $functionName ne "webkit_dom_node_insert_before" && |
| $functionName ne "webkit_dom_node_remove_child" && |
| $functionName ne "webkit_dom_node_append_child" && |
| $functionName ne "webkit_dom_html_collection_item" && |
| $functionName ne "webkit_dom_html_collection_named_item") { |
| return 1; |
| } |
| |
| if ($function->signature->name eq "getSVGDocument") { |
| return 1; |
| } |
| |
| if ($function->signature->name eq "getCSSCanvasContext") { |
| return 1; |
| } |
| |
| # Skip functions that have ["Callback"] parameters, because this |
| # code generator doesn't know how to auto-generate callbacks. |
| # Skip functions that have "MediaQueryListListener" parameters, because this |
| # code generator doesn't know how to auto-generate MediaQueryListListener. |
| foreach my $param (@{$function->parameters}) { |
| if ($param->extendedAttributes->{"Callback"} || |
| $param->type eq "MediaQueryListListener") { |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| # Name type used in the g_value_{set,get}_* functions |
| sub GetGValueTypeName { |
| my $type = shift; |
| |
| my %types = ("DOMString", "string", |
| "DOMTimeStamp", "uint", |
| "float", "float", |
| "double", "double", |
| "boolean", "boolean", |
| "char", "char", |
| "long", "long", |
| "long long", "int64", |
| "short", "int", |
| "uchar", "uchar", |
| "unsigned", "uint", |
| "int", "int", |
| "unsigned int", "uint", |
| "unsigned long long", "uint64", |
| "unsigned long", "ulong", |
| "unsigned short", "ushort"); |
| |
| return $types{$type} ? $types{$type} : "object"; |
| } |
| |
| # Name type used in C declarations |
| sub GetGlibTypeName { |
| my $type = shift; |
| my $name = GetClassName($type); |
| |
| my %types = ("DOMString", "gchar*", |
| "DOMTimeStamp", "guint32", |
| "CompareHow", "gushort", |
| "float", "gfloat", |
| "double", "gdouble", |
| "boolean", "gboolean", |
| "char", "gchar", |
| "long", "glong", |
| "long long", "gint64", |
| "short", "gshort", |
| "uchar", "guchar", |
| "unsigned", "guint", |
| "int", "gint", |
| "unsigned int", "guint", |
| "unsigned long", "gulong", |
| "unsigned long long", "guint64", |
| "unsigned short", "gushort", |
| "void", "void"); |
| |
| return $types{$type} ? $types{$type} : "$name*"; |
| } |
| |
| sub IsGDOMClassType { |
| my $type = shift; |
| |
| return 0 if $codeGenerator->IsNonPointerType($type) || $codeGenerator->IsStringType($type); |
| return 1; |
| } |
| |
| sub GetReadableProperties { |
| my $properties = shift; |
| |
| my @result = (); |
| |
| foreach my $property (@{$properties}) { |
| if (!SkipAttribute($property)) { |
| push(@result, $property); |
| } |
| } |
| |
| return @result; |
| } |
| |
| sub GetWriteableProperties { |
| my $properties = shift; |
| my @result = (); |
| |
| foreach my $property (@{$properties}) { |
| my $writeable = $property->type !~ /^readonly/; |
| my $gtype = GetGValueTypeName($property->signature->type); |
| my $hasGtypeSignature = ($gtype eq "boolean" || $gtype eq "float" || $gtype eq "double" || |
| $gtype eq "uint64" || $gtype eq "ulong" || $gtype eq "long" || |
| $gtype eq "uint" || $gtype eq "ushort" || $gtype eq "uchar" || |
| $gtype eq "char" || $gtype eq "string"); |
| # FIXME: We are not generating setters for 'Replaceable' |
| # attributes now, but we should somehow. |
| my $replaceable = $property->signature->extendedAttributes->{"Replaceable"}; |
| if ($writeable && $hasGtypeSignature && !$replaceable) { |
| push(@result, $property); |
| } |
| } |
| |
| return @result; |
| } |
| |
| sub GenerateConditionalString |
| { |
| my $node = shift; |
| my $conditional = $node->extendedAttributes->{"Conditional"}; |
| if ($conditional) { |
| if ($conditional =~ /&/) { |
| return "ENABLE(" . join(") && ENABLE(", split(/&/, $conditional)) . ")"; |
| } elsif ($conditional =~ /\|/) { |
| return "ENABLE(" . join(") || ENABLE(", split(/\|/, $conditional)) . ")"; |
| } else { |
| return "ENABLE(" . $conditional . ")"; |
| } |
| } else { |
| return ""; |
| } |
| } |
| |
| sub GenerateProperty { |
| my $attribute = shift; |
| my $interfaceName = shift; |
| my @writeableProperties = @{shift @_}; |
| |
| my $conditionalString = GenerateConditionalString($attribute->signature); |
| my $camelPropName = $attribute->signature->name; |
| my $setPropNameFunction = $codeGenerator->WK_ucfirst($camelPropName); |
| my $getPropNameFunction = $codeGenerator->WK_lcfirst($camelPropName); |
| |
| my $propName = decamelize($camelPropName); |
| my $propNameCaps = uc($propName); |
| $propName =~ s/_/-/g; |
| my ${propEnum} = "PROP_${propNameCaps}"; |
| push(@cBodyPriv, "#if ${conditionalString}\n") if $conditionalString; |
| push(@cBodyPriv, " ${propEnum},\n"); |
| push(@cBodyPriv, "#endif /* ${conditionalString} */\n") if $conditionalString; |
| |
| my $propType = $attribute->signature->type; |
| my ${propGType} = decamelize($propType); |
| my ${ucPropGType} = uc($propGType); |
| |
| my $gtype = GetGValueTypeName($propType); |
| my $gparamflag = "WEBKIT_PARAM_READABLE"; |
| my $writeable = $attribute->type !~ /^readonly/; |
| my $const = "read-only "; |
| my $custom = $attribute->signature->extendedAttributes->{"Custom"}; |
| if ($writeable && $custom) { |
| $const = "read-only (due to custom functions needed in webkitdom)"; |
| return; |
| } |
| if ($writeable && !$custom) { |
| $gparamflag = "WEBKIT_PARAM_READWRITE"; |
| $const = "read-write "; |
| } |
| |
| my $type = GetGlibTypeName($propType); |
| $nick = decamelize("${interfaceName}_${propName}"); |
| $long = "${const} ${type} ${interfaceName}.${propName}"; |
| |
| my $convertFunction = ""; |
| if ($gtype eq "string") { |
| $convertFunction = "WTF::String::fromUTF8"; |
| } |
| |
| my $getterExpressionPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute); |
| my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $attribute); |
| |
| my $getterContentHead = "coreSelf->$getterExpressionPrefix"; |
| my $setterContentHead = "coreSelf->$setterExpressionPrefix${convertFunction}(g_value_get_$gtype(value))"; |
| |
| if (grep {$_ eq $attribute} @writeableProperties) { |
| push(@txtSetProps, "#if ${conditionalString}\n") if $conditionalString; |
| push(@txtSetProps, " case ${propEnum}:\n {\n"); |
| push(@txtSetProps, " WebCore::ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions}; |
| push(@txtSetProps, " ${setterContentHead}"); |
| push(@txtSetProps, ", ec") if @{$attribute->setterExceptions}; |
| push(@txtSetProps, ");\n"); |
| push(@txtSetProps, " break;\n }\n"); |
| push(@txtSetProps, "#endif /* ${conditionalString} */\n") if $conditionalString; |
| } |
| |
| push(@txtGetProps, "#if ${conditionalString}\n") if $conditionalString; |
| push(@txtGetProps, " case ${propEnum}:\n {\n"); |
| |
| my $exception = ""; |
| if (@{$attribute->getterExceptions}) { |
| $exception = "ec"; |
| push(@txtGetProps, " WebCore::ExceptionCode ec = 0;\n"); |
| } |
| |
| my $postConvertFunction = ""; |
| my $done = 0; |
| if ($gtype eq "string") { |
| push(@txtGetProps, " g_value_take_string(value, convertToUTF8String(${getterContentHead}${exception})));\n"); |
| $done = 1; |
| } elsif ($gtype eq "object") { |
| $txtGetProp = << "EOF"; |
| RefPtr<WebCore::${propType}> ptr = coreSelf->${getPropNameFunction}(${exception}); |
| g_value_set_object(value, WebKit::kit(ptr.get())); |
| EOF |
| push(@txtGetProps, $txtGetProp); |
| $done = 1; |
| } |
| |
| # FIXME: get rid of this glitch? |
| my $_gtype = $gtype; |
| if ($gtype eq "ushort") { |
| $_gtype = "uint"; |
| } |
| |
| if (!$done) { |
| push(@txtGetProps, " g_value_set_$_gtype(value, ${convertFunction}coreSelf->${getterExpressionPrefix}${exception})${postConvertFunction});\n"); |
| } |
| |
| push(@txtGetProps, " break;\n }\n"); |
| push(@txtGetProps, "#endif /* ${conditionalString} */\n") if $conditionalString; |
| |
| my %param_spec_options = ("int", "G_MININT, /* min */\nG_MAXINT, /* max */\n0, /* default */", |
| "boolean", "FALSE, /* default */", |
| "float", "-G_MAXFLOAT, /* min */\nG_MAXFLOAT, /* max */\n0.0, /* default */", |
| "double", "-G_MAXDOUBLE, /* min */\nG_MAXDOUBLE, /* max */\n0.0, /* default */", |
| "uint64", "0, /* min */\nG_MAXUINT64, /* min */\n0, /* default */", |
| "long", "G_MINLONG, /* min */\nG_MAXLONG, /* max */\n0, /* default */", |
| "int64", "G_MININT64, /* min */\nG_MAXINT64, /* max */\n0, /* default */", |
| "ulong", "0, /* min */\nG_MAXULONG, /* max */\n0, /* default */", |
| "uint", "0, /* min */\nG_MAXUINT, /* max */\n0, /* default */", |
| "ushort", "0, /* min */\nG_MAXUINT16, /* max */\n0, /* default */", |
| "uchar", "G_MININT8, /* min */\nG_MAXINT8, /* max */\n0, /* default */", |
| "char", "0, /* min */\nG_MAXUINT8, /* max */\n0, /* default */", |
| "string", "\"\", /* default */", |
| "object", "WEBKIT_TYPE_DOM_${ucPropGType}, /* gobject type */"); |
| |
| my $txtInstallProp = << "EOF"; |
| g_object_class_install_property(gobjectClass, |
| ${propEnum}, |
| g_param_spec_${_gtype}("${propName}", /* name */ |
| "$nick", /* short description */ |
| "$long", /* longer - could do with some extra doc stuff here */ |
| $param_spec_options{$gtype} |
| ${gparamflag})); |
| EOF |
| push(@txtInstallProps, "#if ${conditionalString}\n") if $conditionalString; |
| push(@txtInstallProps, $txtInstallProp); |
| push(@txtInstallProps, "#endif /* ${conditionalString} */\n") if $conditionalString; |
| } |
| |
| sub GenerateProperties { |
| my ($object, $interfaceName, $dataNode) = @_; |
| |
| my $clsCaps = substr(ClassNameToGObjectType($className), 12); |
| my $lowerCaseIfaceName = "webkit_dom_" . (FixUpDecamelizedName(decamelize($interfaceName))); |
| |
| # Properties |
| my $implContent = ""; |
| |
| # Properties |
| $implContent = << "EOF"; |
| enum { |
| PROP_0, |
| EOF |
| push(@cBodyPriv, $implContent); |
| |
| my @readableProperties = GetReadableProperties($dataNode->attributes); |
| |
| my $privFunction = GetCoreObject($interfaceName, "coreSelf", "self"); |
| |
| my $txtGetProp = << "EOF"; |
| static void ${lowerCaseIfaceName}_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) |
| { |
| WebCore::JSMainThreadNullState state; |
| EOF |
| push(@txtGetProps, $txtGetProp); |
| if (scalar @readableProperties > 0) { |
| $txtGetProp = << "EOF"; |
| ${className}* self = WEBKIT_DOM_${clsCaps}(object); |
| $privFunction |
| EOF |
| push(@txtGetProps, $txtGetProp); |
| } |
| |
| $txtGetProp = << "EOF"; |
| switch (prop_id) { |
| EOF |
| push(@txtGetProps, $txtGetProp); |
| |
| my @writeableProperties = GetWriteableProperties(\@readableProperties); |
| |
| my $txtSetProps = << "EOF"; |
| static void ${lowerCaseIfaceName}_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) |
| { |
| WebCore::JSMainThreadNullState state; |
| EOF |
| push(@txtSetProps, $txtSetProps); |
| |
| if (scalar @writeableProperties > 0) { |
| $txtSetProps = << "EOF"; |
| ${className}* self = WEBKIT_DOM_${clsCaps}(object); |
| $privFunction |
| EOF |
| push(@txtSetProps, $txtSetProps); |
| } |
| |
| $txtSetProps = << "EOF"; |
| switch (prop_id) { |
| EOF |
| push(@txtSetProps, $txtSetProps); |
| |
| foreach my $attribute (@readableProperties) { |
| if ($attribute->signature->type ne "EventListener" && |
| $attribute->signature->type ne "MediaQueryListListener") { |
| GenerateProperty($attribute, $interfaceName, \@writeableProperties); |
| } |
| } |
| |
| push(@cBodyPriv, "};\n\n"); |
| |
| $txtGetProp = << "EOF"; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); |
| break; |
| } |
| } |
| EOF |
| push(@txtGetProps, $txtGetProp); |
| |
| $txtSetProps = << "EOF"; |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); |
| break; |
| } |
| } |
| EOF |
| push(@txtSetProps, $txtSetProps); |
| |
| # Do not insert extra spaces when interpolating array variables |
| $" = ""; |
| |
| $implContent = << "EOF"; |
| |
| static void ${lowerCaseIfaceName}_finalize(GObject* object) |
| { |
| WebKitDOMObject* dom_object = WEBKIT_DOM_OBJECT(object); |
| |
| if (dom_object->coreObject) { |
| WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName} *>(dom_object->coreObject); |
| |
| WebKit::DOMObjectCache::forget(coreObject); |
| coreObject->deref(); |
| |
| dom_object->coreObject = NULL; |
| } |
| |
| G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->finalize(object); |
| } |
| |
| @txtSetProps |
| |
| @txtGetProps |
| |
| static void ${lowerCaseIfaceName}_constructed(GObject* object) |
| { |
| EOF |
| push(@cBodyPriv, $implContent); |
| |
| $implContent = << "EOF"; |
| @txtInstallEventListeners |
| if (G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->constructed) |
| G_OBJECT_CLASS(${lowerCaseIfaceName}_parent_class)->constructed(object); |
| } |
| |
| static void ${lowerCaseIfaceName}_class_init(${className}Class* requestClass) |
| { |
| GObjectClass *gobjectClass = G_OBJECT_CLASS(requestClass); |
| gobjectClass->finalize = ${lowerCaseIfaceName}_finalize; |
| gobjectClass->set_property = ${lowerCaseIfaceName}_set_property; |
| gobjectClass->get_property = ${lowerCaseIfaceName}_get_property; |
| gobjectClass->constructed = ${lowerCaseIfaceName}_constructed; |
| |
| @txtInstallProps |
| @txtInstallSignals |
| } |
| |
| static void ${lowerCaseIfaceName}_init(${className}* request) |
| { |
| } |
| |
| EOF |
| push(@cBodyPriv, $implContent); |
| } |
| |
| sub GenerateHeader { |
| my ($object, $interfaceName, $parentClassName) = @_; |
| |
| my $implContent = ""; |
| |
| # Add the default header template |
| @hPrefix = split("\r", $licenceTemplate); |
| push(@hPrefix, "\n"); |
| |
| #Header guard |
| my $guard = $className . "_h"; |
| |
| @hPrefixGuard = << "EOF"; |
| #ifndef $guard |
| #define $guard |
| |
| EOF |
| |
| $implContent = << "EOF"; |
| G_BEGIN_DECLS |
| EOF |
| |
| push(@hBodyPre, $implContent); |
| |
| my $decamelize = FixUpDecamelizedName(decamelize($interfaceName)); |
| my $clsCaps = uc($decamelize); |
| my $lowerCaseIfaceName = "webkit_dom_" . ($decamelize); |
| |
| $implContent = << "EOF"; |
| #define WEBKIT_TYPE_DOM_${clsCaps} (${lowerCaseIfaceName}_get_type()) |
| #define WEBKIT_DOM_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className})) |
| #define WEBKIT_DOM_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class) |
| #define WEBKIT_DOM_IS_${clsCaps}(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_DOM_${clsCaps})) |
| #define WEBKIT_DOM_IS_${clsCaps}_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_DOM_${clsCaps})) |
| #define WEBKIT_DOM_${clsCaps}_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_DOM_${clsCaps}, ${className}Class)) |
| |
| struct _${className} { |
| ${parentClassName} parent_instance; |
| }; |
| |
| struct _${className}Class { |
| ${parentClassName}Class parent_class; |
| }; |
| |
| WEBKIT_API GType |
| ${lowerCaseIfaceName}_get_type (void); |
| |
| EOF |
| |
| push(@hBody, $implContent); |
| } |
| |
| sub getIncludeHeader { |
| my $type = shift; |
| my $name = GetClassName($type); |
| |
| return "" if $type eq "int"; |
| return "" if $type eq "long"; |
| return "" if $type eq "long long"; |
| return "" if $type eq "short"; |
| return "" if $type eq "char"; |
| return "" if $type eq "float"; |
| return "" if $type eq "double"; |
| return "" if $type eq "unsigned"; |
| return "" if $type eq "unsigned int"; |
| return "" if $type eq "unsigned long"; |
| return "" if $type eq "unsigned long long"; |
| return "" if $type eq "unsigned short"; |
| return "" if $type eq "DOMTimeStamp"; |
| return "" if $type eq "EventListener"; |
| return "" if $type eq "MediaQueryListListener"; |
| return "" if $type eq "unsigned char"; |
| return "" if $type eq "DOMString"; |
| return "" if $type eq "float"; |
| return "" if $type eq "boolean"; |
| return "" if $type eq "void"; |
| return "" if $type eq "CompareHow"; |
| |
| return "$name.h"; |
| } |
| |
| sub addIncludeInBody { |
| my $type = shift; |
| |
| if ($type eq "DOMObject") { |
| return; |
| } |
| |
| my $header = getIncludeHeader($type); |
| if ($header eq "") { |
| return; |
| } |
| |
| if (IsGDOMClassType($type)) { |
| $implIncludes{"webkit/$header"} = 1; |
| } else { |
| $implIncludes{$header} = 1 |
| } |
| } |
| |
| sub GenerateFunction { |
| my ($object, $interfaceName, $function, $prefix) = @_; |
| |
| my $decamelize = FixUpDecamelizedName(decamelize($interfaceName)); |
| |
| if ($object eq "MediaQueryListListener") { |
| return; |
| } |
| |
| if (SkipFunction($function, $decamelize, $prefix)) { |
| return; |
| } |
| |
| my $functionSigName = $function->signature->name; |
| my $functionSigType = $prefix eq "set_" ? "void" : $function->signature->type; |
| my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($functionSigName); |
| my $returnType = GetGlibTypeName($functionSigType); |
| my $returnValueIsGDOMType = IsGDOMClassType($functionSigType); |
| my $conditionalString = GenerateConditionalString($function->signature); |
| |
| my $functionSig = "${className}* self"; |
| |
| my $callImplParams = ""; |
| |
| # skip some custom functions for now |
| my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"} || |
| $function->signature->extendedAttributes->{"CustomArgumentHandling"}; |
| |
| foreach my $param (@{$function->parameters}) { |
| my $paramIDLType = $param->type; |
| if ($paramIDLType eq "EventListener" || $paramIDLType eq "MediaQueryListListener") { |
| # EventListeners are handled elsewhere. |
| return; |
| } |
| addIncludeInBody($paramIDLType); |
| my $paramType = GetGlibTypeName($paramIDLType); |
| my $const = $paramType eq "gchar*" ? "const " : ""; |
| my $paramName = decamelize($param->name); |
| |
| $functionSig .= ", ${const}$paramType $paramName"; |
| |
| my $paramIsGDOMType = IsGDOMClassType($paramIDLType); |
| if ($paramIsGDOMType) { |
| if ($paramIDLType ne "DOMObject") { |
| $implIncludes{"webkit/WebKitDOM${paramIDLType}Private.h"} = 1; |
| } |
| } |
| if ($paramIsGDOMType || ($paramIDLType eq "DOMString") || ($paramIDLType eq "CompareHow")) { |
| $paramName = "converted_" . $paramName; |
| } |
| if ($callImplParams) { |
| $callImplParams .= ", $paramName"; |
| } else { |
| $callImplParams = "$paramName"; |
| } |
| } |
| |
| # Not quite sure what to do with this yet, but we need to take into |
| # account the difference in parameters between the IDL file and the |
| # actual implementation. |
| if ($function->signature->extendedAttributes->{"NeedsUserGestureCheck"}) { |
| $functionSig .= ", gboolean isUserGesture"; |
| $callImplParams .= ", " if $callImplParams; |
| $callImplParams .= "false"; |
| } |
| |
| if ($returnType ne "void" && $returnValueIsGDOMType && $functionSigType ne "DOMObject") { |
| if ($functionSigType ne "EventTarget") { |
| $implIncludes{"webkit/WebKitDOM${functionSigType}Private.h"} = 1; |
| $implIncludes{"webkit/WebKitDOM${functionSigType}.h"} = 1; |
| } else { |
| $implIncludes{"WebKitDOM${functionSigType}.h"} = 1; |
| } |
| |
| $implIncludes{"${functionSigType}.h"} = 1; |
| } |
| |
| if(@{$function->raisesExceptions}) { |
| $functionSig .= ", GError **error"; |
| } |
| |
| # Insert introspection annotations |
| push(@hBody, "/**\n"); |
| push(@hBody, " * ${functionName}:\n"); |
| push(@hBody, " * \@self: A #${className}\n"); |
| |
| foreach my $param (@{$function->parameters}) { |
| my $paramType = GetGlibTypeName($param->type); |
| # $paramType can have a trailing * in some cases |
| $paramType =~ s/\*$//; |
| my $paramName = decamelize($param->name); |
| push(@hBody, " * \@${paramName}: A #${paramType}\n"); |
| } |
| if(@{$function->raisesExceptions}) { |
| push(@hBody, " * \@error: #GError\n"); |
| } |
| push(@hBody, " *\n"); |
| if (IsGDOMClassType($function->signature->type)) { |
| push(@hBody, " * Returns: (transfer none):\n"); |
| } else { |
| push(@hBody, " * Returns:\n"); |
| } |
| push(@hBody, " *\n"); |
| push(@hBody, "**/\n"); |
| |
| push(@hBody, "WEBKIT_API $returnType\n$functionName($functionSig);\n"); |
| push(@hBody, "\n"); |
| |
| push(@cBody, "$returnType\n$functionName($functionSig)\n{\n"); |
| push(@cBody, "#if ${conditionalString}\n") if $conditionalString; |
| |
| if ($returnType ne "void") { |
| # TODO: return proper default result |
| push(@cBody, " g_return_val_if_fail(self, 0);\n"); |
| } else { |
| push(@cBody, " g_return_if_fail(self);\n"); |
| } |
| |
| push(@cBody, " WebCore::JSMainThreadNullState state;\n"); |
| |
| # The WebKit::core implementations check for NULL already; no need to |
| # duplicate effort. |
| push(@cBody, " WebCore::${interfaceName} * item = WebKit::core(self);\n"); |
| |
| foreach my $param (@{$function->parameters}) { |
| my $paramName = decamelize($param->name); |
| my $paramIDLType = $param->type; |
| my $paramTypeIsPrimitive = $codeGenerator->IsPrimitiveType($paramIDLType); |
| my $paramIsGDOMType = IsGDOMClassType($paramIDLType); |
| if (!$paramTypeIsPrimitive) { |
| if ($returnType ne "void") { |
| # TODO: return proper default result |
| # FIXME: Temporary hack for generating a proper implementation |
| # of the webkit_dom_document_evaluate function (Bug-ID: 42115) |
| if (!(($functionName eq "webkit_dom_document_evaluate") && ($paramIDLType eq "XPathResult"))) { |
| push(@cBody, " g_return_val_if_fail($paramName, 0);\n"); |
| } |
| } else { |
| push(@cBody, " g_return_if_fail($paramName);\n"); |
| } |
| } |
| } |
| |
| $returnParamName = ""; |
| foreach my $param (@{$function->parameters}) { |
| my $paramIDLType = $param->type; |
| my $paramName = decamelize($param->name); |
| |
| my $paramIsGDOMType = IsGDOMClassType($paramIDLType); |
| if ($paramIDLType eq "DOMString") { |
| push(@cBody, " WTF::String converted_${paramName} = WTF::String::fromUTF8($paramName);\n"); |
| } elsif ($paramIDLType eq "CompareHow") { |
| push(@cBody, " WebCore::Range::CompareHow converted_${paramName} = static_cast<WebCore::Range::CompareHow>($paramName);\n"); |
| } elsif ($paramIsGDOMType) { |
| push(@cBody, " WebCore::${paramIDLType} * converted_${paramName} = NULL;\n"); |
| push(@cBody, " if (${paramName} != NULL) {\n"); |
| push(@cBody, " converted_${paramName} = WebKit::core($paramName);\n"); |
| |
| if ($returnType ne "void") { |
| # TODO: return proper default result |
| push(@cBody, " g_return_val_if_fail(converted_${paramName}, 0);\n"); |
| } else { |
| push(@cBody, " g_return_if_fail(converted_${paramName});\n"); |
| } |
| |
| push(@cBody, " }\n"); |
| } |
| $returnParamName = "converted_".$paramName if $param->extendedAttributes->{"Return"}; |
| } |
| |
| my $assign = ""; |
| my $assignPre = ""; |
| my $assignPost = ""; |
| |
| # We need to special-case these Node methods because their C++ |
| # signature is different from what we'd expect given their IDL |
| # description; see Node.h. |
| my $functionHasCustomReturn = $functionName eq "webkit_dom_node_append_child" || |
| $functionName eq "webkit_dom_node_insert_before" || |
| $functionName eq "webkit_dom_node_replace_child" || |
| $functionName eq "webkit_dom_node_remove_child"; |
| |
| if ($returnType ne "void" && !$functionHasCustomReturn) { |
| if ($returnValueIsGDOMType) { |
| $assign = "PassRefPtr<WebCore::${functionSigType}> g_res = "; |
| $assignPre = "WTF::getPtr("; |
| $assignPost = ")"; |
| } else { |
| $assign = "${returnType} res = "; |
| } |
| } |
| my $exceptions = ""; |
| if (@{$function->raisesExceptions}) { |
| push(@cBody, " WebCore::ExceptionCode ec = 0;\n"); |
| if (${callImplParams} ne "") { |
| $exceptions = ", ec"; |
| } else { |
| $exceptions = "ec"; |
| } |
| } |
| |
| if ($functionHasCustomReturn) { |
| my $customNodeAppendChild = << "EOF"; |
| bool ok = item->${functionSigName}(${callImplParams}${exceptions}); |
| if (ok) |
| { |
| ${returnType} res = WebKit::kit($returnParamName); |
| return res; |
| } |
| EOF |
| push(@cBody, $customNodeAppendChild); |
| |
| if(@{$function->raisesExceptions}) { |
| my $exceptionHandling = << "EOF"; |
| |
| WebCore::ExceptionCodeDescription ecdesc; |
| WebCore::getExceptionCodeDescription(ec, ecdesc); |
| g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); |
| EOF |
| push(@cBody, $exceptionHandling); |
| } |
| push(@cBody, "return NULL;"); |
| push(@cBody, "}\n\n"); |
| return; |
| } elsif ($functionSigType eq "DOMString") { |
| my $getterContentHead; |
| if ($prefix) { |
| my $getterExpressionPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $function); |
| $getterContentHead = "${assign}convertToUTF8String(item->$getterExpressionPrefix${exceptions}));\n"; |
| } else { |
| $getterContentHead = "${assign}convertToUTF8String(item->${functionSigName}(${callImplParams}${exceptions}));\n"; |
| } |
| push(@cBody, " ${getterContentHead}"); |
| } else { |
| my $contentHead; |
| if ($prefix eq "get_") { |
| my $getterExpressionPrefix = $codeGenerator->GetterExpressionPrefix(\%implIncludes, $interfaceName, $function); |
| $contentHead = "${assign}${assignPre}item->$getterExpressionPrefix${callImplParams}${exceptions}${assignPost});\n"; |
| } elsif ($prefix eq "set_") { |
| my $setterExpressionPrefix = $codeGenerator->SetterExpressionPrefix(\%implIncludes, $interfaceName, $function); |
| $contentHead = "${assign}${assignPre}item->$setterExpressionPrefix${callImplParams}${exceptions}${assignPost});\n"; |
| } else { |
| $contentHead = "${assign}${assignPre}item->${functionSigName}(${callImplParams}${exceptions}${assignPost});\n"; |
| } |
| push(@cBody, " ${contentHead}"); |
| |
| if(@{$function->raisesExceptions}) { |
| my $exceptionHandling = << "EOF"; |
| if (ec) { |
| WebCore::ExceptionCodeDescription ecdesc; |
| WebCore::getExceptionCodeDescription(ec, ecdesc); |
| g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), ecdesc.code, ecdesc.name); |
| } |
| EOF |
| push(@cBody, $exceptionHandling); |
| } |
| } |
| |
| if ($returnType ne "void" && !$functionHasCustomReturn) { |
| if ($functionSigType ne "DOMObject") { |
| if ($returnValueIsGDOMType) { |
| push(@cBody, " ${returnType} res = WebKit::kit(g_res.get());\n"); |
| } |
| } |
| if ($functionSigType eq "DOMObject") { |
| push(@cBody, " return NULL; /* TODO: return canvas object */\n"); |
| } else { |
| push(@cBody, " return res;\n"); |
| } |
| } |
| |
| if ($conditionalString) { |
| if ($returnType ne "void") { |
| push(@cBody, "#else\n"); |
| if ($codeGenerator->IsNonPointerType($functionSigType)) { |
| push(@cBody, " return static_cast<${returnType}>(0);\n"); |
| } else { |
| push(@cBody, " return NULL;\n"); |
| } |
| } |
| push(@cBody, "#endif /* ${conditionalString} */\n") if $conditionalString; |
| } |
| |
| push(@cBody, "}\n\n"); |
| } |
| |
| sub ClassHasFunction { |
| my ($class, $name) = @_; |
| |
| foreach my $function (@{$class->functions}) { |
| if ($function->signature->name eq $name) { |
| return 1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| sub GenerateFunctions { |
| my ($object, $interfaceName, $dataNode) = @_; |
| |
| foreach my $function (@{$dataNode->functions}) { |
| $object->GenerateFunction($interfaceName, $function, ""); |
| } |
| |
| TOP: |
| foreach my $attribute (@{$dataNode->attributes}) { |
| if (SkipAttribute($attribute) || |
| $attribute->signature->type eq "EventListener" || |
| $attribute->signature->type eq "MediaQueryListListener") { |
| next TOP; |
| } |
| |
| if ($attribute->signature->name eq "type" |
| # This will conflict with the get_type() function we define to return a GType |
| # according to GObject conventions. Skip this for now. |
| || $attribute->signature->name eq "URL" # TODO: handle this |
| ) { |
| next TOP; |
| } |
| |
| my $attrNameUpper = $codeGenerator->WK_ucfirst($attribute->signature->name); |
| my $getname = "get${attrNameUpper}"; |
| my $setname = "set${attrNameUpper}"; |
| if (ClassHasFunction($dataNode, $getname) || ClassHasFunction($dataNode, $setname)) { |
| # Very occasionally an IDL file defines getter/setter functions for one of its |
| # attributes; in this case we don't need to autogenerate the getter/setter. |
| next TOP; |
| } |
| |
| # Generate an attribute getter. For an attribute "foo", this is a function named |
| # "get_foo" which calls a DOM class method named foo(). |
| my $function = new domFunction(); |
| $function->signature($attribute->signature); |
| $function->raisesExceptions($attribute->getterExceptions); |
| $object->GenerateFunction($interfaceName, $function, "get_"); |
| |
| # FIXME: We are not generating setters for 'Replaceable' |
| # attributes now, but we should somehow. |
| if ($attribute->type =~ /^readonly/ || |
| $attribute->signature->extendedAttributes->{"Replaceable"}) { |
| next TOP; |
| } |
| |
| # Generate an attribute setter. For an attribute, "foo", this is a function named |
| # "set_foo" which calls a DOM class method named setFoo(). |
| $function = new domFunction(); |
| |
| $function->signature(new domSignature()); |
| $function->signature->name($attribute->signature->name); |
| $function->signature->type($attribute->signature->type); |
| $function->signature->extendedAttributes($attribute->signature->extendedAttributes); |
| |
| my $param = new domSignature(); |
| $param->name("value"); |
| $param->type($attribute->signature->type); |
| my %attributes = (); |
| $param->extendedAttributes(attributes); |
| my $arrayRef = $function->parameters; |
| push(@$arrayRef, $param); |
| |
| $function->raisesExceptions($attribute->setterExceptions); |
| |
| $object->GenerateFunction($interfaceName, $function, "set_"); |
| } |
| } |
| |
| sub GenerateCFile { |
| my ($object, $interfaceName, $parentClassName, $parentGObjType, $dataNode) = @_; |
| |
| if ($dataNode->extendedAttributes->{"EventTarget"}) { |
| $object->GenerateEventTargetIface($dataNode); |
| } |
| |
| my $implContent = ""; |
| |
| my $clsCaps = uc(FixUpDecamelizedName(decamelize($interfaceName))); |
| my $lowerCaseIfaceName = "webkit_dom_" . FixUpDecamelizedName(decamelize($interfaceName)); |
| |
| $implContent = << "EOF"; |
| ${defineTypeMacro}(${className}, ${lowerCaseIfaceName}, ${parentGObjType}${defineTypeInterfaceImplementation} |
| |
| namespace WebKit { |
| |
| WebCore::${interfaceName}* core(${className}* request) |
| { |
| g_return_val_if_fail(request, 0); |
| |
| WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(request)->coreObject); |
| g_return_val_if_fail(coreObject, 0); |
| |
| return coreObject; |
| } |
| |
| } // namespace WebKit |
| EOF |
| |
| push(@cBodyPriv, $implContent); |
| $object->GenerateProperties($interfaceName, $dataNode); |
| $object->GenerateFunctions($interfaceName, $dataNode); |
| |
| my $wrapMethod = << "EOF"; |
| namespace WebKit { |
| ${className}* wrap${interfaceName}(WebCore::${interfaceName}* coreObject) |
| { |
| g_return_val_if_fail(coreObject, 0); |
| |
| /* We call ref() rather than using a C++ smart pointer because we can't store a C++ object |
| * in a C-allocated GObject structure. See the finalize() code for the |
| * matching deref(). |
| */ |
| coreObject->ref(); |
| |
| return WEBKIT_DOM_${clsCaps}(g_object_new(WEBKIT_TYPE_DOM_${clsCaps}, |
| "core-object", coreObject, NULL)); |
| } |
| } // namespace WebKit |
| EOF |
| push(@cBodyPriv, $wrapMethod); |
| } |
| |
| sub GenerateEndHeader { |
| my ($object) = @_; |
| |
| #Header guard |
| my $guard = $className . "_h"; |
| |
| push(@hBody, "G_END_DECLS\n\n"); |
| push(@hPrefixGuardEnd, "#endif /* $guard */\n"); |
| } |
| |
| sub GeneratePrivateHeader { |
| my $object = shift; |
| my $dataNode = shift; |
| |
| my $interfaceName = $dataNode->name; |
| my $filename = "$outputDir/" . $className . "Private.h"; |
| my $guard = uc(decamelize($className)) . "_PRIVATE_H"; |
| my $parentClassName = GetParentClassName($dataNode); |
| my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; |
| my $hasRealParent = @{$dataNode->parents} > 0; |
| my $hasParent = $hasLegacyParent || $hasRealParent; |
| |
| open(PRIVHEADER, ">$filename") or die "Couldn't open file $filename for writing"; |
| |
| print PRIVHEADER split("\r", $licenceTemplate); |
| print PRIVHEADER "\n"; |
| |
| my $text = << "EOF"; |
| #ifndef $guard |
| #define $guard |
| |
| #include <glib-object.h> |
| #include <webkit/${parentClassName}.h> |
| #include "${interfaceName}.h" |
| EOF |
| |
| print PRIVHEADER $text; |
| |
| print PRIVHEADER map { "#include \"$_\"\n" } sort keys(%hdrPropIncludes); |
| print PRIVHEADER "\n" if keys(%hdrPropIncludes); |
| |
| $text = << "EOF"; |
| namespace WebKit { |
| ${className} * |
| wrap${interfaceName}(WebCore::${interfaceName} *coreObject); |
| |
| WebCore::${interfaceName} * |
| core(${className} *request); |
| |
| EOF |
| |
| print PRIVHEADER $text; |
| |
| if ($className ne "WebKitDOMNode") { |
| $text = << "EOF"; |
| ${className}* |
| kit(WebCore::${interfaceName}* node); |
| |
| EOF |
| print PRIVHEADER $text; |
| } |
| |
| $text = << "EOF"; |
| } // namespace WebKit |
| |
| #endif /* ${guard} */ |
| EOF |
| print PRIVHEADER $text; |
| |
| close(PRIVHEADER); |
| } |
| |
| sub UsesManualKitImplementation { |
| my $type = shift; |
| |
| return 1 if $type eq "Node" or $type eq "Element" or $type eq "Event"; |
| return 0; |
| } |
| |
| sub GenerateEventTargetIface { |
| my $object = shift; |
| my $dataNode = shift; |
| |
| my $interfaceName = $dataNode->name; |
| my $decamelize = FixUpDecamelizedName(decamelize($interfaceName)); |
| |
| $implIncludes{"GObjectEventListener.h"} = 1; |
| $implIncludes{"WebKitDOMEventTarget.h"} = 1; |
| $implIncludes{"WebKitDOMEventPrivate.h"} = 1; |
| |
| my $impl = << "EOF"; |
| static void webkit_dom_${decamelize}_dispatch_event(WebKitDOMEventTarget* target, WebKitDOMEvent* event, GError** error) |
| { |
| WebCore::Event* coreEvent = WebKit::core(event); |
| WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject); |
| |
| WebCore::ExceptionCode ec = 0; |
| coreTarget->dispatchEvent(coreEvent, ec); |
| if (ec) { |
| WebCore::ExceptionCodeDescription description; |
| WebCore::getExceptionCodeDescription(ec, description); |
| g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.code, description.name); |
| } |
| } |
| |
| static gboolean webkit_dom_${decamelize}_add_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble, gpointer userData) |
| { |
| WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject); |
| return WebCore::GObjectEventListener::addEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble, userData); |
| } |
| |
| static gboolean webkit_dom_${decamelize}_remove_event_listener(WebKitDOMEventTarget* target, const char* eventName, GCallback handler, gboolean bubble) |
| { |
| WebCore::${interfaceName}* coreTarget = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(target)->coreObject); |
| return WebCore::GObjectEventListener::removeEventListener(G_OBJECT(target), coreTarget, eventName, handler, bubble); |
| } |
| |
| static void webkit_dom_event_target_init(WebKitDOMEventTargetIface* iface) |
| { |
| iface->dispatch_event = webkit_dom_${decamelize}_dispatch_event; |
| iface->add_event_listener = webkit_dom_${decamelize}_add_event_listener; |
| iface->remove_event_listener = webkit_dom_${decamelize}_remove_event_listener; |
| } |
| |
| EOF |
| |
| push(@cBody, $impl); |
| |
| $defineTypeMacro = "G_DEFINE_TYPE_WITH_CODE"; |
| $defineTypeInterfaceImplementation = ", G_IMPLEMENT_INTERFACE(WEBKIT_TYPE_DOM_EVENT_TARGET, webkit_dom_event_target_init))"; |
| } |
| |
| sub Generate { |
| my ($object, $dataNode) = @_; |
| |
| my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"}; |
| my $hasRealParent = @{$dataNode->parents} > 0; |
| my $hasParent = $hasLegacyParent || $hasRealParent; |
| my $parentClassName = GetParentClassName($dataNode); |
| my $parentGObjType = GetParentGObjType($dataNode); |
| my $interfaceName = $dataNode->name; |
| |
| # Add the guard if the 'Conditional' extended attribute exists |
| my $conditionalString = GenerateConditionalString($dataNode); |
| push(@conditionGuardStart, "#if ${conditionalString}\n\n") if $conditionalString; |
| push(@conditionGuardEnd, "#endif /* ${conditionalString} */\n") if $conditionalString; |
| |
| # Add the default impl header template |
| @cPrefix = split("\r", $licenceTemplate); |
| push(@cPrefix, "\n"); |
| |
| $implIncludes{"webkitdefines.h"} = 1; |
| $implIncludes{"webkitglobalsprivate.h"} = 1; |
| $implIncludes{"webkitmarshal.h"} = 1; |
| $implIncludes{"DOMObjectCache.h"} = 1; |
| $implIncludes{"WebKitDOMBinding.h"} = 1; |
| $implIncludes{"gobject/ConvertToUTF8String.h"} = 1; |
| $implIncludes{"webkit/$className.h"} = 1; |
| $implIncludes{"webkit/${className}Private.h"} = 1; |
| $implIncludes{"${interfaceName}.h"} = 1; |
| $implIncludes{"JSMainThreadExecState.h"} = 1; |
| $implIncludes{"ExceptionCode.h"} = 1; |
| |
| $hdrIncludes{"webkit/${parentClassName}.h"} = 1; |
| |
| if (!UsesManualKitImplementation($interfaceName)) { |
| my $converter = << "EOF"; |
| namespace WebKit { |
| |
| ${className}* kit(WebCore::$interfaceName* obj) |
| { |
| g_return_val_if_fail(obj, 0); |
| |
| if (gpointer ret = DOMObjectCache::get(obj)) |
| return static_cast<${className}*>(ret); |
| |
| return static_cast<${className}*>(DOMObjectCache::put(obj, WebKit::wrap${interfaceName}(obj))); |
| } |
| |
| } // namespace WebKit // |
| |
| EOF |
| push(@cBody, $converter); |
| } |
| |
| $object->GenerateHeader($interfaceName, $parentClassName); |
| $object->GenerateCFile($interfaceName, $parentClassName, $parentGObjType, $dataNode); |
| $object->GenerateEndHeader(); |
| $object->GeneratePrivateHeader($dataNode); |
| |
| } |
| |
| # Internal helper |
| sub WriteData { |
| my ($object, $name) = @_; |
| |
| # Write public header. |
| my $hdrFName = "$outputDir/" . $name . ".h"; |
| open(HEADER, ">$hdrFName") or die "Couldn't open file $hdrFName"; |
| |
| print HEADER @hPrefix; |
| print HEADER @hPrefixGuard; |
| print HEADER "#include \"webkit/webkitdomdefines.h\"\n"; |
| print HEADER "#include <glib-object.h>\n"; |
| print HEADER "#include <webkit/webkitdefines.h>\n"; |
| print HEADER map { "#include \"$_\"\n" } sort keys(%hdrIncludes); |
| print HEADER "\n" if keys(%hdrIncludes); |
| print HEADER "\n"; |
| print HEADER @hBodyPre; |
| print HEADER @hBody; |
| print HEADER @hPrefixGuardEnd; |
| |
| close(HEADER); |
| |
| # Write the implementation sources |
| my $implFileName = "$outputDir/" . $name . ".cpp"; |
| open(IMPL, ">$implFileName") or die "Couldn't open file $implFileName"; |
| |
| print IMPL @cPrefix; |
| print IMPL "#include <glib-object.h>\n"; |
| print IMPL "#include \"config.h\"\n\n"; |
| print IMPL @conditionGuardStart; |
| print IMPL "#include <wtf/GetPtr.h>\n"; |
| print IMPL "#include <wtf/RefPtr.h>\n"; |
| print IMPL map { "#include \"$_\"\n" } sort keys(%implIncludes); |
| print IMPL "\n" if keys(%implIncludes); |
| print IMPL @cBody; |
| |
| print IMPL "\n"; |
| print IMPL @cBodyPriv; |
| print IMPL @conditionGuardEnd; |
| |
| close(IMPL); |
| |
| %implIncludes = (); |
| %hdrIncludes = (); |
| @hPrefix = (); |
| @hBody = (); |
| |
| @cPrefix = (); |
| @cBody = (); |
| @cBodyPriv = (); |
| } |
| |
| sub GenerateInterface { |
| my ($object, $dataNode, $defines) = @_; |
| my $name = $dataNode->name; |
| |
| # Set up some global variables |
| $className = GetClassName($dataNode->name); |
| $object->Generate($dataNode); |
| |
| # Write changes |
| my $fname = "WebKitDOM_" . $name; |
| $fname =~ s/_//g; |
| $object->WriteData($fname); |
| } |