Implement returning errors from the scanner

This commit is contained in:
Miek Gieben 2011-12-16 10:06:28 +01:00
parent c6deba77e0
commit 06ae052c32
4 changed files with 75 additions and 57 deletions

2
dns.go
View File

@ -154,7 +154,7 @@ func (s RRset) Ok() bool {
type Exchange struct {
Request *Msg // The question sent.
Reply *Msg // The answer to the question that was sent.
Error error // If something when wrong, this contains the error.
ErrorMsg error // If something when wrong, this contains the error.
}
// DNS resource records.

View File

@ -122,7 +122,7 @@ func TestParse(t *testing.T) {
t.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String())
t.Fail()
} else {
t.Logf("RR is %s", rr.String())
t.Logf("RR is OK: `%s'", rr.String())
}
}
}

View File

@ -61,26 +61,34 @@ type Lex struct {
column int // column in the fil
}
type Token struct {
Rr RR // the scanned resource record
Err *ParseError // when an error occured, this is the specifics
}
// NewRR parses the string s and returns the RR contained in there. If the string
// contains more than one RR, only the first is returned. If an error is detected
// an error is returned.
// that error error is returned.
// If the class is not specified, the IN class is assumed. If the TTL is not
// specified DefaultTtl is assumed.
func NewRR(s string) (RR, error) {
cr := make(chan RR)
t := make(chan Token)
if s[len(s)-1] != '\n' { // We need a closing newline
go ParseZone(strings.NewReader(s+"\n"), cr)
go ParseZone(strings.NewReader(s+"\n"), t)
} else {
go ParseZone(strings.NewReader(s), cr)
go ParseZone(strings.NewReader(s), t)
}
r := <-cr // There are no error send as of yet
return r, nil // Todo: errors
r := <-t
if r.Err != nil {
return nil, r.Err
}
return r.Rr, nil
}
// ParseZone reads a RFC 1035 zone from r. It returns each parsed RR on the
// channel cr. The channel cr is closed by ParseZone when the end of r is reached.
func ParseZone(r io.Reader, cr chan RR) {
defer close(cr)
// ParseZone reads a RFC 1035 zone from r. It returns each parsed RR or on error
// on the channel t. The channel t is closed by ParseZone when the end of r is reached.
func ParseZone(r io.Reader, t chan Token) {
defer close(t)
var s scanner.Scanner
c := make(chan Lex)
s.Init(r)
@ -105,9 +113,9 @@ func ParseZone(r io.Reader, cr chan RR) {
}
switch st {
case _EXPECT_OWNER:
// Set the defaults here
h.Ttl = DefaultTtl
h.Class = ClassINET
// Set the defaults here
h.Ttl = DefaultTtl
h.Class = ClassINET
switch l.value {
case _NEWLINE: // Empty line
st = _EXPECT_OWNER
@ -115,12 +123,14 @@ func ParseZone(r io.Reader, cr chan RR) {
h.Name = l.token
st = _EXPECT_OWNER_BL
default:
fmt.Printf("%s\n", &ParseError{"Error at the start", l})
st = _EXPECT_OWNER
t <- Token{Err: &ParseError{"Error at the start", l}}
return
//st = _EXPECT_OWNER
}
case _EXPECT_OWNER_BL:
if l.value != _BLANK {
fmt.Printf("%s\n", &ParseError{"No blank after owner", l})
t <- Token{Err: &ParseError{"No blank after owner", l}}
return
}
st = _EXPECT_ANY
case _EXPECT_ANY:
@ -131,28 +141,33 @@ func ParseZone(r io.Reader, cr chan RR) {
case _CLASS:
h.Class, ok = Str_class[strings.ToUpper(l.token)]
if !ok {
fmt.Printf("%s\n", &ParseError{"Unknown class", l})
t <- Token{Err: &ParseError{"Unknown class", l}}
return
}
st = _EXPECT_ANY_NOCLASS_BL
case _STRING: // TTL is this case
ttl, ok := strconv.Atoi(l.token)
if ok != nil {
fmt.Printf("%s\n", &ParseError{"Not a TTL", l})
t <- Token{Err: &ParseError{"Not a TTL", l}}
return
} else {
h.Ttl = uint32(ttl)
}
st = _EXPECT_ANY_NOTTL_BL
default:
fmt.Printf("%s\n", &ParseError{"Expecting RR type, TTL or class, not this...", l})
t <- Token{Err: &ParseError{"Expecting RR type, TTL or class, not this...", l}}
return
}
case _EXPECT_ANY_NOCLASS_BL:
if l.value != _BLANK {
fmt.Printf("%s\n", &ParseError{"No blank before NOCLASS", l})
t <- Token{Err: &ParseError{"No blank before NOCLASS", l}}
return
}
st = _EXPECT_ANY_NOCLASS
case _EXPECT_ANY_NOTTL_BL:
if l.value != _BLANK {
fmt.Printf("%s\n", &ParseError{"No blank before NOTTL", l})
t <- Token{Err: &ParseError{"No blank before NOTTL", l}}
return
}
st = _EXPECT_ANY_NOTTL
case _EXPECT_ANY_NOTTL:
@ -160,7 +175,8 @@ func ParseZone(r io.Reader, cr chan RR) {
case _CLASS:
h.Class, ok = Str_class[strings.ToUpper(l.token)]
if !ok {
fmt.Printf("%s\n", &ParseError{"Unknown class", l})
t <- Token{Err: &ParseError{"Unknown class", l}}
return
}
st = _EXPECT_RRTYPE_BL
case _RRTYPE:
@ -172,7 +188,8 @@ func ParseZone(r io.Reader, cr chan RR) {
case _STRING: // TTL
ttl, ok := strconv.Atoi(l.token)
if ok != nil {
fmt.Printf("%s\n", &ParseError{"Not a TTL", l})
t <- Token{Err: &ParseError{"Not a TTL", l}}
return
} else {
h.Ttl = uint32(ttl)
}
@ -181,25 +198,30 @@ func ParseZone(r io.Reader, cr chan RR) {
h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)]
st = _EXPECT_RDATA
default:
fmt.Printf("%s\n", &ParseError{"Expecting RR type or TTL, not this...", l})
t <- Token{Err: &ParseError{"Expecting RR type or TTL, not this...", l}}
return
}
case _EXPECT_RRTYPE_BL:
if l.value != _BLANK {
fmt.Printf("%s\n", &ParseError{"No blank after", l})
t <- Token{Err: &ParseError{"No blank after", l}}
return
}
st = _EXPECT_RRTYPE
case _EXPECT_RRTYPE:
if l.value != _RRTYPE {
fmt.Printf("%s\n", &ParseError{"Unknown RR type", l})
t <- Token{Err: &ParseError{"Unknown RR type", l}}
return
}
h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)]
st = _EXPECT_RDATA
case _EXPECT_RDATA:
// I could save my token here...? l
r, e := setRR(h, c)
if e != nil {
fmt.Printf("%v\n", e)
t <- Token{Err: e}
return
}
cr <- r
t <- Token{Rr: r}
st = _EXPECT_OWNER
}
}
@ -330,7 +352,7 @@ func zlexer(s scanner.Scanner, c chan Lex) {
}
brace--
if brace < 0 {
fmt.Printf("Error\n")
fmt.Printf("%s\n", &ParseError{"Extra closing brace", l})
}
default:
if commt {
@ -341,6 +363,4 @@ func zlexer(s scanner.Scanner, c chan Lex) {
}
tok = s.Scan()
}
// Hmm
// fmt.Printf("XX %s XXX", str)
}

