4 # Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
5 # Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
7 # This file is part of the KDE project
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Library General Public
11 # License as published by the Free Software Foundation; either
12 # version 2 of the License, or (at your option) any later version.
14 # This library is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 # Library General Public License for more details.
19 # You should have received a copy of the GNU Library General Public License
20 # aint with this library; see the file COPYING.LIB. If not, write to
21 # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 # Boston, MA 02111-1307, USA.
25 package CodeGenerator;
28 my $useGenerator = "";
29 my $useOutputDir = "";
30 my $useDirectories = "";
31 my $useLayerOnTop = 0;
33 my $codeGenerator = 0;
35 my %primitiveTypeHash = ("int" => 1, "short" => 1, "long" => 1,
36 "unsigned int" => 1, "unsigned short" => 1,
37 "unsigned long" => 1, "float" => 1,
38 "double" => 1, "boolean" => 1, "void" => 1);
40 my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1,
41 "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1,
42 "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1,
43 "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1,
44 "SVGAnimatedPreserveAspectRatio" => 1,
45 "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1,
46 "SVGAnimatedTransformList" => 1);
48 # Helpers for 'ScanDirectory'
50 my $foundFilename = "";
51 my @foundFilenames = ();
59 $useDirectories = shift;
60 $useGenerator = shift;
61 $useOutputDir = shift;
62 $useLayerOnTop = shift;
64 bless($reference, $object);
72 $name =~ s/[a-zA-Z0-9]*:://;
82 my $ifaceName = "CodeGenerator" . $useGenerator;
84 # Dynamically load external code generation perl module
85 require $ifaceName . ".pm";
86 $codeGenerator = $ifaceName->new($object, $useOutputDir, $useLayerOnTop);
87 unless (defined($codeGenerator)) {
88 my $classes = $useDocument->classes;
89 foreach my $class (@$classes) {
90 print "Skipping $useGenerator code generation for IDL interface \"" . $class->name . "\".\n";
95 # Start the actual code generation!
96 $codeGenerator->GenerateModule($useDocument, $defines);
98 my $classes = $useDocument->classes;
99 foreach my $class (@$classes) {
100 print "Generating $useGenerator bindings code for IDL interface \"" . $class->name . "\"...\n";
101 $codeGenerator->GenerateInterface($class, $defines);
104 $codeGenerator->finish();
107 sub AddMethodsConstantsAndAttributesFromParentClasses
109 # For the passed interface, recursively parse all parent
110 # IDLs in order to find out all inherited properties/methods.
113 my $dataNode = shift;
115 my @parents = @{$dataNode->parents};
116 my $parentsMax = @{$dataNode->parents};
118 my $constantsRef = $dataNode->constants;
119 my $functionsRef = $dataNode->functions;
120 my $attributesRef = $dataNode->attributes;
122 # Exception: For the DOM 'Node' is our topmost baseclass, not EventTargetNode.
123 return if $parentsMax eq 1 and $parents[0] eq "EventTargetNode";
125 my $ignoreParent = 1;
126 foreach (@{$dataNode->parents}) {
128 # Ignore first parent class, already handled by the generation itself.
133 my $interface = $object->StripModule($_);
135 # Step #1: Find the IDL file associated with 'interface'
139 foreach (@{$useDirectories}) {
140 $object->ScanDirectory("$interface.idl", $_, $_, 0) if ($foundFilename eq "");
143 if ($foundFilename ne "") {
144 print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interface\"\n";
146 # Step #2: Parse the found IDL file (in quiet mode).
147 my $parser = IDLParser->new(1);
148 my $document = $parser->Parse($foundFilename, "");
150 foreach my $class (@{$document->classes}) {
151 # Step #3: Collect constants & functions & attributes of this parent-class
152 my $constantsMax = @{$class->constants};
153 my $functionsMax = @{$class->functions};
154 my $attributesMax = @{$class->attributes};
156 print " | |> -> Inherting $constantsMax constants, $functionsMax functions, $attributesMax attributes...\n | |>\n";
158 # Step #4: Concatenate data
159 foreach (@{$class->constants}) {
160 push(@$constantsRef, $_);
163 foreach (@{$class->functions}) {
164 push(@$functionsRef, $_);
167 foreach (@{$class->attributes}) {
168 push(@$attributesRef, $_);
171 # Step #4: Enter recursive parent search
172 AddMethodsConstantsAndAttributesFromParentClasses($object, $class);
175 die("Could NOT find specified parent interface \"$interface\"!\n");
180 # Helper for all CodeGenerator***.pm modules
186 return 1 if ($primitiveTypeHash{$type});
190 sub IsSVGAnimatedType
195 return 1 if ($svgAnimatedTypeHash{$type});
204 my $interface = shift;
205 my $directory = shift;
206 my $useDirectory = shift;
207 my $reportAllFiles = shift;
209 return if ($endCondition eq 1) and ($reportAllFiles eq 0);
211 $thisDir = "$ENV{SOURCE_ROOT}/$directory";
212 opendir(DIR, $thisDir) or die "[ERROR] Can't open directory $thisDir: \"$!\"\n";
214 my @names = readdir(DIR) or die "[ERROR] Cant't read directory $thisDir \"$!\"\n";
217 foreach my $name (@names) {
218 # Skip if we already found the right file or
219 # if we encounter 'exotic' stuff (ie. '.', '..', '.svn')
220 next if ($endCondition eq 1) or ($name =~ /^\./);
222 # Recurisvely enter directory
223 if (-d "$thisDir/$name") {
224 $object->ScanDirectory($interface, "$thisDir/$name", $useDirectory, $reportAllFiles);
228 # Check wheter we found the desired file
229 my $condition = ($name eq $interface);
230 $condition = 1 if ($interface eq "allidls") and ($name =~ /\.idl$/);
233 $foundFilename = "$thisDir/$name";
235 if ($reportAllFiles eq 0) {
238 push(@foundFilenames, $foundFilename);