Upstream tarball 20080630
[amule.git] / src / libs / ec / file_generator.pl
blob044fed589dcd645d918c129668b45d64c65676d6
1 #!/usr/bin/perl
4 ## This file is part of the aMule Project
5 ##
6 ## Copyright (c) 2004-2008 Angel Vidal ( kry@amule.org )
7 ## Copyright (c) 2007-2008 aMule Project ( http://www.amule-project.net )
8 ##
9 ## This program is free software; you can redistribute it and/or
10 ## modify it under the terms of the GNU General Public License
11 ## as published by the Free Software Foundation; either
12 ## version 2 of the License, or (at your option) any later version.
14 ## This program 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
17 ## GNU General Public License for more details.
19 ## You should have received a copy of the GNU General Public License
20 ## along with this program; if not, write to the Free Software
21 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 # Gimme a break, it's my second perl app... (Kry)
25 use File::Copy;
26 use warnings;
27 use strict;
28 use POSIX;
30 my $exit_with_help;
32 if ($#ARGV < 1) {
33 print "You must specify at least the folder and one abstract file.\n";
34 $exit_with_help = "true";
37 if ($exit_with_help) {
38 die "Usage: file_generator file.abstract [file2.abstract ...]\n";
42 my $folder = $ARGV[0] . "/";
44 my $numArgs = $#ARGV;
45 print "Parsing $numArgs files\n";
47 foreach my $argnum (1 .. $#ARGV) {
48 generate_files($folder, $ARGV[$argnum]);
52 sub generate_files {
54 my $folder = $_[0];
55 my $input_file = $_[1];
57 open(INFO, $folder . $input_file) or die "Cannot open input file " . $input_file . " for reading: $!"; # Open the file
59 my $line="no";
60 while ($line !~ /^\[Section Definition\]$/) {
61 $line = <INFO>;
62 if (!($line)) {
63 die $input_file . " seems not to have a Section Definition\n";
65 chop $line;
68 #We're at the start of the Section Definition.
69 # Read the Definition Section.
71 my $filename = "";
73 my $nameline = <INFO>;
74 if ($nameline =~ /^FileName\s+(.+)$/) {
75 $filename = $1;
76 } else {
77 die "Section Definition must start with FileName item.";
80 my $filecontent = "";
82 my $contentline = <INFO>;
83 if ($contentline =~ /^FileContent\s+(.+)$/) {
84 $filecontent = $1;
85 } else {
86 die "Section Definition must have a FileContent after the FileName item.";
89 #Skip the rest of the section, allow for extensions later.
91 $line = "";
92 while ($line && ($line !~ /^\[\/Section\]$/)) {
93 $line = <INFO>;
97 print "FileName: " . $filename . "\n";
98 print "FileContent: " . $filecontent . "\n";
100 #Open language output files
101 open(CPPFILE," > " . $folder . "cpp/$filename" . ".h");
102 #Open language output files
103 open(JAVAFILE," > " . $folder . "java/$filename" . ".java");
105 open(CDASHFILE, ">${folder}/c#/${filename}.cs");
107 # Print license on top.
108 write_license_header($folder, *CPPFILE, "// ", "", $filecontent);
109 write_license_header($folder, *CDASHFILE, "// ", "", $filecontent);
110 write_license_header($folder, *JAVAFILE, "// ", "", $filecontent);
111 #Example for a language that needs start/end:
112 #write_license_header($folder, *CFILE, "/* ", " */", $filecontent);
114 #Add top guards for each language
115 write_cpp_top_guard(*CPPFILE, $filename);
116 write_cdash_top_guard(*CDASHFILE);
117 # JAVA doesn't need guards, but needs file type declaration
118 print JAVAFILE "public interface " . $filename . " {\n\n";
119 ##Add other language guards
122 read_content(*INFO, *CPPFILE, *JAVAFILE, *CDASHFILE);
125 #Add bottom guards for each language
126 write_cpp_bottom_guard(*CPPFILE, $filename);
127 write_cdash_bottom_guard(*CDASHFILE);
128 # JAVA doesn't need guards, but we have to close the interface
129 print JAVAFILE "}\n";
130 ##Add other language guards
133 # Close language files
134 close(CPPFILE);
135 close(JAVAFILE);
137 print "All info parsed\n";
139 close(INFO);
143 ################ Generic Subroutines #####################
145 sub read_content {
146 local (*INFO) = $_[0];
147 local (*CPPFILE) = $_[1];
148 local (*JAVAFILE) = $_[2];
149 local (*CDASHFILE) = $_[3];
151 my $stop = "";
153 while (!($stop)) {
154 my $line="no";
156 #Skip till Content
157 while (!(eof(INFO)) && $line !~ /^\[Section Content\]$/) {
158 $line = <INFO>;
159 chop $line;
162 if ($line =~ /^\[Section Content\]$/) {
163 print "Reading content section...\n";
164 read_content_section(*INFO, *CPPFILE, *JAVAFILE, *CDASHFILE);
165 print CPPFILE "\n";
166 print JAVAFILE "\n";
167 } else {
168 print "No more content sections\n";
169 $stop = "yes";
174 sub read_content_section {
176 local (*INFO) = $_[0];
177 local (*CPPOUTPUT) = $_[1];
178 local (*JAVAOUTPUT) = $_[2];
179 local (*CDASHFILE) = $_[3];
181 my $line = <INFO>;
182 my $datatype = "";
183 if ($line =~ /^Type\s+(.+)$/) {
184 $datatype = $1;
185 print "\tDatatype: " . $datatype . "\n";
186 } else {
187 die "Content section has a non-typed data stream\n";
190 if ($datatype eq "Define") {
191 read_define_content(*INFO, *CPPOUTPUT, *JAVAOUTPUT, *CDASHFILE);
192 } elsif ($datatype eq "Enum") {
193 read_enum_content(*INFO, *CPPOUTPUT, *JAVAOUTPUT, *CDASHFILE);
194 } elsif ($datatype eq "TypeDef") {
195 read_typedef_content(*INFO, *CPPOUTPUT, *JAVAOUTPUT, *CDASHFILE);
196 } else {
197 die "Unknown type on content section\n";
202 sub read_define_content {
203 local (*INFO) = $_[0];
204 local (*CPPOUTPUT) = $_[1];
205 local (*JAVAOUTPUT) = $_[2];
206 local (*CDASHFILE) = $_[3];
208 my $line = <INFO>;
209 while (!(eof) && ($line !~ /^\[\/Section\]$/)) {
210 if ($line !~ /^(#.*|\s*)$/) {
211 if ($line =~ /^(.+)\s+(.+)$/) {
212 write_cpp_define_line(*CPPOUTPUT, $1, $2);
213 write_java_define_line(*JAVAOUTPUT, $1, $2);
214 write_cdash_define_line(*CDASHFILE, $1, $2);
215 } else {
216 die "Malformed content section define line\n";
219 $line = <INFO>;
223 sub read_typedef_content {
225 local (*INFO) = $_[0];
226 local (*CPPOUTPUT) = $_[1];
227 local (*JAVAOUTPUT) = $_[2];
229 my $line = <INFO>;
230 while (!(eof) && ($line !~ /^\[\/Section\]$/)) {
231 if ($line !~ /^(#.*|\s*)$/) {
232 if ($line =~ /^(.+)\s+(.+)$/) {
233 write_cpp_typedef_line(*CPPOUTPUT, $1, $2);
234 # Java doesn't support typedefs, ignore it.
235 #write_java_typedef_line(*JAVAOUTPUT, $1, $2);
236 # c# doesn't support typedefs either (AFAIK)
237 } else {
238 die "Malformed content section typedef line\n";
241 $line = <INFO>;
245 sub read_enum_content {
247 local (*INFO) = $_[0];
248 local (*CPPOUTPUT) = $_[1];
249 local (*JAVAOUTPUT) = $_[2];
250 local (*CDASHFILE) = $_[3];
252 my $line = <INFO>;
253 my $dataname = "";
254 if ($line =~ /^Name\s+(.+)$/) {
255 $dataname = $1;
256 print "\tDataname: " . $dataname . "\n";
257 } else {
258 die "Content section has a non-named data stream\n";
261 $line = <INFO>;
262 my $datatype = "";
263 if ($line =~ /^DataType\s+(.+)$/) {
264 $datatype = $1;
265 print "\tDataType: " . $datatype . "\n";
266 } else {
267 die "Content section has a enum stream with no data type\n";
270 my $first = "yes";
271 $line = <INFO>;
272 while (!(eof) && ($line !~ /^\[\/Section\]$/)) {
273 if ($line !~ /^(#.*|\s*)$/) {
274 if ($line =~ /^(.+)\s+(.+)$/) {
275 my $firstoperand = $1;
276 my $secondoperand = $2;
278 if ($first) {
279 write_cpp_enum_start(*CPPOUTPUT, $dataname);
280 write_cdash_enum_start(*CDASHFILE, $dataname);
283 write_cpp_enum_line(*CPPOUTPUT, $firstoperand, $secondoperand, $first);
284 write_java_define_line(*JAVAOUTPUT, $firstoperand, $secondoperand, $datatype);
285 write_cdash_enum_line(*CDASHFILE, $firstoperand, $secondoperand, $first);
287 if ($first) {
288 $first = "";
290 } else {
291 die "Malformed content section enum line\n";
294 $line = <INFO>;
297 write_cpp_enum_end(*CPPOUTPUT);
298 write_cdash_enum_end(*CDASHFILE);
302 # Takes a file handle, and the comment start/end character for that language
303 sub write_license_header {
305 my $folder = $_[0];
306 local (*OUTPUT) = $_[1];
308 open(LICENSE, $folder . "abstracts/License.abstract") or die "Cannot open license file";
310 my $line = <LICENSE>;
311 while (!(eof)) {
312 printf OUTPUT $_[2] . $line . $_[3];
313 $line = <LICENSE>;
316 print OUTPUT "\n";
318 print OUTPUT $_[2] . "Purpose:" . $_[3] . "\n" . $_[2] . $_[4] . $_[3] . "\n\n";
320 close(LICENSE);
323 ################ C# Specific Subroutines #####################
325 sub write_cdash_top_guard {
326 local (*OUTPUT) = $_[0];
327 print OUTPUT "namespace amule.net\n{\n";
330 sub write_cdash_bottom_guard {
331 local (*OUTPUT) = $_[0];
332 print OUTPUT "}\n";
335 sub write_cdash_enum_start {
337 local (*OUTPUT) = $_[0];
339 print OUTPUT "public enum " . $_[1] . " {\n";
342 sub write_cdash_enum_end {
344 local (*OUTPUT) = $_[0];
346 print OUTPUT "\n};\n"
350 sub write_cdash_enum_line {
351 local (*OUTPUT) = $_[0];
353 if ($_[3] !~ "yes") {
354 print OUTPUT ",\n"
357 # looks like c# can't handle such values as enums
358 if ( not (POSIX::strtod($_[2]) & 0x8000000) ) {
359 print OUTPUT "\t" . $_[1] . " = " . $_[2];
363 sub write_cdash_define_line {
364 local (*OUTPUT) = $_[0];
366 die "ERROR: c# have no 'define' directive $_[1] $_[2]"
369 ################ CPP Specific Subroutines #####################
371 sub write_cpp_top_guard {
373 local (*OUTPUT) = $_[0];
375 my $guardname = uc($_[1]);
377 print OUTPUT "#ifndef __" . $guardname . "_H__\n";
378 print OUTPUT "#define __" . $guardname . "_H__\n\n";
381 sub write_cpp_bottom_guard {
383 local (*OUTPUT) = $_[0];
385 my $guardname = uc($_[1]);
387 print OUTPUT "#endif // __" . $guardname . "_H__\n";
391 sub write_cpp_enum_start {
393 local (*OUTPUT) = $_[0];
395 print OUTPUT "enum " . $_[1] . " {\n";
398 sub write_cpp_enum_end {
400 local (*OUTPUT) = $_[0];
402 print OUTPUT "\n};\n"
406 sub write_cpp_enum_line {
408 local (*OUTPUT) = $_[0];
410 if ($_[3] !~ "yes") {
411 print OUTPUT ",\n"
414 print OUTPUT "\t" . $_[1] . " = " . $_[2];
417 sub write_cpp_define_line {
419 local (*OUTPUT) = $_[0];
421 print OUTPUT "#define " . $_[1] . " " . $_[2] . "\n";
425 sub write_cpp_typedef_line {
427 local (*OUTPUT) = $_[0];
429 my $translated_type;
431 my $preamble = "";
433 my $datatype = $_[2];
435 if ($datatype) {
436 if ($datatype =~ /^u?int(8|16|32|64)$/) {
437 $translated_type = $datatype . "_t";
438 } elsif ($datatype eq "string") {
439 $translated_type = "std::string"
440 } else {
441 $preamble = "// ";
442 $translated_type = $datatype;
444 } else {
445 die "No data type on abstract";
448 print OUTPUT $preamble . "typedef " . $translated_type . " " . $_[1] . ";\n";
452 ################ JAVA Specific Subroutines #####################
455 sub write_java_define_line {
457 local (*OUTPUT) = $_[0];
459 my $datatype = "int";
460 my $first = $_[1];
461 my $second = $_[2];
463 if ($_[3]) {
464 if ($_[3] =~ /int8/) { $datatype = "byte"; }
465 elsif ($_[3] =~ /(uint8|int16)/) { $datatype = "short"; }
466 elsif ($_[3] =~ /(uint16|int32)/) { $datatype = "int"; }
467 elsif ($_[3] =~ /(uint32|int64)/) { $datatype = "long"; }
468 else { die "Unknown data type on abstract: " . $_[3]; }
469 } else {
470 if ($second =~ /^\".*\"$/) {
471 $datatype = "String";
475 print OUTPUT "public final static " . $datatype . " " . $first . " = " . $second . ";\n";
478 sub write_java_typedef_line {
480 die "Typedef not supported on java";