From e2ffb4fc9111e28f1d8e0e987cb06172cbbd4e84 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sun, 27 Aug 2017 15:08:11 +0200 Subject: pkg/compiler: move more const-processing code to compiler --- pkg/compiler/consts.go | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 pkg/compiler/consts.go (limited to 'pkg/compiler/consts.go') 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] } -- cgit mrf-deployment