diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-08-27 15:08:11 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-08-27 15:28:49 +0200 |
| commit | e2ffb4fc9111e28f1d8e0e987cb06172cbbd4e84 (patch) | |
| tree | 8dc4d76063e3430321622cd81763a95a972f2e3a /pkg/compiler/consts.go | |
| parent | e71c87fbf52c83d8e514e4685d40da4d4d0f1a1c (diff) | |
pkg/compiler: move more const-processing code to compiler
Diffstat (limited to 'pkg/compiler/consts.go')
| -rw-r--r-- | pkg/compiler/consts.go | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/pkg/compiler/consts.go b/pkg/compiler/consts.go new file mode 100644 index 000000000..78f8ada00 --- /dev/null +++ b/pkg/compiler/consts.go @@ -0,0 +1,124 @@ +// Copyright 2017 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package compiler + +import ( + "bufio" + "bytes" + "fmt" + "io/ioutil" + "path/filepath" + "sort" + "strconv" + "strings" + + "github.com/google/syzkaller/pkg/ast" +) + +func SerializeConsts(consts map[string]uint64) []byte { + var nv []nameValuePair + for k, v := range consts { + nv = append(nv, nameValuePair{k, v}) + } + sort.Sort(nameValueArray(nv)) + + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "# AUTOGENERATED FILE\n") + for _, x := range nv { + fmt.Fprintf(buf, "%v = %v\n", x.name, x.val) + } + return buf.Bytes() +} + +func DeserializeConsts(data []byte, file string, eh ast.ErrorHandler) map[string]uint64 { + consts := make(map[string]uint64) + pos := ast.Pos{ + File: file, + Line: 1, + } + ok := true + s := bufio.NewScanner(bytes.NewReader(data)) + for ; s.Scan(); pos.Line++ { + line := s.Text() + if line == "" || line[0] == '#' { + continue + } + eq := strings.IndexByte(line, '=') + if eq == -1 { + eh(pos, "expect '='") + ok = false + continue + } + name := strings.TrimSpace(line[:eq]) + val, err := strconv.ParseUint(strings.TrimSpace(line[eq+1:]), 0, 64) + if err != nil { + eh(pos, fmt.Sprintf("failed to parse int: %v", err)) + ok = false + continue + } + if _, ok := consts[name]; ok { + eh(pos, fmt.Sprintf("duplicate const %q", name)) + ok = false + continue + } + consts[name] = val + } + if err := s.Err(); err != nil { + eh(pos, fmt.Sprintf("failed to parse: %v", err)) + ok = false + } + if !ok { + return nil + } + return consts +} + +func DeserializeConstsGlob(glob string, eh ast.ErrorHandler) map[string]uint64 { + if eh == nil { + eh = ast.LoggingHandler + } + files, err := filepath.Glob(glob) + if err != nil { + eh(ast.Pos{}, fmt.Sprintf("failed to find const files: %v", err)) + return nil + } + if len(files) == 0 { + eh(ast.Pos{}, fmt.Sprintf("no const files matched by glob %q", glob)) + return nil + } + consts := make(map[string]uint64) + for _, f := range files { + data, err := ioutil.ReadFile(f) + if err != nil { + eh(ast.Pos{}, fmt.Sprintf("failed to read const file: %v", err)) + return nil + } + consts1 := DeserializeConsts(data, filepath.Base(f), eh) + if consts1 == nil { + consts = nil + } + if consts != nil { + for n, v := range consts1 { + if old, ok := consts[n]; ok && old != v { + eh(ast.Pos{}, fmt.Sprintf( + "different values for const %q: %v vs %v", n, v, old)) + return nil + } + consts[n] = v + } + } + } + return consts +} + +type nameValuePair struct { + name string + val uint64 +} + +type nameValueArray []nameValuePair + +func (a nameValueArray) Len() int { return len(a) } +func (a nameValueArray) Less(i, j int) bool { return a[i].name < a[j].name } +func (a nameValueArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } |
