CodeGeneratorGObject.pm [plain text]
package CodeGeneratorGObject;
my %implIncludes = ();
my %hdrIncludes = ();
my @txtInstallProps = ();
my @txtSetProps = ();
my @txtGetProps = ();
my $className = "";
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));
}
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;
$classname =~ s/x_path/xpath/;
$classname =~ s/web_kit/webkit/;
return $classname;
}
sub ClassNameToGObjectType {
my $className = shift;
my $CLASS_NAME = uc(decamelize($className));
$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/;
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"} ||
$attribute->signature->extendedAttributes->{"Replaceable"}) {
return 1;
}
my $propType = $attribute->signature->type;
if ($propType eq "EventListener") {
return 1;
}
if ($propType =~ /Constructor$/) {
return 1;
}
if ($attribute->signature->name eq "location") {
return 1;
}
if ($attribute->signature->name eq "valueAsDate") {
return 1;
}
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_replace_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->type eq "Event") {
return 1;
}
if ($function->signature->name eq "getSVGDocument") {
return 1;
}
if ($function->signature->name eq "getCSSCanvasContext") {
return 1;
}
return 0;
}
sub GetGValueTypeName {
my $type = shift;
my %types = ("DOMString", "string",
"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";
}
sub GetGlibTypeName {
my $type = shift;
my $name = GetClassName($type);
my %types = ("DOMString", "gchar* ",
"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");
if ($writeable && $hasGtypeSignature) {
push(@result, $property);
}
}
return @result;
}
sub GenerateProperty {
my $attribute = shift;
my $interfaceName = shift;
my @writeableProperties = @{shift @_};
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, " ${propEnum},\n");
my $propType = $attribute->signature->type;
my ${propGType} = decamelize($propType);
if ($propGType eq "event_target") {
$propGType = "event_target_node";
}
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 = "WebCore::String::fromUTF8";
} elsif ($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
$convertFunction = "WebCore::String::number";
}
my $setterContentHead;
my $getterContentHead;
my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
if ($reflect || $reflectURL) {
my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $camelPropName : ($reflect || $reflectURL);
my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
$implIncludes{"${namespace}.h"} = 1;
my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
$setterContentHead = "coreSelf->setAttribute(WebCore::${namespace}::${contentAttributeName}Attr, ${convertFunction}(g_value_get_$gtype(value))";
$getterContentHead = "coreSelf->${getAttributeFunctionName}(WebCore::${namespace}::${contentAttributeName}Attr";
} else {
$setterContentHead = "coreSelf->set${setPropNameFunction}(${convertFunction}(g_value_get_$gtype(value))";
$getterContentHead = "coreSelf->${getPropNameFunction}(";
}
if (grep {$_ eq $attribute} @writeableProperties) {
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(@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;
}
if($attribute->signature->extendedAttributes->{"ConvertFromString"}) {
if($gtype eq "long") {
$convertFunction = "";
$postConvertFunction = ".toInt()";
} else {
die "Can't convert to type ${gtype}.";
}
}
my $_gtype = $gtype;
if ($gtype eq "ushort") {
$_gtype = "uint";
}
if (!$done) {
push(@txtGetProps, " g_value_set_$_gtype(value, ${convertFunction}coreSelf->${getPropNameFunction}(${exception})${postConvertFunction});\n");
}
push(@txtGetProps, " break;\n }\n");
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, $txtInstallProp);
}
sub GenerateProperties {
my ($object, $interfaceName, $dataNode) = @_;
my $clsCaps = substr(ClassNameToGObjectType($className), 12);
my $lowerCaseIfaceName = "webkit_dom_" . (FixUpDecamelizedName(decamelize($interfaceName)));
my $implContent = "";
$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)
{
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)
{
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) {
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);
my $txtInstallSignals = "";
$implContent = << "EOF";
static void ${lowerCaseIfaceName}_finalize(GObject* object)
{
WebKitDOMObject* dom_object = WEBKIT_DOM_OBJECT(object);
if (dom_object->coreObject != NULL) {
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}_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;
@txtInstallProps
$txtInstallSignals
}
static void ${lowerCaseIfaceName}_init(${className}* request)
{
}
EOF
push(@cBodyPriv, $implContent);
}
sub GenerateHeader {
my ($object, $interfaceName, $parentClassName) = @_;
my $implContent = "";
@hPrefix = split("\r", $licenceTemplate);
push(@hPrefix, "\n");
my $guard = $className . "_h";
@hPrefixGuard = << "EOF";
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";
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 "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 (SkipFunction($function, $decamelize, $prefix)) {
return;
}
my $functionSigName = $function->signature->name;
my $functionSigType = $function->signature->type;
my $functionName = "webkit_dom_" . $decamelize . "_" . $prefix . decamelize($functionSigName);
my $returnType = GetGlibTypeName($functionSigType);
my $returnValueIsGDOMType = IsGDOMClassType($functionSigType);
my $functionSig = "$className *self";
my $callImplParams = "";
my $isCustomFunction = $function->signature->extendedAttributes->{"Custom"} ||
$function->signature->extendedAttributes->{"CustomArgumentHandling"};
foreach my $param (@{$function->parameters}) {
my $paramIDLType = $param->type;
if ($paramIDLType eq "Event" || $paramIDLType eq "EventListener") {
push(@hBody, "\n/* TODO: event function ${functionName} */\n\n");
push(@cBody, "\n/* TODO: event function ${functionName} */\n\n");
return;
}
addIncludeInBody($paramIDLType);
my $paramType = GetGlibTypeName($paramIDLType);
my $paramName = decamelize($param->name);
$functionSig .= ", $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 = "_g_" . $paramName;
}
if ($callImplParams) {
$callImplParams .= ", $paramName";
} else {
$callImplParams = "$paramName";
}
}
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;
}
$implIncludes{"${functionSigType}.h"} = 1;
}
if(@{$function->raisesExceptions}) {
$functionSig .= ", GError **error";
}
push(@hBody, "WEBKIT_API $returnType\n$functionName ($functionSig);\n\n");
push(@cBody, "$returnType\n$functionName ($functionSig)\n{\n");
if ($returnType ne "void") {
push(@cBody, " g_return_val_if_fail (self, 0);\n");
} else {
push(@cBody, " g_return_if_fail (self);\n");
}
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") {
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, " WebCore::String _g_${paramName} = WebCore::String::fromUTF8($paramName);\n");
} elsif ($paramIDLType eq "CompareHow") {
push(@cBody, " WebCore::Range::CompareHow _g_${paramName} = static_cast<WebCore::Range::CompareHow>($paramName);\n");
} elsif ($paramIsGDOMType) {
push(@cBody, " WebCore::${paramIDLType} * _g_${paramName} = WebKit::core($paramName);\n");
if ($returnType ne "void") {
push(@cBody, " g_return_val_if_fail (_g_${paramName}, 0);\n");
} else {
push(@cBody, " g_return_if_fail (_g_${paramName});\n");
}
}
$returnParamName = "_g_".$paramName if $param->extendedAttributes->{"Return"};
}
my $assign = "";
my $assignPre = "";
my $assignPost = "";
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 = static_cast<${returnType}>(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;
my $reflect = $function->signature->extendedAttributes->{"Reflect"};
my $reflectURL = $function->signature->extendedAttributes->{"ReflectURL"};
if ($reflect || $reflectURL) {
my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $functionSigName : ($reflect || $reflectURL);
my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
$implIncludes{"${namespace}.h"} = 1;
my $getAttributeFunctionName = $reflectURL ? "getURLAttribute" : "getAttribute";
$getterContentHead = "${assign}convertToUTF8String(item->${getAttributeFunctionName}(WebCore::${namespace}::${contentAttributeName}Attr));\n";
} else {
$getterContentHead = "${assign}convertToUTF8String(item->${functionSigName}(${callImplParams}${exceptions}));\n";
}
push(@cBody, " ${getterContentHead}");
} else {
my $setterContentHead;
my $reflect = $function->signature->extendedAttributes->{"Reflect"};
my $reflectURL = $function->signature->extendedAttributes->{"ReflectURL"};
if ($reflect || $reflectURL) {
my $contentAttributeName = (($reflect || $reflectURL) eq "1") ? $functionSigName : ($reflect || $reflectURL);
$contentAttributeName =~ s/set//;
$contentAttributeName = $codeGenerator->WK_lcfirst($contentAttributeName);
my $namespace = $codeGenerator->NamespaceForAttributeName($interfaceName, $contentAttributeName);
$implIncludes{"${namespace}.h"} = 1;
$setterContentHead = "${assign}${assignPre}item->setAttribute(WebCore::${namespace}::${contentAttributeName}Attr, ${callImplParams}${exceptions}${assignPost});\n";
} else {
$setterContentHead = "${assign}${assignPre}item->${functionSigName}(${callImplParams}${exceptions}${assignPost});\n";
}
push(@cBody, " ${setterContentHead}");
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 = static_cast<${returnType}>(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");
}
}
push(@cBody, "\n}\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)) {
next TOP;
}
if ($attribute->signature->name eq "type"
|| $attribute->signature->name eq "URL" || $attribute->signature->extendedAttributes->{"ConvertFromString"} ) {
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)) {
next TOP;
}
my $function = new domFunction();
$function->signature($attribute->signature);
$function->raisesExceptions($attribute->getterExceptions);
$object->GenerateFunction($interfaceName, $function, "get_");
if ($attribute->type =~ /^readonly/) {
next TOP;
}
$function = new domFunction();
$function->signature(new domSignature());
$function->signature->name($setname);
$function->signature->type("void");
$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, "");
}
}
sub GenerateCFile {
my ($object, $interfaceName, $parentClassName, $parentGObjType, $dataNode) = @_;
my $implContent = "";
my $clsCaps = uc(FixUpDecamelizedName(decamelize($interfaceName)));
my $lowerCaseIfaceName = "webkit_dom_" . FixUpDecamelizedName(decamelize($interfaceName));
$implContent = << "EOF";
G_DEFINE_TYPE(${className}, ${lowerCaseIfaceName}, ${parentGObjType})
namespace WebKit {
${className}* wrap${interfaceName}(WebCore::${interfaceName}* coreObject)
{
g_return_val_if_fail(coreObject != 0, 0);
${className}* wrapper = WEBKIT_DOM_${clsCaps}(g_object_new(WEBKIT_TYPE_DOM_${clsCaps}, NULL));
g_return_val_if_fail(wrapper != 0, 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();
WEBKIT_DOM_OBJECT(wrapper)->coreObject = coreObject;
return wrapper;
}
WebCore::${interfaceName}* core(${className}* request)
{
g_return_val_if_fail(request != 0, 0);
WebCore::${interfaceName}* coreObject = static_cast<WebCore::${interfaceName}*>(WEBKIT_DOM_OBJECT(request)->coreObject);
g_return_val_if_fail(coreObject != 0, 0);
return coreObject;
}
} // namespace WebKit
EOF
push(@cBodyPriv, $implContent);
$object->GenerateProperties($interfaceName, $dataNode);
$object->GenerateFunctions($interfaceName, $dataNode);
}
sub GenerateEndHeader {
my ($object) = @_;
#Header guard
my $guard = $className . "_h";
push(@hBody, "G_END_DECLS\n\n");
push(@hBody, "#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 { " 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";
gpointer
kit(WebCore::${interfaceName}* node);
EOF
print PRIVHEADER $text;
}
$text = << "EOF";
} // namespace WebKit
EOF
print PRIVHEADER $text;
close(PRIVHEADER);
}
sub UsesManualKitImplementation {
my $type = shift;
return 1 if $type eq "Node" or $type eq "Element";
return 0;
}
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;
@cPrefix = split("\r", $licenceTemplate);
push(@cPrefix, "\n");
$implIncludes{"webkitmarshal.h"} = 1;
$implIncludes{"webkitprivate.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{"ExceptionCode.h"} = 1;
$hdrIncludes{"webkit/${parentClassName}.h"} = 1;
if (!UsesManualKitImplementation($interfaceName)) {
my $converter = << "EOF";
namespace WebKit {
gpointer kit(WebCore::$interfaceName* obj)
{
g_return_val_if_fail(obj != 0, 0);
if (gpointer ret = DOMObjectCache::get(obj))
return ret;
return 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);
}
sub WriteData {
my ($object, $name) = @_;
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;
close(HEADER);
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 "#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;
close(IMPL);
%implIncludes = ();
%hdrIncludes = ();
@hPrefix = ();
@hBody = ();
@cPrefix = ();
@cBody = ();
@cBodyPriv = ();
}
sub GenerateInterface {
my ($object, $dataNode, $defines) = @_;
my $name = $dataNode->name;
$className = GetClassName($dataNode->name);
$object->Generate($dataNode);
my $fname = "WebKitDOM_" . $name;
$fname =~ s/_//g;
$object->WriteData($fname);
}