Repository navigation
Expand file tree
/
Copy pathBitfield.pm
More file actions
128 lines (101 loc) · 3.96 KB
/
Copy pathBitfield.pm
File metadata and controls
128 lines (101 loc) · 3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package Bitfield;
use utf8;
use strict;
use warnings;
BEGIN {
use Exporter ();
our $VERSION = 1.00;
our @ISA = qw(Exporter);
our @EXPORT = qw( &render_bitfield_core &render_bitfield_type );
our %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ],
our @EXPORT_OK = qw( );
}
END { }
use XML::LibXML;
use Common;
sub render_bitfield_core {
my ($name, $tag) = @_;
my $bitfield_name = $name;
my $base = get_primitive_base($tag);
my @fields = $tag->findnodes('child::ld:field');
emit_comment $tag, -attr => 1;
emit_block {
emit $base, ' whole;';
my $idx = 0;
my @idlist;
emit_block {
for my $item (@fields) {
($item->getAttribute('ld:meta') eq 'number' &&
$item->getAttribute('ld:subtype') eq 'flag-bit')
or die "Invalid bitfield member: ".$item->toString."\n";
check_bad_attrs($item);
my $name = ensure_name $item->getAttribute('name');
my $size = $item->getAttribute('count') || 1;
my $fbase = $base;
my ($etn, $ettag) = decode_type_name_ref($item, -force_type => 'enum-type');
if ($etn) {
my $ebase = get_primitive_base($ettag, 'int32_t');
unless ($ebase eq $base) {
die "Bitfield item $name of $bitfield_name has a different base type: $ebase.\n";
}
$fbase = $etn;
}
push @idlist, [ $name, $idx, sprintf('0x%xU',((1<<$size)-1)<<$idx), ',' ];
$idx += $size;
emit_comment $item;
emit $fbase, " ", $name, " : ", $size, ";", get_comment($item);
}
} "struct ", " bits;";
$idlist[-1][3] = '';
emit_block {
for my $r (@idlist) {
emit "shift_", $r->[0], " = ", $r->[1], $r->[3];
}
} "enum Shift ", ";";
emit_block {
for my $r (@idlist) {
emit "mask_", $r->[0], " = ", $r->[2], $r->[3];
}
} "enum Mask : $base ", ";";
emit $name, "($base whole_ = 0) : whole(whole_) {};";
} "union $name ", ";";
my $full_name = fully_qualified_name($tag, $name, 1);
my $traits_name = 'traits<'.$full_name.'>';
with_emit_traits {
emit_block {
emit "typedef $base base_type;";
emit "typedef $full_name bitfield_type;";
emit "static const int bit_count = sizeof(base_type)*8;";
emit "static const bitfield_item_info bits[bit_count];";
} "template<> struct ${export_prefix}bitfield_$traits_name ", ";";
emit_block {
emit "static const type_identity_for<$full_name> identity;";
emit "static const type_identity_for<$full_name> *get() { return &identity; }";
} "template<> struct ${export_prefix}identity_$traits_name ", ";";
header_ref("Export.h");
header_ref("DataDefs.h");
header_ref("DataIdentity.h");
};
with_emit_static {
emit_block {
for my $item (@fields) {
my $name = $item->getAttribute('name');
my $size = $item->getAttribute('count') || 1;
emit "{ ", ($name?'"'.$name.'"':'NULL'), ", ", $size, " },";
for (my $j = 1; $j < $size; $j++) {
emit "{ NULL, ", -$j, " },";
}
}
$lines[-1] =~ s/,$//;
} "const bitfield_item_info bitfield_${traits_name}::bits[bit_count] = ", ";";
emit "const type_identity_for<$full_name> identity_${traits_name}::identity(",
"sizeof($full_name), ",
type_identity_reference($tag,-parent => 1), ', ',
"\"$name\", bitfield_${traits_name}::bit_count, bitfield_${traits_name}::bits);";
} 'enums';
}
sub render_bitfield_type {
my ($tag) = @_;
render_bitfield_core($typename,$tag);
}
1;