710ee4a71abe89ea418602768d74d1437242eedc
[nativez] / src / notzed.nativez / jni / nativez-gen
1 #!/usr/bin/perl
2
3 # usage [ options ]* def-file.def
4
5 #  -b basedir   Base directory for any 'header' sections.  It is added to the include path.
6 #  --func-name  Function table variable name.  Default is `fn'.
7 #  --java-name  Java table variable name.  Default is 'java'.
8 #  -J           Create #defines to map java names to the variable name.
9 #  --java-long  Create long java names for object types.  Sort of like mangled jni names.
10
11 # All other options and arguments are passed to cproto.
12
13 $args = "$0 ".join " ", @ARGV;
14 $java_name = "java";
15 $func_name = "fn";
16 $doJ = 0;
17 $doLong = 0;
18 $cprotoArgs = "";
19
20 while ($#ARGV > 0) {
21     my $cmd = shift;
22     if ($cmd eq "-b") {
23         $basedir = shift;
24         $cprotoArgs .= " -I '${basedir}'";
25     } elsif ($cmd eq "--func-name") {
26         $func_name = shift;
27     } elsif ($cmd eq "--java-name") {
28         $java_name = shift;
29     } elsif ($cmd eq "-J") {
30         $doJ = 1;
31     } elsif ($cmd eq "--java-long") {
32         $doLong = 1;
33     } else {
34         $cprotoArgs .= " '$cmd'";
35     }
36 }
37 $def = shift;
38
39 $header = "";
40 $librart = "";
41 @functions = ();
42 @headers = ();
43 %proto = ();
44 $last_library = "";
45 $mode = "";
46
47 open (IN,"<$def") || die ("opening $def");
48
49 while (<IN>) {
50     chop;
51     s/#.*$//;
52     if (m/^header (.*) (.*) \{/) {
53         $library = $1;
54         $header = $2;
55         push @headers, $header;
56
57         print STDERR "cproto -q -x ${cprotoArgs} $basedir/$header\n";
58         %proto = ();
59         open (PROTO, "cproto -q -x ${cprotoArgs} $basedir/$header|") || die("cproto failed");
60         
61         while (<PROTO>) {
62             chop;
63             $cproto = $_;
64             if (m/([a-zA-Z0-9_]*)\(/) {
65                 $func = $1;
66                 $proto{$func} = $cproto;
67             }
68         }
69         close PROTO;
70
71         if ($library ne $last_library) {
72             push @functions, "#$library";
73             $last_library = $library;
74         }
75         $mode = "proto";
76     } elsif (m/^java (.*) (.*) \{/) {
77         $name = $1;
78         $class = $2;
79         $mode = "java";
80         push @classes,"#$name:$class";
81     } elsif (m/^}$/) {
82         $mode = "";
83     } elsif ($mode eq "proto") {
84         if (m/\s*([a-zA-Z0-9_]+)/) {
85             my $func= $1;
86             my $cproto = $proto{$func};
87             
88             die ("No function $func in $header") if !defined($cproto);
89             
90             push @functions, $cproto;
91         }
92     } elsif ($mode eq "java") {
93         # maps to strict "[static|],name,(arguments)"
94         if (m/(static)? *([\w<>]*) *, *([\[\w<>\(\)\/;]*)/) {
95             push @classes,"$1,$2,$3";
96         }
97     }
98 }
99 close IN;
100
101 print "/* This file was autogenerated by: */\n";
102 print "/* $args */\n";
103
104 if ($#headers >= 0) {
105     # Handle C prototype mappings
106     foreach $h (@headers) {
107         print "#include <$h>\n";
108     }
109
110     print "static struct functable {\n";
111     foreach $func (@functions) {
112         if ($func =~ m/^\#(.+)/) {
113             print "\t/* lib$1 */\n";
114         } else {
115             $dfunc = $func;
116             $dfunc =~ s/([a-zA-Z0-9_]*)(\(.*;)/(*\1)\2/;
117             print "\t$dfunc\n";
118         }
119     }
120     print "} ${func_name};\n";
121     print "static const char *${func_name}_names =\n";
122     foreach $func (@functions) {
123         if ($func =~ m/^(\#.+)/) {
124             print "\t\"$func\\0\"\n";
125         } else {
126             $func =~ m/([a-zA-Z0-9_]*)\(/;
127             print "\t\"$1\\0\"\n";
128         }
129     }
130     print "\t;\n";
131 }
132
133 if ($#classes >= 0) {
134     # Handle java defines
135     $name = "";
136     $class = "";
137     print "static struct {\n";
138     foreach $func (@classes) {
139         if ($func =~ m/^#(.+):(.+)/) {
140             $name = $1;
141             $class = $2;
142             print "\t// $class\n";
143             print "\tjclass $name"."_classid;\n";
144             printf "#define $name"."_classid ${java_name}.$name"."_classid\n" if $doJ;
145         } elsif ($func =~ m/(.*),(.+),\((.*)\).*/) {
146             my $method = $2;
147             my $args = $3;
148
149             if ($doLong) {
150                 while ($args =~ m/(.*)L([^;]*);(.*)/) {
151                     my $a = $1;
152                     my $b = $2;
153                     my $c = $3;
154
155                     $b =~ s,/,_,g;
156                     $args = $a."_".$b."_".$c;
157                 }               
158             } else {
159                 $args =~ s/L[^;]*;/l/g;
160                 $args =~ tr/A-Z/a-z/;
161             }
162             $args =~ s/\[/_/g;
163
164             $method =~ s/<init>/new/;
165             
166             print "\tjmethodID $name"."_$method"."_$args;\n";
167             print "#define $name"."_$method"."_$args ${java_name}.$name"."_$method"."_$args\n" if $doJ;
168         } elsif ($func =~ m/(.*),(.+),(.+)/) {
169             my $field = $2;
170             my $type = $3;
171
172             print "\tjfieldID $name"."_$field;\n";
173             print "#define $name"."_$field ${java_name}.$name"."_$field\n" if $doJ;
174         } else {
175             die("can't parse java signature $func");
176         }
177     }
178     print "} ${java_name};\n";
179     print "static const char *${java_name}_names =\n";
180     foreach $func (@classes) {
181         if ($func =~ m/^#(.+):(.+)/) {
182             $name = $1;
183             $class = $2;
184
185             print "\t\"#$class\\0\"\n";
186         } elsif ($func =~ m/static,(.*),(.*\(.*\).*)/) {
187             print "\t\":$1\\0$2\\0\"\n";
188         } elsif ($func =~ m/,(.*),(.*\(.*\).*)/) {
189             print "\t\".$1\\0$2\\0\"\n";
190         } elsif ($func =~ m/static,(.*),(.*)/) {
191             print "\t\";$1\\0$2\\0\"\n";
192         } elsif ($func =~ m/,(.*),(.*)/) {
193             print "\t\",$1\\0$2\\0\"\n";
194         }
195     }
196     print "\t;\n";    
197 }