rockbox/apps/plugins/lib/action_helper.pl

210 lines
6 KiB
Perl
Raw Normal View History

#!/usr/bin/env perl
############################################################################
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
# $action_helper$
#
# Copyright (C) 2021 William Wilgus
#
# All files in this archive are subject to the GNU General Public License.
# See the file COPYING in the source tree root for full license agreement.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
############################################################################
#expects -E source input on STDIN
use strict;
use warnings;
my @actions = ();
my @contexts = ();
my @action_offset = ();
my @context_offset = ();
my $action_ct = 0;
my $context_ct = 0;
my $len_max_action = 0;
my $len_max_context = 0;
my $len_min_action = -1;
my $len_min_context = -1;
while(my $line = <STDIN>)
{
chomp($line);
if($line =~ /^\s*(ACTION_[^\s]+)(\s*=.*)?,\s*$/)
{
$actions[$action_ct] = $1;
$action_ct++;
}
elsif($line =~ /^\s*(LAST_ACTION_PLACEHOLDER)(\s*=.*)?,\s*$/)
{ #special case don't save actual name
$actions[$action_ct] = "";
$action_ct++;
}
elsif($line =~ /^\s*(PLA_[^\s]+)(\s*=.*)?,\s*$/)
{
$actions[$action_ct] = $1;
$action_ct++;
}
elsif($line =~ /^\s*(CONTEXT_[^\s]+)(\s*=.*)?,\s*$/)
{
$contexts[$context_ct] = $1;
$context_ct++;
}
}
print <<EOF
/* Don't change this file! */
/* It is automatically generated of action.h */
#include "plugin.h"
#include "action_helper.h"
EOF
;
#dump actions
my $offset = 0;
print "static const char action_names[]= \n";
for(my $i = 0; $i < $action_ct; $i++){
my $act = $actions[$i];
$act =~ s/ACTION_USB_HID_/%s/ig; # strip the common part
$act =~ s/ACTION_/%s/ig; # strip the common part
my $actlen = length($act);
if ($actlen < $len_min_action or $len_min_action == -1){
$len_min_action = $actlen;
}
if ($actions[$i] ne $act){
printf "/*%s*/\"%s\\0\"\n", substr($actions[$i], 0, -($actlen - 2)), $act;
} else {
print "\"$act\\0\" \n";
}
my $slen = length($actions[$i]) + 1; #NULL terminator
if ($slen > $len_max_action) { $len_max_action = $slen; }
push(@action_offset, {'name' => $actions[$i], 'offset' => $offset});
$offset += length($act) + 1; # NULL terminator
}
printf "\"\";/* %d + \\0 */\n\n", $offset;
@actions = ();
#dump contexts
$offset = 0;
print "static const char context_names[]= \n";
for(my $i = 0; $i < $context_ct; $i++){
my $ctx = $contexts[$i];
$ctx =~ s/CONTEXT_/%s/ig; # strip the common part
my $ctxlen = length($ctx);
if ($ctxlen < 5){
$ctx = $contexts[$i];
$ctxlen = length($ctx);
}
if ($ctxlen < $len_min_context or $len_min_context == -1){
$len_min_context = $ctxlen;
}
if ($contexts[$i] ne $ctx){
printf "/*%s*/\"%s\\0\"\n", substr($contexts[$i], 0, -($ctxlen - 2)), $ctx;
} else {
print "\"$ctx\\0\" \n";
}
my $slen = length($contexts[$i]) + 1; # NULL terminator
if ($slen > $len_max_context) { $len_max_context = $slen; }
push(@context_offset, {'name' => $contexts[$i], 'offset' => $offset});
$offset += length($ctx) + 1; # NULL terminator
}
printf "\"\";/* %d + \\0 */\n\n", $offset;
@contexts = ();
printf "#define ACTION_CT %d\n", $action_ct;
print "static const uint16_t action_offsets[ACTION_CT] = {\n";
foreach my $define (@action_offset)
{
printf("%d, /*%s*/\n", @$define{'offset'}, @$define{'name'});
}
print "};\n\n";
@action_offset = ();
printf "#define CONTEXT_CT %d\n", $context_ct;
print "#if 0 /* context_names is small enough to walk the string instead */\n";
print "static const uint16_t context_offsets[CONTEXT_CT] = {\n";
foreach my $define (@context_offset)
{
printf("%d, /*%s*/\n", @$define{'offset'}, @$define{'name'});
}
print "};\n#endif\n\n";
@context_offset = ();
printf "#define ACTIONBUFSZ %d\n", $len_max_action;
printf "#define CONTEXTBUFSZ %d\n\n", $len_max_context;
if ($len_max_action > $len_max_context)
{
print "static char name_buf[ACTIONBUFSZ];\n";
}
else
{
print "static char name_buf[CONTEXTBUFSZ];\n";
}
print <<EOF
char* action_name(int action)
{
if (action >= 0 && action < ACTION_CT)
{
uint16_t offset = action_offsets[action];
const char *act = &action_names[offset];
if (action < ACTION_USB_HID_FIRST)
rb->snprintf(name_buf, ACTIONBUFSZ, act, "ACTION_");
else
rb->snprintf(name_buf, ACTIONBUFSZ, act, "ACTION_USB_HID_");
}
else
rb->snprintf(name_buf, ACTIONBUFSZ, "ACTION_UNKNOWN");
return name_buf;
}
/* walk string increment offset for each NULL if desired offset found, return */
static const char *context_getoffset(int offset)
{
const char *names = context_names;
const size_t len = sizeof(context_names) - 1;
int current = 0;
if (offset > 0)
{
const char *pos = names;
const char *end = names + len;
while (pos < end)
{
if (*pos++ == '\\0')
{
current++;
if (offset == current)
return pos;
pos += $len_min_context; /* each string is at least this long */
}
}
}
return names;
}
char* context_name(int context)
{
const char *ctx;
if (context >= 0 && context < CONTEXT_CT)
{
#if 0
uint16_t offset = context_offsets[context];
ctx = &context_names[offset];
#else
ctx = context_getoffset(context);
#endif
}
else
ctx = "%sUNKNOWN";
rb->snprintf(name_buf, CONTEXTBUFSZ, ctx, "CONTEXT_");
return name_buf;
}
EOF
;