Upstream tarball 9882
[amule.git] / src / libs / ec / file_generator.pl
blobefdf02b69f55533c1f54e1b3a861679ad72f9980
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) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
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 @debugOut;
46 my $numArgs = $#ARGV;
47 print "Parsing $numArgs files\n";
49 foreach my $argnum (1 .. $#ARGV) {
50 generate_files($folder, $ARGV[$argnum]);
54 sub generate_files {
56 my $folder = $_[0];
57 my $input_file = $_[1];
58 @debugOut = ();
60 open(INFO, $folder . $input_file) or die "Cannot open input file " . $input_file . " for reading: $!"; # Open the file
62 my $line="no";
63 while ($line !~ /^\[Section Definition\]$/) {
64 $line = <INFO>;
65 if (!($line)) {
66 die $input_file . " seems not to have a Section Definition\n";
68 chop $line;
71 #We're at the start of the Section Definition.
72 # Read the Definition Section.
74 my $filename = "";
76 my $nameline = <INFO>;
77 if ($nameline =~ /^FileName\s+(.+)$/) {
78 $filename = $1;
79 } else {
80 die "Section Definition must start with FileName item.";
83 my $filecontent = "";
85 my $contentline = <INFO>;
86 if ($contentline =~ /^FileContent\s+(.+)$/) {
87 $filecontent = $1;
88 } else {
89 die "Section Definition must have a FileContent after the FileName item.";
92 #Skip the rest of the section, allow for extensions later.
94 $line = "";
95 while ($line && ($line !~ /^\[\/Section\]$/)) {
96 $line = <INFO>;
100 print "FileName: " . $filename . "\n";
101 print "FileContent: " . $filecontent . "\n";
103 #Open language output files
104 open(CPPFILE," > " . $folder . "cpp/$filename" . ".h");
105 #Open language output files
106 open(JAVAFILE," > " . $folder . "java/$filename" . ".java");
108 open(CDASHFILE, ">${folder}/c#/${filename}.cs");
110 # Print license on top.
111 write_license_header($folder, *CPPFILE, "// ", "", $filecontent);
112 write_license_header($folder, *CDASHFILE, "// ", "", $filecontent);
113 write_license_header($folder, *JAVAFILE, "// ", "", $filecontent);
114 #Example for a language that needs start/end:
115 #write_license_header($folder, *CFILE, "/* ", " */", $filecontent);
117 #Add top guards for each language
118 write_cpp_top_guard(*CPPFILE, $filename);
119 write_cdash_top_guard(*CDASHFILE);
120 # JAVA doesn't need guards, but needs file type declaration
121 print JAVAFILE "public interface " . $filename . " {\n\n";
122 ##Add other language guards
125 read_content(*INFO, *CPPFILE, *JAVAFILE, *CDASHFILE);
128 #Add bottom guards for each language
129 write_cpp_bottom_guard(*CPPFILE, $filename);
130 write_cdash_bottom_guard(*CDASHFILE);
131 # JAVA doesn't need guards, but we have to close the interface
132 print JAVAFILE "}\n";
133 ##Add other language guards
136 # Close language files
137 close(CPPFILE);
138 close(JAVAFILE);
140 print "All info parsed\n";
142 close(INFO);
146 ################ Generic Subroutines #####################
148 sub read_content {
149 local (*INFO) = $_[0];
150 local (*CPPFILE) = $_[1];
151 local (*JAVAFILE) = $_[2];
152 local (*CDASHFILE) = $_[3];
154 my $stop = "";
156 while (!($stop)) {
157 my $line="no";
159 #Skip till Content
160 while (!(eof(INFO)) && $line !~ /^\[Section Content\]$/) {
161 $line = <INFO>;
162 chop $line;
165 if ($line =~ /^\[Section Content\]$/) {
166 print "Reading content section...\n";
167 read_content_section(*INFO, *CPPFILE, *JAVAFILE, *CDASHFILE);
168 print CPPFILE "\n";
169 print JAVAFILE "\n";
170 } else {
171 print "No more content sections\n";
172 $stop = "yes";
177 sub read_content_section {
179 local (*INFO) = $_[0];
180 local (*CPPOUTPUT) = $_[1];
181 local (*JAVAOUTPUT) = $_[2];
182 local (*CDASHFILE) = $_[3];
184 my $line = <INFO>;
185 my $datatype = "";
186 if ($line =~ /^Type\s+(.+)$/) {
187 $datatype = $1;
188 print "\tDatatype: " . $datatype . "\n";
189 } else {
190 die "Content section has a non-typed data stream\n";
193 if ($datatype eq "Define") {
194 read_define_content(*INFO, *CPPOUTPUT, *JAVAOUTPUT, *CDASHFILE);
195 } elsif ($datatype eq "Enum") {
196 read_enum_content(*INFO, *CPPOUTPUT, *JAVAOUTPUT, *CDASHFILE);
197 } elsif ($datatype eq "TypeDef") {
198 read_typedef_content(*INFO, *CPPOUTPUT, *JAVAOUTPUT, *CDASHFILE);
199 } else {
200 die "Unknown type on content section\n";
205 sub read_define_content {
206 local (*INFO) = $_[0];
207 local (*CPPOUTPUT) = $_[1];
208 local (*JAVAOUTPUT) = $_[2];
209 local (*CDASHFILE) = $_[3];
211 my $line = <INFO>;
212 while (!(eof) && ($line !~ /^\[\/Section\]$/)) {
213 if ($line !~ /^(#.*|\s*)$/) {
214 if ($line =~ /^(.+)\s+(.+)$/) {
215 write_cpp_define_line(*CPPOUTPUT, $1, $2);
216 write_java_define_line(*JAVAOUTPUT, $1, $2);
217 write_cdash_define_line(*CDASHFILE, $1, $2);
218 } else {
219 die "Malformed content section define line\n";
222 $line = <INFO>;
226 sub read_typedef_content {
228 local (*INFO) = $_[0];
229 local (*CPPOUTPUT) = $_[1];
230 local (*JAVAOUTPUT) = $_[2];
232 my $line = <INFO>;
233 while (!(eof) && ($line !~ /^\[\/Section\]$/)) {
234 if ($line !~ /^(#.*|\s*)$/) {
235 if ($line =~ /^(.+)\s+(.+)$/) {
236 write_cpp_typedef_line(*CPPOUTPUT, $1, $2);
237 # Java doesn't support typedefs, ignore it.
238 #write_java_typedef_line(*JAVAOUTPUT, $1, $2);
239 # c# doesn't support typedefs either (AFAIK)
240 } else {
241 die "Malformed content section typedef line\n";
244 $line = <INFO>;
248 sub read_enum_content {
250 local (*INFO) = $_[0];
251 local (*CPPOUTPUT) = $_[1];
252 local (*JAVAOUTPUT) = $_[2];
253 local (*CDASHFILE) = $_[3];
255 my $line = <INFO>;
256 my $dataname = "";
257 if ($line =~ /^Name\s+(.+)$/) {
258 $dataname = $1;
259 print "\tDataname: " . $dataname . "\n";
260 } else {
261 die "Content section has a non-named data stream\n";
264 $line = <INFO>;
265 my $datatype = "";
266 if ($line =~ /^DataType\s+(.+)$/) {
267 $datatype = $1;
268 print "\tDataType: " . $datatype . "\n";
269 } else {
270 die "Content section has a enum stream with no data type\n";
273 my $first = "yes";
274 $line = <INFO>;
275 while (!(eof) && ($line !~ /^\[\/Section\]$/)) {
276 if ($line !~ /^(#.*|\s*)$/) {
277 if ($line =~ /^(.+)\s+(.+)$/) {
278 my $firstoperand = $1;
279 my $secondoperand = $2;
281 if ($first) {
282 write_cpp_enum_start(*CPPOUTPUT, $dataname, $datatype);
283 write_cdash_enum_start(*CDASHFILE, $dataname);
286 write_cpp_enum_line(*CPPOUTPUT, $firstoperand, $secondoperand, $first);
287 write_java_define_line(*JAVAOUTPUT, $firstoperand, $secondoperand, $datatype);
288 write_cdash_enum_line(*CDASHFILE, $firstoperand, $secondoperand, $first);
290 if ($first) {
291 $first = "";
293 } else {
294 die "Malformed content section enum line\n";
297 $line = <INFO>;
300 write_cpp_enum_end(*CPPOUTPUT);
301 write_cdash_enum_end(*CDASHFILE);
305 # Takes a file handle, and the comment start/end character for that language
306 sub write_license_header {
308 my $folder = $_[0];
309 local (*OUTPUT) = $_[1];
311 open(LICENSE, $folder . "abstracts/License.abstract") or die "Cannot open license file";
313 my $line = <LICENSE>;
314 while (!(eof)) {
315 printf OUTPUT $_[2] . $line . $_[3];
316 $line = <LICENSE>;
319 print OUTPUT "\n";
321 print OUTPUT $_[2] . "Purpose:" . $_[3] . "\n" . $_[2] . $_[4] . $_[3] . "\n\n";
323 close(LICENSE);
326 ################ C# Specific Subroutines #####################
328 sub write_cdash_top_guard {
329 local (*OUTPUT) = $_[0];
330 print OUTPUT "namespace amule.net\n{\n";
333 sub write_cdash_bottom_guard {
334 local (*OUTPUT) = $_[0];
335 print OUTPUT "}\n";
338 sub write_cdash_enum_start {
340 local (*OUTPUT) = $_[0];
342 print OUTPUT "public enum " . $_[1] . " {\n";
345 sub write_cdash_enum_end {
347 local (*OUTPUT) = $_[0];
349 print OUTPUT "\n};\n"
353 sub write_cdash_enum_line {
354 local (*OUTPUT) = $_[0];
356 if ($_[3] !~ "yes") {
357 print OUTPUT ",\n"
360 # looks like c# can't handle such values as enums
361 if ( not (POSIX::strtod($_[2]) & 0x8000000) ) {
362 print OUTPUT "\t" . $_[1] . " = " . $_[2];
366 sub write_cdash_define_line {
367 local (*OUTPUT) = $_[0];
369 die "ERROR: c# have no 'define' directive $_[1] $_[2]"
372 ################ CPP Specific Subroutines #####################
374 sub write_cpp_top_guard {
376 local (*OUTPUT) = $_[0];
378 my $guardname = uc($_[1]);
380 print OUTPUT "#ifndef __" . $guardname . "_H__\n";
381 print OUTPUT "#define __" . $guardname . "_H__\n\n";
384 sub write_cpp_bottom_guard {
386 local (*OUTPUT) = $_[0];
388 my $guardname = uc($_[1]);
390 print OUTPUT "#ifdef DEBUG_EC_IMPLEMENTATION\n\n" . join("\n", @debugOut) . "\n#endif\t// DEBUG_EC_IMPLEMENTATION\n\n";
392 print OUTPUT "#endif // __" . $guardname . "_H__\n";
395 sub write_cpp_enum_start {
397 local (*OUTPUT) = $_[0];
399 print OUTPUT "enum " . $_[1] . " {\n";
401 push @debugOut, "wxString GetDebugName$_[1]($_[2] arg)\n{\n\tswitch (arg) {";
404 sub write_cpp_enum_end {
406 local (*OUTPUT) = $_[0];
408 print OUTPUT "\n};\n";
410 push @debugOut, "\t\tdefault: return CFormat(wxT(\"unknown %d 0x%x\")) % arg % arg;\n\t}\n}\n";
414 sub write_cpp_enum_line {
416 local (*OUTPUT) = $_[0];
418 if ($_[3] !~ "yes") {
419 print OUTPUT ",\n"
422 print OUTPUT "\t" . $_[1] . " = " . $_[2];
424 my $arg = $_[1];
425 $arg =~ s/\s//g; # remove whitespace
426 push @debugOut, "\t\tcase $_[2]: return wxT(\"$arg\");";
430 sub write_cpp_define_line {
432 local (*OUTPUT) = $_[0];
434 print OUTPUT "#define " . $_[1] . " " . $_[2] . "\n";
438 sub write_cpp_typedef_line {
440 local (*OUTPUT) = $_[0];
442 my $translated_type;
444 my $preamble = "";
446 my $datatype = $_[2];
448 if ($datatype) {
449 if ($datatype =~ /^u?int(8|16|32|64)$/) {
450 $translated_type = $datatype . "_t";
451 } elsif ($datatype eq "string") {
452 $translated_type = "std::string"
453 } else {
454 $preamble = "// ";
455 $translated_type = $datatype;
457 } else {
458 die "No data type on abstract";
461 print OUTPUT $preamble . "typedef " . $translated_type . " " . $_[1] . ";\n";
465 ################ JAVA Specific Subroutines #####################
468 sub write_java_define_line {
470 local (*OUTPUT) = $_[0];
472 my $datatype = "int";
473 my $first = $_[1];
474 my $second = $_[2];
476 if ($_[3]) {
477 if ($_[3] =~ /int8/) { $datatype = "byte"; }
478 elsif ($_[3] =~ /(uint8|int16)/) { $datatype = "short"; }
479 elsif ($_[3] =~ /(uint16|int32)/) { $datatype = "int"; }
480 elsif ($_[3] =~ /(uint32|int64)/) { $datatype = "long"; }
481 else { die "Unknown data type on abstract: " . $_[3]; }
482 } else {
483 if ($second =~ /^\".*\"$/) {
484 $datatype = "String";
488 print OUTPUT "public final static " . $datatype . " " . $first . " = " . $second . ";\n";
491 sub write_java_typedef_line {
493 die "Typedef not supported on java";