A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1#!/usr/bin/env perl
2############################################################################
3# __________ __ ___.
4# Open \______ \ ____ ____ | | _\_ |__ _______ ___
5# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8# \/ \/ \/ \/ \/
9# $Id$
10#
11# Copyright (C) 2019 by William Wilgus
12#
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.
15#
16# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17# KIND, either express or implied.
18#
19############################################################################
20
21#rockbox to lua define generator, add names of constants to the array to include
22
23if ($#ARGV + 1 != 1) {
24 warn "no definition type defined";
25 exit;
26}
27
28my $def_type = $ARGV[0];
29#warn "$def_type\n";
30my $lua_table;
31my @rockbox_defines;
32
33if ($def_type eq "rb_defines") {
34 $lua_table = "rb";
35 @rockbox_defines = (
36 '^HZ$',
37 '^LCD_(DEPTH|HEIGHT|WIDTH)$',
38 '^MODEL_NAME$',
39 '^SCREEN_MAIN$',
40 '^LCD_DEFAULT_(FG|BG)$',
41 '^LCD_REMOTE_(DEPTH|HEIGHT|WIDTH)$',
42 '^LCD_.+(BRIGHT|DARK)COLOR',
43 '^SCREEN_REMOTE$',
44 '^FONT_SYSFIXED$',
45 '^FONT_UI$',
46 '^PLAYBACK_EVENT_.*',
47 '^PLAYLIST_(INSERT|PREPEND|REPLACE)',
48 '^TOUCHSCREEN_(POINT|BUTTON)$',
49 '^SYS_CHARGER_(DIS|)CONNECTED$',
50 '^SYS_(TIMEOUT|POWEROFF|BATTERY_UPDATE)$',
51 '^SYS_USB_(DIS|)CONNECTED$',
52 '^HOME_DIR$',
53 '^PLUGIN(_OK|_USB_CONNECTED|_POWEROFF|_GOTO_WPS|_GOTO_PLUGIN)$',
54 '^PLUGIN_DIR$',
55 '^PLUGIN(_APPS_|_GAMES_|_)DATA_DIR$',
56 '^ROCKBOX_DIR$',
57 '^STYLE_(NONE|DEFAULT|INVERT|COLORBAR|GRADIENT|COLORED)',
58 '^CORE_KEYMAP_FILE$',
59 'CONTEXT_(STOPSEARCHING|REMOTE|CUSTOM|CUSTOM2|PLUGIN|REMAPPED)$',
60 '^VIEWERS_DATA_DIR$');
61}
62elsif ($def_type eq "sound_defines") {
63 $lua_table = "rb.sound_settings";
64 @rockbox_defines = (
65 '^(?!.*LAST_SETTING)SOUND_');
66}
67
68my @captured_defines;
69my @names_seen;
70my @all_defines;
71
72############# precompile regex for speed #############
73my $def_regex = qr/#define\s+([^\s\r\n]+)\s+([^\r\n]+)/;
74my $quot_regex = qr/.*([\"\']).*/;
75my $num_regex = qr/.*([\+\-\*\\|&\d]).*/;
76my $configh_regex = qr/^\s*#define\s*__CONFIG_H__\s*$/;
77my $config_h = "?";
78my $exclude_regex = qr/^#define\s*_?POSIX.*/;
79my $exclude_enum_regex = qr/^#define\s*(_SC_|_PC_|_CS_).*/;
80print <<EOF
81#include <stdio.h>
82#include <stdbool.h>
83
84#define stringify(s) #s
85
86/* auto generated defines */
87
88
89EOF
90;
91
92while(my $line = <STDIN>)
93{
94 if($config_h eq "?" && $line =~ $configh_regex) { $config_h = $line; }
95 next if($config_h eq "?"); #don't capture till we get to the config file
96 next if($line =~ $exclude_regex);
97
98 if($line =~ $def_regex) #does it begin with #define?
99 {
100 push(@all_defines, $line); #save all defines for possible ambiguous macros
101 $name = $1;
102 next if $name =~ /^(ATTRIBUTE_|print|__).*/; #don't add reserved
103 $value = $2;
104
105 if(grep($name =~ $_, @rockbox_defines))
106 {
107 push(@names_seen, $name);
108 push(@captured_defines, {'name' => $name, 'value' => $value});
109 print $line
110 }
111 else
112 {
113 $name =~ s{(\(.*\))}{}gx; #remove (...) on function type macros
114 #ifndef guard so we don't clash with the host
115 printf "#ifndef %s\n%s#endif\n\n", $name, $line;
116 }
117 }
118 elsif($line =~ /^(?!.*;)enum.*{/) #enum {
119 {
120 next if($line =~ /enum\s*__.*/); #don't add reserved
121 print $line;
122 next if($line =~ /.*};.*/);
123 do_enum($line)
124 }
125 elsif($line =~ /^(?!.*[;\(\)])enum.*/) #enum
126 {
127 next if($line =~ /enum\s*__.*/); #don't add reserved
128 #need to be careful might be a function returning enum
129 my $lastline = $line;
130 next if($line =~ /.*};.*/);
131 ($line = <STDIN>);
132 if($line =~ /.*{.*/)
133 {
134 print $lastline;
135 print $line;
136 }
137 else { next; }
138 do_enum($line)
139 }
140 elsif($line =~ /^enum.*{[^;]+};.*/) #enum {
141 {
142 next if($line =~ /enum\s*__.*/); #don't add reserved
143 next if(do_enum($line));
144
145 }
146}
147#warn "total defines: ".scalar @all_defines;
148#warn "captured defines: ".scalar @captured_defines;
149#Sort the functions
150my @sorted_defines = sort { @$a{'name'} cmp @$b{'name'} } @captured_defines;
151
152printf "int main(void)\n{\n";
153printf "\tprintf(\"--[[Autogenerated rockbox constants]]\\n\\n\");\n\n";
154printf "\tprintf(\"%s = %s or {}\\n\");\n", $lua_table, $lua_table;
155# Print the C array
156foreach my $define (@sorted_defines)
157{
158 if(@$define{'value'} =~ /^0[xX][0-9a-fA-F]+$/) #hex number
159 {
160 printf "\tprintf(\"%s[\\\"%%s\\\"] = 0x%%x\\n\", stringify(%s), %s);\n", $lua_table, @$define{'name'}, @$define{'name'};
161 }
162 elsif(@$define{'value'} =~ /^[0-9]+$/) #number
163 {
164 printf "\tprintf(\"%s[\\\"%%s\\\"] = %%ld\\n\", stringify(%s), (long) %s);\n", $lua_table, @$define{'name'}, @$define{'name'};
165 }
166 else #might be a string but we don't know since the macro isn't expanded far enough
167 {
168 my $max_depth = 10;
169 my $var = @$define{'value'};
170 while($max_depth > 0) #follow the chain of #defines until we can see what type
171 {
172 $max_depth--;
173 $var = "\\\s*#define\\s+$var\\s+.*";
174 #warn $var;
175 if(my ($x) = grep($_ =~ /($var)/, @all_defines)) #check all the defines
176 {
177 #warn $x;
178 if($x =~ $def_regex)
179 {
180 $var = $2;
181 #warn $var;
182 last if ($var =~ $quot_regex);
183 last if ($var =~ $num_regex);
184 next
185 }
186 #warn "end ".$var;
187 last
188 }
189 else
190 {
191 $var = @$define{'value'};
192 last
193 }
194 }
195 if ($var =~$quot_regex) #has a quote it is a string
196 {
197 #guard with empty literals "" so gcc throws an error if it isn't a string
198 printf "\tprintf(\"%s[\\\"%%s\\\"] = \\\"%%s\\\"\\n\", stringify(%s), \"\" %s \"\");\n", $lua_table, @$define{'name'}, @$define{'name'};
199 }
200 elsif ($var =~$num_regex) #it must be a number
201 {
202 printf "\tprintf(\"%s[\\\"%%s\\\"] = %%ld\\n\", stringify(%s), (long) %s);\n", $lua_table, @$define{'name'}, @$define{'name'};
203 }
204 else { warn "Skipping ".@$define{'name'}." indeterminate macro type\n"; }
205 }
206}
207
208print <<EOF
209 return 0;
210}
211
212EOF
213;
214
215sub do_enum {
216 my ($line) = @_;
217 if($line =~ /.*enum.*{(.*)};.*/) #single line enums
218 {
219 print $line;
220 $value = "0"; #enums are always integers
221 my $enum = $1;
222 $enum =~ s/\s+//g;;
223 my @values = split(',', $enum);
224
225 foreach my $name(@values) {
226 if(grep($name =~ $_, @rockbox_defines))
227 {
228 push(@names_seen, $name);
229 push(@captured_defines, {'name' => $name, 'value' => $value});
230 }
231 }
232 return 1;
233 }
234
235 while($line = <STDIN>)
236 {
237 next if($line =~ $exclude_enum_regex);
238 if($line =~ /.*};.*/)
239 {
240 print $line;
241 last
242 }
243 elsif($line =~ /([^\s,\t]+)\s*=?.*,?/)
244 {
245 $name = $1;
246 #printf "%s WHATTT?", $name;
247 $value = "0"; #enums are always integers
248 }
249 print $line;
250 if(grep($name =~ $_, @rockbox_defines))
251 {
252 push(@names_seen, $name);
253 push(@captured_defines, {'name' => $name, 'value' => $value});
254 }
255
256 }
257 return 0;
258}