in meta/utils.pm [430:608]
sub ProcessEnumInitializers
{
#
# This function attempts to figure out enum integers values during paring
# time in similar way as C compiler would do. Because SAI community agreed
# that enum grouping is more beneficial then ordering enums, then enum
# values could be not sorted any more. But if we figure out integers
# values, we could perform stable sort at this parser level, and generate
# enums metadata where enum values are sorted.
#
my ($arr_ref, $ini_ref, $enumTypeName, $SAI_DEFINES_REF) = @_;
return if $enumTypeName =~ /_extensions_t$/; # ignore initializers on extensions
if (scalar(@$arr_ref) != scalar(@$ini_ref))
{
LogError "attr array not matching initializers array on $enumTypeName";
return;
}
#return if grep (/<</, @$ini_ref); # skip shifted flags enum
my $previousEnumValue = -1;
my $idx = 0;
# using reference here, will cause update $ini inside initializer table
# reference and that's what we want
for my $ini (@$ini_ref)
{
if ($ini eq "")
{
$previousEnumValue += 1;
$ini = sprintf("0x%08x", $previousEnumValue);
}
elsif ($ini =~ /^= (0x[0-9a-f]{8})$/)
{
$previousEnumValue = hex($1);
$ini = sprintf("0x%08x", $previousEnumValue);
}
elsif ($ini =~ /^=\s+(\d+)$/)
{
$previousEnumValue = hex($1);
$ini = sprintf("0x%08x", $previousEnumValue);
}
elsif ($ini =~ /= (SAI_\w+)$/)
{
for my $i (0..$idx)
{
if ($$arr_ref[$i] eq $1)
{
$ini = @$ini_ref[$i];
$previousEnumValue = hex($ini);
last;
}
}
LogError "initializer $ini not found on $enumTypeName before $$arr_ref[$idx]" if not $ini =~ /^0x/;
}
elsif ($ini =~ /^= (SAI_\w+) \+ (SAI_\w+)$/) # special case SAI_ACL_USER_DEFINED_FIELD_ATTR_ID_RANGE
{
# this case is in form: = (sai enum value) + (sai define)
my $first = $1;
my $val = $SAI_DEFINES_REF->{$2};
if (not defined $val)
{
LogError "Value $2 not defined using #define directive";
}
elsif (not $val =~ /^0x[0-9a-f]+$/i)
{
LogError "$val not in hex format 0xYY";
}
else
{
for my $i (0..$idx)
{
if ($$arr_ref[$i] eq $first)
{
$ini = sprintf("0x%08x", hex(@$ini_ref[$i]) + hex($val));
$previousEnumValue = hex($ini);
last;
}
}
LogError "initializer $ini not found on $enumTypeName before $$arr_ref[$idx]" if not $ini =~ /^0x/;
}
}
elsif ($ini =~/^= (SAI_\w+) \+ (\d+)$/)
{
my $first = $1;
my $val = $2;
for my $i (0..$idx)
{
if ($$arr_ref[$i] eq $first)
{
$ini = sprintf("0x%08x", hex(@$ini_ref[$i]) + $val);
$previousEnumValue = hex($ini);
last;
}
}
LogError "initializer $ini not found on $enumTypeName before $$arr_ref[$idx]" if not $ini =~ /^0x/;
}
elsif ($ini =~/^= (SAI_\w+) \+ (0x[0-9a-f]{1,8})$/)
{
my $first = $1;
my $val = $2;
for my $i (0..$idx)
{
if ($$arr_ref[$i] eq $first)
{
$ini = sprintf("0x%08x", hex(@$ini_ref[$i]) + hex($val));
$previousEnumValue = hex($ini);
last;
}
}
LogError "initializer $ini not found on $enumTypeName before $$arr_ref[$idx]" if not $ini =~ /^0x/;
}
elsif ($ini =~ /^= \(?(\d+) << (\d+)\)?$/)
{
$previousEnumValue = $1 << $2;
$ini = sprintf("0x%08x", $previousEnumValue);
}
else
{
LogError "not supported initializer '$ini' on $$arr_ref[$idx], FIXME";
}
$idx++;
}
# in final form all initializers must be hex numbers 8 digits long, since
# they will be used in stable sort
if (scalar(grep (/^0x[0-9a-f]{8}$/, @$ini_ref)) != scalar(@$ini_ref))
{
LogError "wrong initializers on $enumTypeName: @$ini_ref";
return;
}
my $before = "@$arr_ref";
my @joined = ();
for my $idx (0..$#$arr_ref)
{
push @joined, "$$ini_ref[$idx]$$arr_ref[$idx]"; # format is: 0x00000000SAI_
}
my @sorted = sort { substr($a, 0, 10) cmp substr($b, 0, 10) } @joined;
s/^0x[0-9a-f]{8}SAI/SAI/i for @sorted;
my $after = "@sorted";
return if $after eq $before;
LogDebug "Need sort initalizers for $enumTypeName";
@$arr_ref = ();
push @$arr_ref, @sorted;
}