View File

@ -11,13 +11,11 @@ import (
// All data from the channel c is either _STRING or _BLANK.
// After the rdata there may come 1 _BLANK and then a _NEWLINE
// or immediately a _NEWLINE. If this is not the case we flag
// an error: garbage after rdata.
// an *ParseError: garbage after rdata.
func setRR(h RR_Header, c chan Lex) (RR, error) {
var (
r RR
e error
)
func setRR(h RR_Header, c chan Lex) (RR, *ParseError) {
var r RR
e := new(ParseError)
switch h.Rrtype {
case TypeA:
r, e = setA(h, c)
@ -87,7 +85,7 @@ func setRR(h RR_Header, c chan Lex) (RR, error) {
return r, e
}
func slurpRemainder(c chan Lex) error {
func slurpRemainder(c chan Lex) *ParseError {
l := <-c
if DEBUG {
fmt.Printf("%\v", l)
@ -112,7 +110,7 @@ func slurpRemainder(c chan Lex) error {
return nil
}
func setA(h RR_Header, c chan Lex) (RR, error) {
func setA(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_A)
rr.Hdr = h
@ -124,7 +122,7 @@ func setA(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setAAAA(h RR_Header, c chan Lex) (RR, error) {
func setAAAA(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_AAAA)
rr.Hdr = h
@ -136,7 +134,7 @@ func setAAAA(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setNS(h RR_Header, c chan Lex) (RR, error) {
func setNS(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_NS)
rr.Hdr = h
@ -148,7 +146,7 @@ func setNS(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setMX(h RR_Header, c chan Lex) (RR, error) {
func setMX(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_MX)
rr.Hdr = h
@ -167,7 +165,7 @@ func setMX(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setCNAME(h RR_Header, c chan Lex) (RR, error) {
func setCNAME(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_CNAME)
rr.Hdr = h
@ -179,7 +177,7 @@ func setCNAME(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setSOA(h RR_Header, c chan Lex) (RR, error) {
func setSOA(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_SOA)
rr.Hdr = h
@ -198,7 +196,7 @@ func setSOA(h RR_Header, c chan Lex) (RR, error) {
<-c // _BLANK
var j int
var e error
var e error
for i := 0; i < 5; i++ {
l = <-c
if j, e = strconv.Atoi(l.token); e != nil {
@ -221,7 +219,7 @@ func setSOA(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setRRSIG(h RR_Header, c chan Lex) (RR, error) {
func setRRSIG(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_RRSIG)
rr.Hdr = h
l := <-c
@ -297,7 +295,7 @@ func setRRSIG(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setNSEC(h RR_Header, c chan Lex) (RR, error) {
func setNSEC(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_NSEC)
rr.Hdr = h
@ -328,7 +326,7 @@ func setNSEC(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setNSEC3(h RR_Header, c chan Lex) (RR, error) {
func setNSEC3(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_NSEC3)
rr.Hdr = h
@ -382,7 +380,7 @@ func setNSEC3(h RR_Header, c chan Lex) (RR, error) {
return rr, nil
}
func setDNSKEY(h RR_Header, c chan Lex) (RR, error) {
func setDNSKEY(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_DNSKEY)
rr.Hdr = h
@ -424,7 +422,7 @@ func setDNSKEY(h RR_Header, c chan Lex) (RR, error) {
}
/*
func setNSEC3PARAM(h RR_Header, c chan Lex) (RR, error) {
func setNSEC3PARAM(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_NSEC3PARAM)
rr.Hdr = h
rdf := fields(data[mark:p], 4)
@ -449,7 +447,7 @@ func setNSEC3PARAM(h RR_Header, c chan Lex) (RR, error) {
}
*/
func setTXT(h RR_Header, c chan Lex) (RR, error) {
func setTXT(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_TXT)
rr.Hdr = h
@ -472,7 +470,7 @@ func setTXT(h RR_Header, c chan Lex) (RR, error) {
}
/*
func setDS(h RR_Header, c chan Lex) (RR, error) {
func setDS(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_DS)
rr.Hdr = h
action setDS {
@ -503,7 +501,7 @@ func setDS(h RR_Header, c chan Lex) (RR, error) {
zp.RR <- rr
}
func setCNAME(h RR_Header, c chan Lex) (RR, error) {
func setCNAME(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_CNAME)
rr.Hdr = h
action setDLV {
@ -534,7 +532,7 @@ func setCNAME(h RR_Header, c chan Lex) (RR, error) {
zp.RR <- rr
}
func setCNAME(h RR_Header, c chan Lex) (RR, error) {
func setCNAME(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_CNAME)
rr.Hdr = h
action setTA {
@ -566,7 +564,7 @@ func setCNAME(h RR_Header, c chan Lex) (RR, error) {
}
func setSSHFP(h RR_Header, c chan Lex) (RR, error) {
func setSSHFP(h RR_Header, c chan Lex) (RR, *ParseError) {
rr := new(RR_CNAME)
rr.Hdr = h
var (