Prepare new maemo release
[maemo-rb.git] / apps / plugins / lua / rocklib_aux.pl
blob9103fccbda9c0eb69231f60f05d3612a1aae2d9e
1 #!/usr/bin/env perl
2 ############################################################################
3 # __________ __ ___.
4 # Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 # \/ \/ \/ \/ \/
9 # $Id$
11 # Copyright (C) 2009 by Maurus Cuelenaere
13 # All files in this archive are subject to the GNU General Public License.
14 # See the file COPYING in the source tree root for full license agreement.
16 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 # KIND, either express or implied.
19 ############################################################################
22 # The purpose of this script is to automatically generate Lua wrappers for
23 # (easily) portable C functions used in the Rockbox plugin API.
24 # It doesn't contain support for enums, structs or pointers (apart from char*).
26 # The output will be written to <build_dir>/apps/plugins/lua/rocklib_aux.c
28 sub trim
30 my $text = $_[0];
31 $text =~ s/^\s+//;
32 $text =~ s/\s+$//;
33 return $text;
36 sub rand_string
38 my @chars=('a'..'z');
39 my $ret;
40 foreach (1..5)
42 $ret .= $chars[rand @chars];
44 return $ret;
48 my @functions;
49 my @ported_functions;
50 # These functions are excluded from automatically wrapping. This is useful if
51 # you want to manually port them to Lua. The format is a standard Perl regular
52 # expression.
53 my @forbidden_functions = ('^open$',
54 '^close$',
55 '^read$',
56 '^write$',
57 '^mkdir$',
58 '^rmdir$',
59 '^lseek$',
60 '^ftruncate$',
61 '^filesize$',
62 '^fdprintf$',
63 '^read_line$',
64 '^[a-z]+dir$',
65 '^__.+$',
66 '^.+_(un)?cached$',
67 '^audio_play$',
68 '^round_value_to_list32$');
70 my $rocklib = sprintf("%s/rocklib.c", $ARGV[0]);
71 open ROCKLIB, "<$rocklib" or die("Couldn't open $rocklib: $!");
72 while(<ROCKLIB>)
74 if(/^RB_WRAP\(([^)]+)\)/)
76 push(@ported_functions, $1);
79 close ROCKLIB;
81 # Parse plugin.h
82 my $start = 0;
83 while(<STDIN>)
85 if(/struct plugin_api \{/)
87 $start = 1;
89 elsif($start && /\};/)
91 $start = 0;
94 if($start == 1)
96 my $line = $_;
97 while($line !~ /;/)
99 $line .= <STDIN>;
102 $line =~ s/(\n|\r)//g;
104 if($line =~ /([a-zA-Z *_]+)?\s?\(\*([^)]+)?\)\(([^)]+)\).*?;/)
106 $return_type = $1;
107 $name = $2;
108 $arguments = $3;
110 $return_type = trim($return_type);
111 $arguments =~ s/\s{2,}/ /g;
113 if( !grep($_ eq $name, @ported_functions) &&
114 !grep($name =~ $_, @forbidden_functions))
116 push(@functions, {'name' => $name, 'return' => $return_type, 'arg' => $arguments});
122 my $svnrev = '$Revision$';
124 # Print the header
125 print <<EOF
126 /* Automatically generated from rocklib.c & plugin.h ($svnrev)
128 * See apps/plugins/lua/rocklib_aux.pl for the generator.
131 #define lrocklib_c
132 #define LUA_LIB
134 #define _ROCKCONF_H_ /* We don't need strcmp() etc. wrappers */
135 #include "lua.h"
136 #include "lauxlib.h"
137 #include "plugin.h"
142 my %in_types = ('void' => \&in_void,
143 'int' => \&in_int,
144 'unsigned' => \&in_int,
145 'unsignedint' => \&in_int,
146 'signed' => \&in_int,
147 'signedint' => \&in_int,
148 'short' => \&in_int,
149 'unsignedshort' => \&in_int,
150 'signedshort' => \&in_int,
151 'long' => \&in_int,
152 'unsignedlong' => \&in_int,
153 'signedlong' => \&in_int,
154 'char' => \&in_int,
155 'unsignedchar' => \&in_int,
156 'signedchar' => \&in_int,
157 'size_t' => \&in_int,
158 'ssize_t' => \&in_int,
159 'off_t' => \&in_int,
160 'char*' => \&in_string,
161 'signedchar*' => \&in_string,
162 'unsignedchar*' => \&in_string,
163 'bool' => \&in_bool,
164 '_Bool' => \&in_bool
165 ), %out_types = ('void' => \&out_void,
166 'int' => \&out_int,
167 'unsigned' => \&out_int,
168 'unsignedint' => \&out_int,
169 'signed' => \&out_int,
170 'signedint' => \&out_int,
171 'short' => \&out_int,
172 'unsignedshort' => \&out_int,
173 'signedshort' => \&out_int,
174 'long' => \&out_int,
175 'unsignedlong' => \&out_int,
176 'signedlong' => \&out_int,
177 'char' => \&out_int,
178 'unsignedchar' => \&out_int,
179 'signedchar' => \&out_int,
180 'size_t' => \&out_int,
181 'ssize_t' => \&out_int,
182 'off_t' => \&out_int,
183 'char*' => \&out_string,
184 'signedchar*' => \&out_string,
185 'unsignedchar*' => \&out_string,
186 'bool' => \&out_bool,
187 '_Bool' => \&out_bool
190 sub in_void
192 return "\t(void)L;\n";
195 sub in_int
197 my ($name, $type, $pos) = @_;
198 return sprintf("\t%s %s = (%s) luaL_checkint(L, %d);\n", $type, $name, $type, $pos);
201 sub in_string
203 my ($name, $type, $pos) = @_;
204 return sprintf("\t%s %s = (%s) luaL_checkstring(L, %d);\n", $type, $name, $type, $pos)
207 sub in_bool
209 my ($name, $type, $pos) = @_;
210 return sprintf("\tbool %s = luaL_checkboolean(L, %d);\n", $name, $pos)
213 sub out_void
215 my $name = $_[0];
216 return sprintf("\t%s;\n\treturn 0;\n", $name);
219 sub out_int
221 my ($name, $type) = @_;
222 return sprintf("\t%s result = %s;\n\tlua_pushinteger(L, result);\n\treturn 1;\n", $type, $name);
225 sub out_string
227 my ($name, $type) = @_;
228 return sprintf("\t%s result = %s;\n\tlua_pushstring(L, result);\n\treturn 1;\n", $type, $name);
231 sub out_bool
233 my ($name, $type) = @_;
234 return sprintf("\tbool result = %s;\n\tlua_pushboolean(L, result);\n\treturn 1;\n", $name);
237 # Print the functions
238 my @valid_functions;
239 foreach my $function (@functions)
241 my $valid = 1, @arguments = ();
242 # Check for supported arguments
243 foreach my $argument (split(/,/, @$function{'arg'}))
245 $argument = trim($argument);
246 if($argument !~ /\[.+\]/ && ($argument =~ /^(.+[\s*])([^[*\s]*)/
247 || $argument eq "void"))
249 my $literal_type, $type, $name;
250 if($argument eq "void")
252 $literal_type = "void", $type = "void", $name = "";
254 else
256 $literal_type = trim($1), $name = trim($2), $type = trim($1);
257 $type =~ s/(\s|const)//g;
259 if($name eq "")
261 $name = rand_string();
265 #printf "/* %s: %s|%s */\n", @$function{'name'}, $type, $name;
266 if(!defined $in_types{$type})
268 $valid = 0;
269 break;
272 push(@arguments, {'name' => $name,
273 'type' => $type,
274 'literal_type' => $literal_type
277 else
279 $valid = 0;
280 break;
284 # Check for supported return value
285 my $return = @$function{'return'};
286 $return =~ s/(\s|const)//g;
287 #printf "/* %s: %s [%d] */\n", @$function{'name'}, $return, $valid;
288 if(!defined $out_types{$return})
290 $valid = 0;
293 if($valid == 1)
295 # Print the header
296 printf "static int rock_%s(lua_State *L)\n".
297 "{\n",
298 @$function{'name'};
300 # Print the arguments
301 my $i = 1;
302 foreach my $argument (@arguments)
304 print $in_types{@$argument{'type'}}->(@$argument{'name'}, @$argument{'literal_type'}, $i++);
307 # Generate the arguments string
308 my $func_args = $arguments[0]{'name'};
309 for(my $i = 1; $i < $#arguments + 1; $i++)
311 $func_args .= ", ".$arguments[$i]{'name'};
314 # Print the function call
315 my $func = sprintf("rb->%s(%s)", @$function{'name'}, $func_args);
317 # Print the footer
318 print $out_types{$return}->($func, @$function{'return'});
319 print "}\n\n";
321 push(@valid_functions, $function);
325 # Print the C array
326 print "const luaL_Reg rocklib_aux[] =\n{\n";
327 foreach my $function (@valid_functions)
329 printf "\t{\"%s\", rock_%s},\n", @$function{'name'}, @$function{'name'};
331 print "\t{NULL, NULL}\n};\n\n";