From 127a9c2b65ae07f309e839c3b8e5ab2ee7983e56 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 22 May 2017 05:28:31 +0200 Subject: pkg/ast: new parser for sys descriptions The old parser in sys/sysparser is too hacky, difficult to extend and drops debug info too early, so that we can't produce proper error messages. Add a new parser that is build like a proper language parser and preserves full debug info for every token. --- tools/syz-fmt/syz-fmt.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tools/syz-fmt/syz-fmt.go (limited to 'tools') diff --git a/tools/syz-fmt/syz-fmt.go b/tools/syz-fmt/syz-fmt.go new file mode 100644 index 000000000..f78e8b8dc --- /dev/null +++ b/tools/syz-fmt/syz-fmt.go @@ -0,0 +1,72 @@ +// 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. + +// syz-fmt re-formats sys files into standard form. +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/google/syzkaller/pkg/ast" +) + +func main() { + if len(os.Args) < 2 { + fmt.Fprintf(os.Stderr, "usage: syz-fmt files... or dirs...\n") + os.Exit(1) + } + for _, arg := range os.Args[1:] { + st, err := os.Stat(arg) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to stat %v: %v\n", arg, err) + os.Exit(1) + } + if st.IsDir() { + files, err := ioutil.ReadDir(arg) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read dir %v: %v\n", arg, err) + os.Exit(1) + } + for _, file := range files { + if !strings.HasSuffix(file.Name(), ".txt") { + continue + } + processFile(filepath.Join(arg, file.Name()), file.Mode()) + } + } else { + processFile(arg, st.Mode()) + } + } +} + +func processFile(file string, mode os.FileMode) { + data, err := ioutil.ReadFile(file) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to read file %v: %v\n", file, err) + os.Exit(1) + } + errorHandler := func(pos ast.Pos, msg string) { + fmt.Fprintf(os.Stderr, "%v:%v:%v: %v", pos.File, pos.Line, pos.Col, msg) + } + top, ok := ast.Parse(data, filepath.Base(file), errorHandler) + if !ok { + os.Exit(1) + } + formatted := ast.Format(top) + if bytes.Equal(data, formatted) { + return + } + if err := os.Rename(file, file+"~"); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } + if err := ioutil.WriteFile(file, formatted, mode); err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + os.Exit(1) + } +} -- cgit mrf-deployment