aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler/consts.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-08-27 15:08:11 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-08-27 15:28:49 +0200
commite2ffb4fc9111e28f1d8e0e987cb06172cbbd4e84 (patch)
tree8dc4d76063e3430321622cd81763a95a972f2e3a /pkg/compiler/consts.go
parente71c87fbf52c83d8e514e4685d40da4d4d0f1a1c (diff)
pkg/compiler: move more const-processing code to compiler
Diffstat (limited to 'pkg/compiler/consts.go')
-rw-r--r--pkg/compiler/consts.go124
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] }