...
1 package main
2
3 import (
4 "fmt"
5 "os"
6 )
7
8 func (p *Protocol) AddAlignGaps() {
9 for i := range p.Imports {
10 p.Imports[i].AddAlignGaps()
11 }
12 for i := range p.Types {
13 switch t := p.Types[i].(type) {
14 case *Struct:
15 t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
16 case *Event:
17 t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
18 case *Error:
19 t.Fields = addAlignGapsToFields(t.xmlName, t.Fields)
20 }
21 }
22 for i := range p.Requests {
23 p.Requests[i].Fields = addAlignGapsToFields(
24 p.Requests[i].xmlName, p.Requests[i].Fields)
25 if p.Requests[i].Reply != nil {
26 p.Requests[i].Reply.Fields = addAlignGapsToFields(
27 p.Requests[i].xmlName, p.Requests[i].Reply.Fields)
28 }
29 }
30 }
31
32 func addAlignGapsToFields(name string, fields []Field) []Field {
33 var i int
34 for i = 0; i < len(fields); i++ {
35 if _, ok := fields[i].(*ListField); ok {
36 break
37 }
38 }
39 if i >= len(fields) {
40 return fields
41 }
42
43 r := make([]Field, 0, len(fields)+2)
44 r = append(r, fields[:i]...)
45
46 r = append(r, fields[i])
47 for i = i + 1; i < len(fields); i++ {
48 switch f := fields[i].(type) {
49 case *ListField:
50
51 sz := xcbSizeOfType(f.Type)
52 switch {
53 case sz == 1:
54
55 case sz == 2:
56 r = append(r, &PadField{0, 2})
57 case sz == 3:
58 panic(fmt.Errorf("Alignment is not a power of 2"))
59 case sz >= 4:
60 r = append(r, &PadField{0, 4})
61 }
62 case *LocalField:
63
64 default:
65 fmt.Fprintf(os.Stderr,
66 "Can't add alignment gaps, mix of list and non-list "+
67 "fields: %s\n", name)
68 return fields
69 }
70 r = append(r, fields[i])
71 }
72 return r
73 }
74
75 func xcbSizeOfField(fld Field) int {
76 switch f := fld.(type) {
77 case *PadField:
78 return int(f.Bytes)
79 case *SingleField:
80 return xcbSizeOfType(f.Type)
81 case *ListField:
82 return 0
83 case *ExprField:
84 return xcbSizeOfType(f.Type)
85 case *ValueField:
86 return xcbSizeOfType(f.MaskType)
87 case *SwitchField:
88 return 0
89 default:
90 return 0
91 }
92 }
93
94 func xcbSizeOfType(typ Type) int {
95 switch t := typ.(type) {
96 case *Resource:
97 return 4
98 case *TypeDef:
99 return t.Size().Eval()
100 case *Base:
101 return t.Size().Eval()
102 case *Struct:
103 sz := 0
104 for i := range t.Fields {
105 sz += xcbSizeOfField(t.Fields[i])
106 }
107 return sz
108 case *Union:
109 sz := 0
110 for i := range t.Fields {
111 csz := xcbSizeOfField(t.Fields[i])
112 if csz > sz {
113 sz = csz
114 }
115 }
116 return sz
117 default:
118 return 0
119 }
120 }
121
View as plain text