CodeGeneratorGObject.pm 60 KB

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