4 # Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
5 # Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
6 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
7 # Copyright (C) 2006 Apple Computer, Inc.
9 # This file is part of the KDE project
11 # This library is free software; you can redistribute it and/or
12 # modify it under the terms of the GNU Library General Public
13 # License as published by the Free Software Foundation; either
14 # version 2 of the License, or (at your option) any later version.
16 # This library is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 # Library General Public License for more details.
21 # You should have received a copy of the GNU Library General Public License
22 # aint with this library; see the file COPYING.LIB. If not, write to
23 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 # Boston, MA 02111-1307, USA.
27 package CodeGeneratorObjC;
33 my %implIncludes = ();
34 my %headerForwardDeclarations = ();
35 my %headerForwardDeclarationsForProtocols = ();
37 my $exceptionInit = "WebCore::ExceptionCode ec = 0;";
38 my $exceptionRaiseOnError = "raiseOnDOMError(ec);";
41 # Default Licence Templates
42 my $headerLicenceTemplate = << "EOF";
44 * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
45 * Copyright (C) 2006 Samuel Weinig <sam.weinig\@gmail.com>
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
56 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
57 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
59 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
60 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
61 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
62 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
63 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
64 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
66 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 my $implementationLicenceTemplate = << "EOF";
72 This file is part of the WebKit open source project.
73 This file has been generated by generate-bindings.pl. DO NOT MODIFY!
75 This library is free software; you can redistribute it and/or
76 modify it under the terms of the GNU Library General Public
77 License as published by the Free Software Foundation; either
78 version 2 of the License, or (at your option) any later version.
80 This library is distributed in the hope that it will be useful,
81 but WITHOUT ANY WARRANTY; without even the implied warranty of
82 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
83 Library General Public License for more details.
85 You should have received a copy of the GNU Library General Public License
86 along with this library; see the file COPYING.LIB. If not, write to
87 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
88 Boston, MA 02111-1307, USA.
98 $codeGenerator = shift;
101 bless($reference, $object);
110 $object->WriteData();
113 # Params: 'domClass' struct
114 sub GenerateInterface
117 my $dataNode = shift;
119 $object->RemoveExcludedAttributesAndFunctions($dataNode);
121 # Start actual generation..
122 $object->GenerateHeader($dataNode);
123 $object->GenerateImplementation($dataNode);
125 my $name = $dataNode->name;
127 # Open files for writing...
128 my $headerFileName = "$outputDir/DOM$name.h";
129 my $implFileName = "$outputDir/DOM$name.mm";
131 open($IMPL, ">$implFileName") or die "Couldn't open file $implFileName";
132 open($HEADER, ">$headerFileName") or die "Couldn't open file $headerFileName";
135 # Params: 'idlDocument' struct
139 my $dataNode = shift;
141 $module = $dataNode->module;
144 sub RemoveExcludedAttributesAndFunctions
147 my $dataNode = shift;
151 while ($i < @{$dataNode->attributes}) {
152 my $lang = ${$dataNode->attributes}[$i]->signature->extendedAttributes->{"Exclude"};
153 if ($lang and $lang eq "ObjC") {
154 splice(@{$dataNode->attributes}, $i, 1);
161 while ($i < @{$dataNode->functions}) {
162 my $lang = ${$dataNode->functions}[$i]->signature->extendedAttributes->{"Exclude"};
163 if ($lang and $lang eq "ObjC") {
164 splice(@{$dataNode->functions}, $i, 1);
173 my $name = $codeGenerator->StripModule(shift);
176 if ($name eq "boolean") {
178 } elsif ($name eq "unsigned long") {
180 } elsif ($name eq "long") {
182 } elsif ($name eq "DOMString") {
184 } elsif ($name eq "DOMWindow") {
185 return "DOMAbstractView";
186 } elsif ($name eq "XPathNSResolver") {
187 return "id <DOMXPathNSResolver>";
188 } elsif ($name eq "unsigned short"
191 or $name eq "DOMImplementation") {
195 # Default, assume objective-c type has the same type name as
196 # idl type prefixed with "DOM".
197 return "DOM" . $name;
202 my $name = $codeGenerator->StripModule(shift);
205 if ($name eq "DOMImplementation") {
206 return "WebCore::DOMImplementationFront";
209 return "WebCore::" . $name;
212 sub GetParentImplClassName
214 my $dataNode = shift;
216 if (@{$dataNode->parents} eq 0) {
220 my $parent = $codeGenerator->StripModule($dataNode->parents(0));
223 if ($parent eq "EventTargetNode") {
232 my $name = GetClassName(shift);
234 if ($codeGenerator->IsPrimitiveType($name)
236 or $name eq "unsigned"
238 or $name eq "id <DOMXPathNSResolver>") {
242 # Default, return type as a pointer.
248 my $type = $codeGenerator->StripModule(shift);
250 if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMString") {
254 if ($type eq "DOMRGBColor") {
255 return "_RGBColorWithRGB";
260 if ($type eq "HTMLCollection") {
261 $typeMaker = "collection";
262 } elsif ($type eq "HTMLFormElement") {
263 $typeMaker = "formElement";
264 } elsif ($type eq "HTMLDocument") {
265 $typeMaker = "HTMLDocument";
266 } elsif ($type eq "CSSStyleDeclaration") {
267 $typeMaker = "styleDeclaration";
268 } elsif ($type eq "CSSStyleSheet") {
269 $typeMaker = "CSSStyleSheet";
270 } elsif ($type eq "DOMImplementation") {
271 $typeMaker = "DOMImplementation";
272 } elsif ($type eq "CDATASection") {
273 $typeMaker = "CDATASection";
274 } elsif ($type eq "DOMWindow") {
275 $typeMaker = "abstractView";
276 } elsif ($type eq "XPathResult") {
277 $typeMaker = "xpathResult";
278 } elsif ($type eq "XPathNSResolver") {
279 $typeMaker = "xpathNSResolver";
280 } elsif ($type eq "XPathExpression") {
281 $typeMaker = "xpathExpression";
283 $typeMaker = lcfirst($type);
286 # put into the form "_fooBarWith" for type FooBar.
287 $typeMaker = "_" . $typeMaker . "With";
291 sub AddForwardDeclarationsForType
293 my $type = $codeGenerator->StripModule(shift);
295 if ($codeGenerator->IsPrimitiveType($type) or $type eq "DOMString") {
299 if ($type eq "DOMImplementation") {
300 $headerForwardDeclarations{"$type"} = 1;
304 if ($type eq "DOMWindow") {
305 $headerForwardDeclarations{"DOMAbstractView"} = 1;
309 if ($type eq "XPathNSResolver") {
310 # Only one protocol so far.
311 $headerForwardDeclarationsForProtocols{"DOMXPathNSResolver"} = 1;
315 $headerForwardDeclarations{"DOM$type"} = 1;
318 sub AddIncludesForType
320 my $type = $codeGenerator->StripModule(shift);
322 if ($codeGenerator->IsPrimitiveType($type)) {
326 if ($type eq "DOMString") {
327 $implIncludes{"PlatformString.h"} = 1;
332 if ($type eq "Counter"
333 or $type eq "MediaList"
334 or $type eq "CSSStyleSheet") {
335 $implIncludes{"DOMCSS.h"} = 1;
336 $implIncludes{"$type.h"} = 1;
339 if ($type eq "CSSStyleDeclaration") {
340 $implIncludes{"DOMCSS.h"} = 1;
341 $implIncludes{"$type.h"} = 1;
342 $implIncludes{"CSSMutableStyleDeclaration.h"} = 1;
345 if ($type eq "RGBColor" or $type eq "Rect") {
346 $implIncludes{"DOMCSS.h"} = 1;
351 if ($type eq "HTMLDocument") {
352 $implIncludes{"DOMHTML.h"} = 1;
353 $implIncludes{"DOMHTMLInternal.h"} = 1;
354 $implIncludes{"$type.h"} = 1;
359 if ($type eq "Event") {
360 $implIncludes{"DOMEvents.h"} = 1;
361 $implIncludes{"DOMEventsInternal.h"} = 1;
362 $implIncludes{"$type.h"} = 1;
366 # Temp DOMStyleSheets.h
367 if ($type eq "StyleSheetList") {
368 $implIncludes{"DOMStyleSheets.h"} = 1;
369 $implIncludes{"$type.h"} = 1;
374 if ($type eq "DOMWindow") {
375 $implIncludes{"DOMViews.h"} = 1;
376 $implIncludes{"DOMViewsInternal.h"} = 1;
377 $implIncludes{"$type.h"} = 1;
382 if ($type eq "XPathExpression"
383 or $type eq "XPathNSResolver"
384 or $type eq "XPathResult") {
385 $implIncludes{"DOMXPath.h"} = 1;
386 $implIncludes{"DOMXPathInternal.h"} = 1;
387 $implIncludes{"$type.h"} = 1;
391 # Temp DOMImplementationFront.h
392 if ($type eq "DOMImplementation") {
393 $implIncludes{"DOMImplementationFront.h"} = 1;
396 # Default, include the same named file (the implementation) and the same name prefixed with "DOM".
397 $implIncludes{"$type.h"} = 1;
398 $implIncludes{"DOM$type.h"} = 1;
404 my $dataNode = shift;
406 # Make sure that we don't have more than one parent.
407 if (@{$dataNode->parents} > 1) {
408 die "A class can't have more than one parent.";
411 my $interfaceName = $dataNode->name;
412 my $className = GetClassName($interfaceName);
413 my $parentClassName = "DOM" . GetParentImplClassName($dataNode);
415 my $numConstants = @{$dataNode->constants};
416 my $numAttributes = @{$dataNode->attributes};
417 my $numFunctions = @{$dataNode->functions};
419 # - Add default header template
420 @headerContentHeader = split("\r", $headerLicenceTemplate);
423 push(@headerContentHeader, "\n#import \"$parentClassName.h\" // parent class\n\n");
426 if ($numConstants > 0) {
427 my @headerConstants = ();
428 foreach my $constant (@{$dataNode->constants}) {
430 my $constantName = $constant->name;
431 my $constantValue = $constant->value;
432 my $output = " DOM_" . $constantName . " = " . $constantValue;
434 push(@headerConstants, $output);
436 my $combinedConstants = join(",\n", @headerConstants);
438 # FIXME: the formatting of the enums should line up the equal signs.
439 push(@headerContent, "\n// Constants\n");
440 push(@headerContent, "enum {\n");
441 push(@headerContent, $combinedConstants);
442 push(@headerContent, "\n};\n");
445 my %hashOfCatagories = ();
448 push(@headerContent, "\n\@interface $className : $parentClassName\n");
450 # - Add attribute getters/setters.
451 if ($numAttributes > 0) {
452 my @headerAttributes = ();
454 foreach (@{$dataNode->attributes}) {
457 AddForwardDeclarationsForType($attribute->signature->type);
459 my $attributeName = $attribute->signature->name;
460 my $attributeType = GetObjCType($attribute->signature->type);
461 my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
462 my $catagory = $attribute->signature->extendedAttributes->{"ObjCCatagory"};
465 my $getter = "- (" . $attributeType . ")" . $attributeName . ";\n";
468 push(@{ $hashOfCatagories{$catagory} }, $getter);
470 push(@headerAttributes, $getter);
475 if (!$attributeIsReadonly) {
476 my $setter = "- (void)set" . ucfirst($attributeName) . ":(" . $attributeType . ")" . $attributeName . ";\n";
479 push(@{ $hashOfCatagories{$catagory} }, $setter);
481 push(@headerAttributes, $setter);
486 if (@headerAttributes > 0) {
487 push(@headerContent, "\n// Attributes\n");
488 push(@headerContent, @headerAttributes);
493 if ($numFunctions > 0) {
494 my @headerFunctions = ();
496 foreach (@{$dataNode->functions}) {
499 AddForwardDeclarationsForType($function->signature->type);
501 my $functionName = $function->signature->name;
502 my $returnType = GetObjCType($function->signature->type);
503 my $numberOfParameters = @{$function->parameters};
504 my $catagory = $function->signature->extendedAttributes->{"ObjCCatagory"};
506 my $output = "- ($returnType)$functionName";
507 foreach my $param (@{$function->parameters}) {
508 my $paramName = $param->name;
509 my $paramType = GetObjCType($param->type);
510 AddForwardDeclarationsForType($param->type);
512 $output .= ":($paramType)$paramName ";
514 # remove any trailing spaces.
519 push(@{ $hashOfCatagories{$catagory} }, $output);
521 push(@headerFunctions, $output);
525 if (@headerFunctions > 0) {
526 push(@headerContent, "\n// Methods\n");
527 push(@headerContent, @headerFunctions);
532 push(@headerContent, "\n\@end\n");
534 # Add additional Catagories (if any)
535 if (scalar(keys(%hashOfCatagories))) {
537 foreach(sort(keys(%hashOfCatagories))) {
541 push(@headerContent, "\n\@interface $className ($catagory)\n");
543 foreach (@{ $hashOfCatagories{$catagory} }) {
544 my $declaration = $_;
545 push(@headerContent, $declaration);
549 push(@headerContent, "\@end\n");
554 sub GenerateImplementation
557 my $dataNode = shift;
559 my $interfaceName = $dataNode->name;
560 my $className = GetClassName($interfaceName);
561 my $implClassName = GetImplClassName($interfaceName);
562 my $parentImplClassName = GetParentImplClassName($dataNode);
565 my $numAttributes = @{$dataNode->attributes};
566 my $numFunctions = @{$dataNode->functions};
567 my $hasFunctionsOrAttributes = $numAttributes + $numFunctions;
569 # - Add default header template.
570 @implContentHeader = split("\r", $implementationLicenceTemplate);
573 push(@implContentHeader, "\n#import \"config.h\"\n");
574 push(@implContentHeader, "#import \"$className.h\"\n\n");
576 if ($hasFunctionsOrAttributes) {
577 # NEEDED for DOM_CAST
578 push(@implContentHeader, "#import \"DOMInternal.h\" // needed for DOM_cast<>\n");
580 # include module dependant internal interfaces.
581 if ($module eq "html") {
582 # HTML module internal interfaces
583 push(@implContentHeader, "#import \"DOMHTMLInternal.h\"\n");
584 } elsif ($module eq "css") {
585 # CSS module internal interfaces
586 push(@implContentHeader, "#import \"DOMCSSInternal.h\"\n");
587 } elsif ($module eq "events") {
588 # CSS module internal interfaces
589 push(@implContentHeader, "#import \"DOMEventsInternal.h\"\n");
590 } elsif ($module eq "xpath") {
591 # CSS module internal interfaces
592 push(@implContentHeader, "#import \"DOMXPathInternal.h\"\n");
595 # include Implementation class
596 push(@implContentHeader, "#import \"$interfaceName.h\" // implementation class\n");
597 if ($interfaceName eq "DOMImplementation") {
598 # FIXME: needed until we can remove DOMImplementationFront
599 push(@implContentHeader, "#import \"DOMImplementationFront.h\"\n");
605 # START implementation
606 push(@implContent, "\n\@implementation $className\n\n");
608 # ADD INTERNAL CASTING METHOD
609 my $internalCastingName = "_" . lcfirst($interfaceName);
610 my $implementation = "[self $internalCastingName]";
612 if ($hasFunctionsOrAttributes) {
613 if ($parentImplClassName eq "Object") {
614 # Only generate 'dealloc' and 'finalize' methods for direct subclasses of DOMObject.
616 push(@implContent, "- (void)dealloc\n");
617 push(@implContent, "{\n");
618 push(@implContent, " if (_internal)\n");
619 push(@implContent, " DOM_cast<$implClassName *>(_internal)->deref();\n");
620 push(@implContent, " [super dealloc];\n");
621 push(@implContent, "}\n\n");
623 push(@implContent, "- (void)finalize\n");
624 push(@implContent, "{\n");
625 push(@implContent, " if (_internal)\n");
626 push(@implContent, " DOM_cast<$implClassName *>(_internal)->deref();\n");
627 push(@implContent, " [super finalize];\n");
628 push(@implContent, "}\n\n");
630 push(@implContent, "- ($implClassName *)$internalCastingName\n");
631 push(@implContent, "{\n");
632 push(@implContent, " return DOM_cast<$implClassName *>(_internal);\n");
633 push(@implContent, "}\n\n");
637 my $internalBaseType;
638 if ($interfaceName eq "CSSPrimitiveValue") {
639 # FIXME: this should be a regex matching CSS...Value.
640 $internalBaseType = "WebCore::CSSValue"
641 } elsif ($interfaceName eq "CSSImportRule" or $interfaceName eq "CSSFontFaceRule") {
642 # FIXME: this should be a regex matching CSS...Rule.
643 $internalBaseType = "WebCore::CSSRule"
645 $internalBaseType = "WebCore::Node"
647 push(@implContent, "- ($implClassName *)$internalCastingName\n");
648 push(@implContent, "{\n");
649 push(@implContent, " return static_cast<$implClassName *>(DOM_cast<$internalBaseType *>(_internal));\n");
650 push(@implContent, "}\n\n");
655 if ($numAttributes > 0) {
656 foreach (@{$dataNode->attributes}) {
659 AddIncludesForType($attribute->signature->type);
661 my $attributeName = $attribute->signature->name;
662 my $attributeType = GetObjCType($attribute->signature->type);
663 my $attributeIsReadonly = ($attribute->type =~ /^readonly/);
666 my $getterSig = "- ($attributeType)$attributeName\n";
669 my $hasGetterException = @{$attribute->getterExceptions};
670 if ($hasGetterException) {
671 die "We should not have any getter exceptions yet!";
674 my $getterContentHead = "$implementation->$attributeName(";
675 my $getterContentTail = ")";
677 my $attributeTypeSansPtr = $attributeType;
678 $attributeTypeSansPtr =~ s/ \*$//; # Remove trailing " *" from pointer types.
679 my $typeMaker = GetObjCTypeMaker($attribute->signature->type);
680 if ($attributeTypeSansPtr eq "DOMImplementation") {
681 # FIXME: We have to special case DOMImplementation until DOMImplementationFront is removed
682 $getterContentHead = "[$attributeTypeSansPtr $typeMaker:implementationFront($implementation";
683 $getterContentTail .= "]";
684 } elsif ($typeMaker ne "") {
685 # Surround getter with TypeMaker
686 $getterContentHead = "[$attributeTypeSansPtr $typeMaker:" . $getterContentHead;
687 $getterContentTail .= "]";
690 if ($attribute->signature->extendedAttributes->{"UsesPassRefPtr"}) {
691 $getterContentTail = ").get(" . $functionContentTail;
695 if ($hasGetterException) {
696 $getterContent = $getterContentHead . "ec" . $getterContentTail;
698 $getterContent = $getterContentHead . $getterContentTail;
701 push(@implContent, $getterSig);
702 push(@implContent, "{\n");
703 push(@implContent, " $exceptionInit\n") if $hasGetterException;
704 push(@implContent, " return $getterContent;\n");
705 push(@implContent, " $exceptionRaiseOnError\n") if $hasGetterException;
706 push(@implContent, "}\n\n");
709 if (!$attributeIsReadonly) {
712 my $hasSetterException = @{$attribute->setterExceptions};
714 my $setterName = "set" . ucfirst($attributeName);
715 my $setterSig = "- (void)$setterName:($attributeType)$attributeName\n";
717 push(@implContent, $setterSig);
718 push(@implContent, "{\n");
720 if ($hasSetterException) {
721 # FIXME: asserts exsist in the exsisting bindings, but I am unsure why they are
722 # there in the first place;
723 push(@implContent, " ASSERT($attributeName);\n\n");
725 push(@implContent, " $exceptionInit\n");
726 push(@implContent, " $implementation->$setterName($attributeName, ec);\n");
727 push(@implContent, " $exceptionRaiseOnError\n");
729 push(@implContent, " $implementation->$setterName($attributeName);\n");
732 push(@implContent, "}\n\n");
738 if ($numFunctions > 0) {
739 foreach (@{$dataNode->functions}) {
742 AddIncludesForType($function->signature->type);
744 my $functionName = $function->signature->name;
745 my $returnType = GetObjCType($function->signature->type);
746 my $hasParameters = @{$function->parameters};
747 my $raisesExceptions = @{$function->raisesExceptions};
749 my @parameterNames = ();
750 my @needsAssert = ();
753 my $functionSig = "- ($returnType)$functionName";
754 foreach (@{$function->parameters}) {
757 my $paramType = GetObjCType($param->type);
758 AddIncludesForType($param->type);
760 my $paramName = $param->name;
762 # FIXME: should move this out into it's own fuction to take care of possible special cases.
763 my $idlType = $codeGenerator->StripModule($param->type);
764 if ($codeGenerator->IsPrimitiveType($idlType) or $idlType eq "DOMString") {
765 push(@parameterNames, $paramName);
766 } elsif ($idlType eq "XPathNSResolver") {
767 my $implGetter = "[nativeResolver _xpathNSResolver]";
768 push(@parameterNames, $implGetter);
769 $needsCustom{"XPathNSResolver"} = $paramName;
770 } elsif ($idlType eq "XPathResult") {
771 my $implGetter = "[" . $paramName . " _xpathResult]";
772 push(@parameterNames, $implGetter);
774 my $implGetter = "[" . $paramName . " _" . lcfirst($idlType) . "]";
775 push(@parameterNames, $implGetter);
778 if (!$param->extendedAttributes->{"IsIndex"}) {
779 push(@needsAssert, " ASSERT($paramName);\n");
782 $functionSig .= ":($paramType)$paramName ";
784 # remove any trailing spaces.
785 $functionSig =~ s/\s+$//;
787 my @functionContent = ();
789 if ($returnType eq "void") {
790 # Special case 'void' return type.
792 my $functionContentHead = "$implementation->$functionName(";
793 my $functionContentTail = ");";
796 if ($hasParameters) {
797 my $params = join(", ", @parameterNames);
798 if ($raisesExceptions) {
799 $content = $functionContentHead . $params . ", ec" . $functionContentTail;
801 $content = $functionContentHead . $params . $functionContentTail;
804 if ($raisesExceptions) {
805 $content = $functionContentHead . "ec" . $functionContentTail;
807 $content = $functionContentHead . $functionContentTail;
811 if ($raisesExceptions) {
812 push(@functionContent, " $exceptionInit\n");
813 push(@functionContent, " $content\n");
814 push(@functionContent, " $exceptionRaiseOnError\n");
816 push(@functionContent, " $content\n");
821 my $functionContentHead = $implementation . "->" . $functionName . "(";
822 my $functionContentTail = ")";
824 my $typeMaker = GetObjCTypeMaker($function->signature->type);
825 unless ($typeMaker eq "") {
826 my $returnTypeClass = "";
827 if ($function->signature->type eq "XPathNSResolver") {
828 # Special case XPathNSResolver
829 $returnTypeClass = "DOMNativeXPathNSResolver";
831 # Remove trailing " *" from pointer types.
832 $returnTypeClass = $returnType;
833 $returnTypeClass =~ s/ \*$//;
836 # Surround getter with TypeMaker
837 $functionContentHead = "[$returnTypeClass $typeMaker:" . $functionContentHead;
838 $functionContentTail .= "]";
841 if ($function->signature->extendedAttributes->{"UsesPassRefPtr"}) {
842 $functionContentTail = ").get(" . $functionContentTail;
847 if ($hasParameters) {
848 my $params = join(", " , @parameterNames);
849 if ($raisesExceptions) {
850 # A temparary variable is needed.
851 $content = $functionContentHead . $params . ", ec" . $functionContentTail;
853 $content = $functionContentHead . $params . $functionContentTail;
856 if ($raisesExceptions) {
857 # A temparary variable is needed.
858 $content = $functionContentHead . "ec" . $functionContentTail;
860 $content = $functionContentHead . $functionContentTail;
865 if ($raisesExceptions) {
866 # Differentiated between when the return type is a pointer and
867 # not for white space issue (ie. Foo *result vs. int result).
868 if ($returnType =~ /\*$/) {
869 $content = $returnType . "result = " . $content;
871 $content = $returnType . " result = " . $content;
874 push(@functionContent, " $exceptionInit\n");
875 push(@functionContent, " $content;\n");
876 push(@functionContent, " $exceptionRaiseOnError\n");
877 push(@functionContent, " return result;\n");
879 push(@functionContent, " return $content;\n");
883 push(@implContent, "$functionSig\n");
884 push(@implContent, "{\n");
886 # special case the XPathNSResolver
887 if (defined $needsCustom{"XPathNSResolver"}) {
888 my $paramName = $needsCustom{"XPathNSResolver"};
889 push(@implContent, " if ($paramName && ![$paramName isMemberOfClass:[DOMNativeXPathNSResolver class]])\n");
890 push(@implContent, " [NSException raise:NSGenericException format:\@\"createExpression currently does not work with custom NS resolvers\"];\n");
891 push(@implContent, " DOMNativeXPathNSResolver *nativeResolver = (DOMNativeXPathNSResolver *)$paramName;\n\n");
893 push(@implContent, @functionContent);
894 push(@implContent, "}\n\n");
902 push(@implContent, "\@end\n");
908 if (defined($IMPL)) {
909 # Write content to file.
910 print $IMPL @implContentHeader;
912 foreach my $implInclude (sort keys(%implIncludes)) {
913 print $IMPL "#import \"$implInclude\"\n";
916 print $IMPL @implContent;
920 @implHeaderContent = "";
925 if (defined($HEADER)) {
926 # Write content to file.
927 print $HEADER @headerContentHeader;
929 foreach my $forwardClassDeclaration (sort keys(%headerForwardDeclarations)) {
930 print $HEADER "\@class $forwardClassDeclaration;\n";
933 foreach my $forwardProtocolDeclaration (sort keys(%headerForwardDeclarationsForProtocols)) {
934 print $HEADER "\@protocol $forwardProtocolDeclaration;\n";
937 print $HEADER @headerContent;
941 @headerContentHeader = "";
943 %headerForwardDeclarations = ();