1
2
3
4
5 package xeddata
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "io/ioutil"
13 "os"
14 "path/filepath"
15 "regexp"
16 "strings"
17 )
18
19
20 type (
21
22 OperandSizeMode int
23
24
25 AddressSizeMode int
26
27
28 CPUMode int
29 )
30
31
32 const (
33 OpSize16 OperandSizeMode = iota
34 OpSize32
35 OpSize64
36 )
37
38
39 const (
40 AddrSize16 AddressSizeMode = iota
41 AddrSize32
42 AddrSize64
43 )
44
45
46 const (
47 Mode16 CPUMode = iota
48 Mode32
49 Mode64
50 )
51
52 var sizeStrings = [...]string{"16", "32", "64"}
53
54
55 func sizeString(size int) string {
56
57
58
59 if size >= len(sizeStrings) {
60 panic(fmt.Sprintf("illegal size value: %d", size))
61 }
62 return sizeStrings[size]
63 }
64
65
66 func (osz OperandSizeMode) String() string { return sizeString(int(osz)) }
67
68
69 func (asz AddressSizeMode) String() string { return sizeString(int(asz)) }
70
71
72
73 type Database struct {
74 widths map[string]*width
75 states map[string]string
76 xtypes map[string]*xtype
77 }
78
79
80 type width struct {
81
82 xtype string
83
84
85 sizes [3]string
86 }
87
88
89 type xtype struct {
90
91 name string
92
93
94
95 baseType string
96
97
98 size string
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116 func NewDatabase(xedPath string) (*Database, error) {
117 var db Database
118
119 stat, err := os.Stat(xedPath)
120 if err != nil {
121 return nil, err
122 }
123 if !stat.IsDir() {
124 return nil, errors.New("xedPath is not directory")
125 }
126
127 states, err := os.Open(filepath.Join(xedPath, "all-state.txt"))
128 if err == nil {
129 err = db.LoadStates(states)
130 if err != nil {
131 return &db, err
132 }
133 }
134
135 widths, err := os.Open(filepath.Join(xedPath, "all-widths.txt"))
136 if err == nil {
137 err = db.LoadWidths(widths)
138 if err != nil {
139 return &db, err
140 }
141 }
142
143 xtypes, err := os.Open(filepath.Join(xedPath, "all-element-types.txt"))
144 if err == nil {
145 err = db.LoadXtypes(xtypes)
146 if err != nil {
147 return &db, err
148 }
149 }
150
151 return &db, nil
152 }
153
154
155
156
157 func (db *Database) LoadWidths(r io.Reader) error {
158 var err error
159 db.widths, err = parseWidths(r)
160 return err
161 }
162
163
164
165
166 func (db *Database) LoadStates(r io.Reader) error {
167 var err error
168 db.states, err = parseStates(r)
169 return err
170 }
171
172
173
174
175
176 func (db *Database) LoadXtypes(r io.Reader) error {
177 var err error
178 db.xtypes, err = parseXtypes(r)
179 return err
180 }
181
182
183
184 func (db *Database) WidthSize(width string, m OperandSizeMode) string {
185 info := db.widths[width]
186 if info == nil {
187 return ""
188 }
189 return info.sizes[m]
190 }
191
192 func parseWidths(r io.Reader) (map[string]*width, error) {
193 data, err := ioutil.ReadAll(r)
194 if err != nil {
195 return nil, fmt.Errorf("parse widths: %v", err)
196 }
197
198
199
200
201 reLine := regexp.MustCompile(`(^\s*\w+\s+\w+\s+\w+\s+\w+\s+\w+)|(^\s*\w+\s+\w+\s+\w+)`)
202
203 widths := make(map[string]*width, 128)
204 for _, l := range bytes.Split(data, []byte("\n")) {
205 var name, xtype, size16, size32, size64 string
206
207 if m := reLine.FindSubmatch(l); m != nil {
208 var f [][]byte
209 if m[1] != nil {
210 f = bytes.Fields(m[1])
211 } else {
212 f = bytes.Fields(m[2])
213 }
214
215 name = string(f[0])
216 xtype = string(f[1])
217 if len(f) > 3 {
218 size16 = string(f[2])
219 size32 = string(f[3])
220 size64 = string(f[4])
221 } else {
222 size16 = string(f[2])
223 size32 = size16
224 size64 = size16
225 }
226 }
227 if name != "" {
228 widths[name] = &width{
229 xtype: xtype,
230 sizes: [3]string{size16, size32, size64},
231 }
232 }
233 }
234
235 return widths, nil
236 }
237
238 func parseStates(r io.Reader) (map[string]string, error) {
239 data, err := ioutil.ReadAll(r)
240 if err != nil {
241 return nil, fmt.Errorf("parse states: %v", err)
242 }
243
244
245
246 lineRE := regexp.MustCompile(`^\s*(\w+)\s+([^#]+)`)
247
248 states := make(map[string]string, 128)
249 for _, l := range strings.Split(string(data), "\n") {
250 if m := lineRE.FindStringSubmatch(l); m != nil {
251 name, replacements := m[1], m[2]
252 states[name] = strings.TrimSpace(replacements)
253 }
254 }
255
256 return states, nil
257 }
258
259 func parseXtypes(r io.Reader) (map[string]*xtype, error) {
260 data, err := ioutil.ReadAll(r)
261 if err != nil {
262 return nil, fmt.Errorf("parse xtypes: %v", err)
263 }
264
265
266 lineRE := regexp.MustCompile(`^\s*(\w+)\s+(\w+)\s*(\d+)`)
267
268 xtypes := make(map[string]*xtype)
269 for _, l := range strings.Split(string(data), "\n") {
270 if m := lineRE.FindStringSubmatch(l); m != nil {
271 name, baseType, size := m[1], m[2], m[3]
272 xtypes[name] = &xtype{
273 name: name,
274 baseType: baseType,
275 size: size,
276 }
277 }
278 }
279
280 return xtypes, nil
281 }
282
View as plain text