A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 258 lines 8.3 kB view raw
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}