func isSpecialStruct(typ sys.Type) func(r *randGen, s *state) (*Arg, []*Call) { a, ok := typ.(*sys.StructType) if !ok { panic("must be a struct") } switch typ.Name() { case "timespec": return func(r *randGen, s *state) (*Arg, []*Call) { return r.timespec(s, a, false) } case "timeval": return func(r *randGen, s *state) (*Arg, []*Call) { return r.timespec(s, a, true) } } return nil }
func isSpecialStruct(typ sys.Type) func(r *randGen, s *state) (*Arg, []*Call) { if _, ok := typ.(*sys.StructType); !ok { panic("must be a struct") } switch typ.Name() { case "timespec": return func(r *randGen, s *state) (*Arg, []*Call) { return r.timespec(s, false) } case "timeval": return func(r *randGen, s *state) (*Arg, []*Call) { return r.timespec(s, true) } case "in6_addr": return func(r *randGen, s *state) (*Arg, []*Call) { return r.in6addr(s) } case "in_addr_any": return func(r *randGen, s *state) (*Arg, []*Call) { return r.inaddrany(s) } } return nil }
func parseArg(typ sys.Type, p *parser, vars map[string]*Arg) (*Arg, error) { r := "" if p.Char() == '<' { p.Parse('<') r = p.Ident() p.Parse('=') p.Parse('>') } var arg *Arg switch p.Char() { case '0': val := p.Ident() v, err := strconv.ParseUint(val, 0, 64) if err != nil { return nil, fmt.Errorf("wrong arg value '%v': %v", val, err) } arg = constArg(uintptr(v)) case 'r': id := p.Ident() v, ok := vars[id] if !ok || v == nil { return nil, fmt.Errorf("result %v references unknown variable (vars=%+v)", id, vars) } arg = resultArg(v) if p.Char() == '/' { p.Parse('/') op := p.Ident() v, err := strconv.ParseUint(op, 0, 64) if err != nil { return nil, fmt.Errorf("wrong result div op: '%v'", op) } arg.OpDiv = uintptr(v) } if p.Char() == '+' { p.Parse('+') op := p.Ident() v, err := strconv.ParseUint(op, 0, 64) if err != nil { return nil, fmt.Errorf("wrong result add op: '%v'", op) } arg.OpAdd = uintptr(v) } case '&': var typ1 sys.Type switch t1 := typ.(type) { case sys.PtrType: typ1 = t1.Type case sys.VmaType: default: return nil, fmt.Errorf("& arg is not a pointer: %#v", typ) } p.Parse('&') page, off, size, err := parseAddr(p, true) if err != nil { return nil, err } p.Parse('=') inner, err := parseArg(typ1, p, vars) if err != nil { return nil, err } arg = pointerArg(page, off, size, inner) case '(': page, off, _, err := parseAddr(p, false) if err != nil { return nil, err } arg = pageSizeArg(page, off) case '"': p.Parse('"') val := "" if p.Char() != '"' { val = p.Ident() } p.Parse('"') data, err := hex.DecodeString(val) if err != nil { return nil, fmt.Errorf("data arg has bad value '%v'", val) } arg = dataArg(data) case '{': t1, ok := typ.(*sys.StructType) if !ok { return nil, fmt.Errorf("'{' arg is not a struct: %#v", typ) } p.Parse('{') var inner []*Arg for i := 0; p.Char() != '}'; i++ { if i >= len(t1.Fields) { return nil, fmt.Errorf("wrong struct arg count: %v, want %v", i+1, len(t1.Fields)) } fld := t1.Fields[i] if sys.IsPad(fld) { inner = append(inner, constArg(0)) } else { arg, err := parseArg(fld, p, vars) if err != nil { return nil, err } inner = append(inner, arg) if p.Char() != '}' { p.Parse(',') } } } p.Parse('}') if sys.IsPad(t1.Fields[len(t1.Fields)-1]) { inner = append(inner, constArg(0)) } arg = groupArg(inner) case '[': t1, ok := typ.(sys.ArrayType) if !ok { return nil, fmt.Errorf("'[' arg is not an array: %#v", typ) } p.Parse('[') var inner []*Arg for i := 0; p.Char() != ']'; i++ { arg, err := parseArg(t1.Type, p, vars) if err != nil { return nil, err } inner = append(inner, arg) if p.Char() != ']' { p.Parse(',') } } p.Parse(']') arg = groupArg(inner) case '@': t1, ok := typ.(*sys.UnionType) if !ok { return nil, fmt.Errorf("'@' arg is not a union: %#v", typ) } p.Parse('@') name := p.Ident() p.Parse('=') var optType sys.Type for _, t2 := range t1.Options { if name == t2.Name() { optType = t2 break } } if optType == nil { return nil, fmt.Errorf("union arg %v has unknown option: %v", typ.Name(), name) } opt, err := parseArg(optType, p, vars) if err != nil { return nil, err } arg = unionArg(opt, optType) case 'n': p.Parse('n') p.Parse('i') p.Parse('l') if r != "" { return nil, fmt.Errorf("named nil argument") } default: return nil, fmt.Errorf("failed to parse argument at %v (line #%v/%v: %v)", int(p.Char()), p.l, p.i, p.s) } if r != "" { vars[r] = arg } return arg, nil }