aboutsummaryrefslogtreecommitdiffstats
path: root/sysparser
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-06-17 13:17:11 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-06-17 14:41:15 +0200
commit2007005ac39f66f3fb6314745ffb22b6d30314d3 (patch)
treedbdfe1600cf905199e058ff799b0c8f31efcf7a8 /sysparser
parent017b5dea530573ce49ccc6f09c469a78c7dbaede (diff)
sys/sysparser: move from sysparser
Diffstat (limited to 'sysparser')
-rw-r--r--sysparser/lexer.go313
-rw-r--r--sysparser/parser.go100
2 files changed, 0 insertions, 413 deletions
diff --git a/sysparser/lexer.go b/sysparser/lexer.go
deleted file mode 100644
index 505b52059..000000000
--- a/sysparser/lexer.go
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2015/2016 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 sysparser
-
-import (
- "fmt"
- "io"
- "os"
- "sort"
- "strconv"
- "strings"
-)
-
-type Description struct {
- Includes []string
- Defines map[string]string
- Syscalls []Syscall
- Structs map[string]*Struct
- Unnamed map[string][]string
- Flags map[string][]string
- StrFlags map[string][]string
- Resources map[string]Resource
-}
-
-type Syscall struct {
- Name string
- CallName string
- Args [][]string
- Ret []string
-}
-
-type Struct struct {
- Name string
- Flds [][]string
- IsUnion bool
- Packed bool
- Varlen bool
- Align int
-}
-
-type Resource struct {
- Name string
- Base string
- Values []string
-}
-
-func Parse(in io.Reader) *Description {
- p := newParser(in)
- var includes []string
- defines := make(map[string]string)
- var syscalls []Syscall
- structs := make(map[string]*Struct)
- unnamed := make(map[string][]string)
- flags := make(map[string][]string)
- strflags := make(map[string][]string)
- resources := make(map[string]Resource)
- var str *Struct
- for p.Scan() {
- if p.EOF() || p.Char() == '#' {
- continue
- }
- if str != nil {
- // Parsing a struct.
- if p.Char() == '}' || p.Char() == ']' {
- p.Parse(p.Char())
- for _, attr := range parseType1(p, unnamed, flags, "")[1:] {
- if str.IsUnion {
- switch attr {
- case "varlen":
- str.Varlen = true
- default:
- failf("unknown union %v attribute: %v", str.Name, attr)
- }
- } else {
- switch {
- case attr == "packed":
- str.Packed = true
- case strings.HasPrefix(attr, "align_ptr"):
- str.Align = 8 // TODO: this must be target pointer size
- case strings.HasPrefix(attr, "align_"):
- a, err := strconv.ParseUint(attr[6:], 10, 64)
- if err != nil {
- failf("bad struct %v alignment %v: %v", str.Name, attr, err)
- }
- if a&(a-1) != 0 || a == 0 || a > 1<<30 {
- failf("bad struct %v alignment %v: must be sane power of 2", str.Name, a)
- }
- str.Align = int(a)
- default:
- failf("unknown struct %v attribute: %v", str.Name, attr)
- }
- }
- }
- if str.IsUnion {
- if len(str.Flds) <= 1 {
- failf("union %v has only %v fields, need at least 2", str.Name, len(str.Flds))
- }
- }
- fields := make(map[string]bool)
- for _, f := range str.Flds {
- if f[0] == "parent" {
- failf("struct/union %v contains reserved field 'parent'", str.Name)
- }
- if fields[f[0]] {
- failf("duplicate field %v in struct/union %v", f[0], str.Name)
- }
- fields[f[0]] = true
- }
- structs[str.Name] = str
- str = nil
- } else {
- p.SkipWs()
- fld := []string{p.Ident()}
- fld = append(fld, parseType(p, unnamed, flags)...)
- str.Flds = append(str.Flds, fld)
- }
- } else {
- name := p.Ident()
- if name == "include" {
- p.Parse('<')
- var include []byte
- for {
- ch := p.Char()
- if ch == '>' {
- break
- }
- p.Parse(ch)
- include = append(include, ch)
- }
- p.Parse('>')
- includes = append(includes, string(include))
- } else if name == "define" {
- key := p.Ident()
- var val []byte
- for !p.EOF() {
- ch := p.Char()
- p.Parse(ch)
- val = append(val, ch)
- }
- if defines[key] != "" {
- failf("%v define is defined multiple times", key)
- }
- defines[key] = fmt.Sprintf("(%s)", val)
- } else if name == "resource" {
- p.SkipWs()
- id := p.Ident()
- p.Parse('[')
- base := p.Ident()
- p.Parse(']')
- var vals []string
- if !p.EOF() && p.Char() == ':' {
- p.Parse(':')
- vals = append(vals, p.Ident())
- for !p.EOF() {
- p.Parse(',')
- vals = append(vals, p.Ident())
- }
- }
- if _, ok := resources[id]; ok {
- failf("resource '%v' is defined multiple times", id)
- }
- if _, ok := structs[id]; ok {
- failf("struct '%v' is redefined as resource", name)
- }
- resources[id] = Resource{id, base, vals}
- } else {
- switch ch := p.Char(); ch {
- case '(':
- // syscall
- p.Parse('(')
- var args [][]string
- for p.Char() != ')' {
- arg := []string{p.Ident()}
- arg = append(arg, parseType(p, unnamed, flags)...)
- args = append(args, arg)
- if p.Char() != ')' {
- p.Parse(',')
- }
- }
- p.Parse(')')
- var ret []string
- if !p.EOF() {
- ret = parseType(p, unnamed, flags)
- }
- callName := name
- if idx := strings.IndexByte(callName, '$'); idx != -1 {
- callName = callName[:idx]
- }
- fields := make(map[string]bool)
- for _, a := range args {
- if fields[a[0]] {
- failf("duplicate arg %v in syscall %v", a[0], name)
- }
- fields[a[0]] = true
- }
- syscalls = append(syscalls, Syscall{name, callName, args, ret})
- case '=':
- // flag
- p.Parse('=')
- str := p.Char() == '"'
- var vals []string
- for {
- v := p.Ident()
- if str {
- v = v[1 : len(v)-1]
- }
- vals = append(vals, v)
- if p.EOF() {
- break
- }
- p.Parse(',')
- }
- if str {
- strflags[name] = vals
- } else {
- flags[name] = vals
- }
- case '{', '[':
- p.Parse(ch)
- if _, ok := structs[name]; ok {
- failf("struct '%v' is defined multiple times", name)
- }
- if _, ok := resources[name]; ok {
- failf("resource '%v' is redefined as struct", name)
- }
- str = &Struct{Name: name, IsUnion: ch == '['}
- default:
- failf("bad line (%v)", p.Str())
- }
- }
- }
- if !p.EOF() {
- failf("trailing data (%v)", p.Str())
- }
- }
- sort.Sort(syscallArray(syscalls))
- return &Description{
- Includes: includes,
- Defines: defines,
- Syscalls: syscalls,
- Structs: structs,
- Unnamed: unnamed,
- Flags: flags,
- StrFlags: strflags,
- Resources: resources,
- }
-}
-
-func isIdentifier(s string) bool {
- for i, c := range s {
- if c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || i > 0 && (c >= '0' && c <= '9') {
- continue
- }
- return false
- }
- return true
-}
-
-func parseType(p *parser, unnamed map[string][]string, flags map[string][]string) []string {
- return parseType1(p, unnamed, flags, p.Ident())
-}
-
-var (
- unnamedSeq int
- constSeq int
-)
-
-func parseType1(p *parser, unnamed map[string][]string, flags map[string][]string, name string) []string {
- typ := []string{name}
- if !p.EOF() && p.Char() == '[' {
- p.Parse('[')
- for {
- id := p.Ident()
- if p.Char() == '[' {
- inner := parseType1(p, unnamed, flags, id)
- id = fmt.Sprintf("unnamed%v", unnamedSeq)
- unnamedSeq++
- unnamed[id] = inner
- }
- typ = append(typ, id)
- if p.Char() == ']' {
- break
- }
- p.Parse(',')
- }
- p.Parse(']')
- }
- if name == "const" && len(typ) > 1 {
- // Create a fake flag with the const value.
- id := fmt.Sprintf("const_flag_%v", constSeq)
- constSeq++
- flags[id] = typ[1:2]
- }
- if name == "array" && len(typ) > 2 {
- // Create a fake flag with the const value.
- id := fmt.Sprintf("const_flag_%v", constSeq)
- constSeq++
- flags[id] = typ[2:3]
- }
- return typ
-}
-
-type syscallArray []Syscall
-
-func (a syscallArray) Len() int { return len(a) }
-func (a syscallArray) Less(i, j int) bool { return a[i].Name < a[j].Name }
-func (a syscallArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
-
-func failf(msg string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, msg+"\n", args...)
- os.Exit(1)
-}
diff --git a/sysparser/parser.go b/sysparser/parser.go
deleted file mode 100644
index d5021eee6..000000000
--- a/sysparser/parser.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2015/2016 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 sysparser
-
-import (
- "bufio"
- "fmt"
- "io"
- "os"
-)
-
-type parser struct {
- r *bufio.Scanner
- s string
- i int
- l int
-}
-
-func newParser(r io.Reader) *parser {
- return &parser{r: bufio.NewScanner(r)}
-}
-
-func (p *parser) Scan() bool {
- if !p.r.Scan() {
- if err := p.r.Err(); err != nil {
- failf("failed to read input file: %v", err)
- }
- return false
- }
- p.s = p.r.Text()
- p.i = 0
- p.l++
- return true
-}
-
-func (p *parser) Str() string {
- return p.s
-}
-
-func (p *parser) EOF() bool {
- return p.i == len(p.s)
-}
-
-func (p *parser) Char() byte {
- if p.EOF() {
- p.failf("unexpected eof")
- }
- return p.s[p.i]
-}
-
-func (p *parser) Parse(ch byte) {
- if p.EOF() {
- p.failf("want %s, got EOF", string(ch))
- }
- if p.s[p.i] != ch {
- p.failf("want '%v', got '%v'", string(ch), string(p.s[p.i]))
- }
- p.i++
- p.SkipWs()
-}
-
-func (p *parser) SkipWs() {
- for p.i < len(p.s) && (p.s[p.i] == ' ' || p.s[p.i] == '\t') {
- p.i++
- }
-}
-
-func (p *parser) Ident() string {
- start, end := p.i, 0
- if p.Char() == '"' {
- p.Parse('"')
- for p.Char() != '"' {
- p.i++
- }
- end = p.i + 1
- p.Parse('"')
- } else {
- for p.i < len(p.s) &&
- (p.s[p.i] >= 'a' && p.s[p.i] <= 'z' ||
- p.s[p.i] >= 'A' && p.s[p.i] <= 'Z' ||
- p.s[p.i] >= '0' && p.s[p.i] <= '9' ||
- p.s[p.i] == '_' || p.s[p.i] == '$' || // $ is for n-way syscalls (like ptrace$peek)
- p.s[p.i] == '-' || p.s[p.i] == ':') { // : is for ranged int (like int32[-3:10])
- p.i++
- }
- if start == p.i {
- p.failf("failed to parse identifier at pos %v", start)
- }
- end = p.i
- }
- s := p.s[start:end]
- p.SkipWs()
- return s
-}
-
-func (p *parser) failf(msg string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, "line #%v: %v\n", p.l, p.s)
- failf(msg, args...)
-}