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