Bug 617947 - glib-mkenums: add @valuenum@ support

Add a @valuenum@ substitution that outputs the integer value of a
particular enum value.  The value is determined by using (sandboxed)
perl to evaluate C expression.  If evaluation fails then glib-mkenums
dies loudly.  Evaluation is only enabled if '@valuenum@' appears in the
template file, so existing users will not be affected.
This commit is contained in:
Ryan Lortie 2010-05-06 14:19:58 -05:00
parent 7aa71527e5
commit 47805f4e0c

View File

@ -1,6 +1,7 @@
#!@PERL_PATH@ -w
use File::Basename;
use Safe;
# glib-mkenums.pl
# Information about the current enumeration
@ -21,6 +22,7 @@ my $enumname_prefix; # prefix of $enumname
my $enumindex = 0; # Global enum counter
my $firstenum = 1; # Is this the first enumeration per file?
my @entries; # [ $name, $val ] for each entry
my $sandbox = Safe->new; # sandbox for safe evaluation of expressions
sub parse_trigraph {
my $opts = shift;
@ -110,10 +112,10 @@ sub parse_entries {
if (defined $options) {
my %options = parse_trigraph($options);
if (!defined $options{skip}) {
push @entries, [ $name, $options{nick} ];
push @entries, [ $name, $value, $options{nick} ];
}
} else {
push @entries, [ $name ];
push @entries, [ $name, $value ];
}
} elsif (m@^\s*\#@) {
# ignore preprocessor directives
@ -158,6 +160,7 @@ sub usage {
print " \@ENUMPREFIX\@ PREFIX\n";
print " \@VALUENAME\@ PREFIX_THE_XVALUE\n";
print " \@valuenick\@ the-xvalue\n";
print " \@valuenum\@ the integer value (limited support, Since: 2.26)\n";
print " \@type\@ either enum or flags\n";
print " \@Type\@ either Enum or Flags\n";
print " \@TYPE\@ either ENUM or FLAGS\n";
@ -331,7 +334,7 @@ while (<>) {
# Autogenerate a prefix
if (!defined $enum_prefix) {
for (@entries) {
my $nick = $_->[1];
my $nick = $_->[2];
if (!defined $nick) {
my $name = $_->[0];
if (defined $enum_prefix) {
@ -357,12 +360,12 @@ while (<>) {
}
for $entry (@entries) {
my ($name,$nick) = @{$entry};
my ($name,$num,$nick) = @{$entry};
if (!defined $nick) {
($nick = $name) =~ s/^$enum_prefix//;
$nick =~ tr/_/-/;
$nick = lc($nick);
@{$entry} = ($name, $nick);
@{$entry} = ($name, $num, $nick);
}
}
@ -454,13 +457,34 @@ while (<>) {
if (length($vprod)) {
my $prod = $vprod;
my $next_num = 0;
$prod =~ s/\\a/\a/g; $prod =~ s/\\b/\b/g; $prod =~ s/\\t/\t/g; $prod =~ s/\\n/\n/g;
$prod =~ s/\\f/\f/g; $prod =~ s/\\r/\r/g;
for (@entries) {
my ($name,$nick) = @{$_};
my ($name,$num,$nick) = @{$_};
my $tmp_prod = $prod;
if ($prod =~ /\@valuenum\@/) {
# only attempt to eval the value if it is requested
# this prevents us from throwing errors otherwise
if (defined $num) {
# use sandboxed perl evaluation as a reasonable
# approximation to C constant folding
$num = $sandbox->reval ($num);
# make sure it parsed to an integer
if (!defined $num or $num !~ /^-?\d+$/) {
die "Unable to parse enum value '$num'";
}
} else {
$num = $next_num;
}
$tmp_prod =~ s/\@valuenum\@/$num/g;
$next_num = $num + 1;
}
$tmp_prod =~ s/\@VALUENAME\@/$name/g;
$tmp_prod =~ s/\@valuenick\@/$nick/g;
if ($flags) { $tmp_prod =~ s/\@type\@/flags/g; } else { $tmp_prod =~ s/\@type\@/enum/g; }