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
|
package main
import (
"fmt"
"os"
)
func (p *Protocol) AddAlignGaps() {
for i := range p.Imports {
p.Imports[i].AddAlignGaps()
}
for i := range p.Types {
switch t := p.Types[i].(type) {
case *Struct:
t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
case *Event:
t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
case *Error:
t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
}
}
for i := range p.Requests {
p.Requests[i].Fields = addAlignGapsToFields(
p.Requests[i].xmlName, p.Requests[i].Fields)
if p.Requests[i].Reply != nil {
p.Requests[i].Reply.Fields = addAlignGapsToFields(
p.Requests[i].xmlName, p.Requests[i].Reply.Fields)
}
}
}
func addAlignGapsToFields(name string, fields []Field) []Field {
var i int
for i = 0; i < len(fields); i++ {
if _, ok := fields[i].(*ListField); ok {
break
}
}
if i >= len(fields) {
return fields
}
r := make([]Field, 0, len(fields)+2)
r = append(r, fields[:i]...)
r = append(r, fields[i])
for i = i + 1; i < len(fields); i++ {
switch f := fields[i].(type) {
case *ListField:
// ok, add padding
sz := xcbSizeOfType(f.Type)
switch {
case sz == 1:
// nothing
case sz == 2:
r = append(r, &PadField{0, 2})
case sz == 3:
panic(fmt.Errorf("Alignment is not a power of 2"))
case sz >= 4:
r = append(r, &PadField{0, 4})
}
case *LocalField:
// nothing
default:
fmt.Fprintf(os.Stderr,
"Can't add alignment gaps, mix of list and non-list "+
"fields: %s\n", name)
return fields
}
r = append(r, fields[i])
}
return r
}
func xcbSizeOfField(fld Field) int {
switch f := fld.(type) {
case *PadField:
return int(f.Bytes)
case *SingleField:
return xcbSizeOfType(f.Type)
case *ListField:
return 0
case *ExprField:
return xcbSizeOfType(f.Type)
case *ValueField:
return xcbSizeOfType(f.MaskType)
case *SwitchField:
return 0
default:
return 0
}
}
func xcbSizeOfType(typ Type) int {
switch t := typ.(type) {
case *Resource:
return 4
case *TypeDef:
return t.Size().Eval()
case *Base:
return t.Size().Eval()
case *Struct:
sz := 0
for i := range t.Fields {
sz += xcbSizeOfField(t.Fields[i])
}
return sz
case *Union:
sz := 0
for i := range t.Fields {
csz := xcbSizeOfField(t.Fields[i])
if csz > sz {
sz = csz
}
}
return sz
default:
return 0
}
}
|