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 { type Exchange struct {
Request *Msg // The question sent. Request *Msg // The question sent.
Reply *Msg // The answer to the question that was 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. // 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.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String())
t.Fail() t.Fail()
} else { } 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 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 // 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 // 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 // If the class is not specified, the IN class is assumed. If the TTL is not
// specified DefaultTtl is assumed. // specified DefaultTtl is assumed.
func NewRR(s string) (RR, error) { 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 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 { } else {
go ParseZone(strings.NewReader(s), cr) go ParseZone(strings.NewReader(s), t)
} }
r := <-cr // There are no error send as of yet r := <-t
return r, nil // Todo: errors 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 // ParseZone reads a RFC 1035 zone from r. It returns each parsed RR or on error
// channel cr. The channel cr is closed by ParseZone when the end of r is reached. // on the channel t. The channel t is closed by ParseZone when the end of r is reached.
func ParseZone(r io.Reader, cr chan RR) { func ParseZone(r io.Reader, t chan Token) {
defer close(cr) defer close(t)
var s scanner.Scanner var s scanner.Scanner
c := make(chan Lex) c := make(chan Lex)
s.Init(r) s.Init(r)
@ -105,9 +113,9 @@ func ParseZone(r io.Reader, cr chan RR) {
} }
switch st { switch st {
case _EXPECT_OWNER: case _EXPECT_OWNER:
// Set the defaults here // Set the defaults here
h.Ttl = DefaultTtl h.Ttl = DefaultTtl
h.Class = ClassINET h.Class = ClassINET
switch l.value { switch l.value {
case _NEWLINE: // Empty line case _NEWLINE: // Empty line
st = _EXPECT_OWNER st = _EXPECT_OWNER
@ -115,12 +123,14 @@ func ParseZone(r io.Reader, cr chan RR) {
h.Name = l.token h.Name = l.token
st = _EXPECT_OWNER_BL st = _EXPECT_OWNER_BL
default: default:
fmt.Printf("%s\n", &ParseError{"Error at the start", l}) t <- Token{Err: &ParseError{"Error at the start", l}}
st = _EXPECT_OWNER return
//st = _EXPECT_OWNER
} }
case _EXPECT_OWNER_BL: case _EXPECT_OWNER_BL:
if l.value != _BLANK { 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 st = _EXPECT_ANY
case _EXPECT_ANY: case _EXPECT_ANY:
@ -131,28 +141,33 @@ func ParseZone(r io.Reader, cr chan RR) {
case _CLASS: case _CLASS:
h.Class, ok = Str_class[strings.ToUpper(l.token)] h.Class, ok = Str_class[strings.ToUpper(l.token)]
if !ok { if !ok {
fmt.Printf("%s\n", &ParseError{"Unknown class", l}) t <- Token{Err: &ParseError{"Unknown class", l}}
return
} }
st = _EXPECT_ANY_NOCLASS_BL st = _EXPECT_ANY_NOCLASS_BL
case _STRING: // TTL is this case case _STRING: // TTL is this case
ttl, ok := strconv.Atoi(l.token) ttl, ok := strconv.Atoi(l.token)
if ok != nil { if ok != nil {
fmt.Printf("%s\n", &ParseError{"Not a TTL", l}) t <- Token{Err: &ParseError{"Not a TTL", l}}
return
} else { } else {
h.Ttl = uint32(ttl) h.Ttl = uint32(ttl)
} }
st = _EXPECT_ANY_NOTTL_BL st = _EXPECT_ANY_NOTTL_BL
default: 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: case _EXPECT_ANY_NOCLASS_BL:
if l.value != _BLANK { 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 st = _EXPECT_ANY_NOCLASS
case _EXPECT_ANY_NOTTL_BL: case _EXPECT_ANY_NOTTL_BL:
if l.value != _BLANK { 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 st = _EXPECT_ANY_NOTTL
case _EXPECT_ANY_NOTTL: case _EXPECT_ANY_NOTTL:
@ -160,7 +175,8 @@ func ParseZone(r io.Reader, cr chan RR) {
case _CLASS: case _CLASS:
h.Class, ok = Str_class[strings.ToUpper(l.token)] h.Class, ok = Str_class[strings.ToUpper(l.token)]
if !ok { if !ok {
fmt.Printf("%s\n", &ParseError{"Unknown class", l}) t <- Token{Err: &ParseError{"Unknown class", l}}
return
} }
st = _EXPECT_RRTYPE_BL st = _EXPECT_RRTYPE_BL
case _RRTYPE: case _RRTYPE:
@ -172,7 +188,8 @@ func ParseZone(r io.Reader, cr chan RR) {
case _STRING: // TTL case _STRING: // TTL
ttl, ok := strconv.Atoi(l.token) ttl, ok := strconv.Atoi(l.token)
if ok != nil { if ok != nil {
fmt.Printf("%s\n", &ParseError{"Not a TTL", l}) t <- Token{Err: &ParseError{"Not a TTL", l}}
return
} else { } else {
h.Ttl = uint32(ttl) h.Ttl = uint32(ttl)
} }
@ -181,25 +198,30 @@ func ParseZone(r io.Reader, cr chan RR) {
h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)] h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)]
st = _EXPECT_RDATA st = _EXPECT_RDATA
default: 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: case _EXPECT_RRTYPE_BL:
if l.value != _BLANK { 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 st = _EXPECT_RRTYPE
case _EXPECT_RRTYPE: case _EXPECT_RRTYPE:
if l.value != _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)] h.Rrtype, _ = Str_rr[strings.ToUpper(l.token)]
st = _EXPECT_RDATA st = _EXPECT_RDATA
case _EXPECT_RDATA: case _EXPECT_RDATA:
// I could save my token here...? l
r, e := setRR(h, c) r, e := setRR(h, c)
if e != nil { if e != nil {
fmt.Printf("%v\n", e) t <- Token{Err: e}
return
} }
cr <- r t <- Token{Rr: r}
st = _EXPECT_OWNER st = _EXPECT_OWNER
} }
} }
@ -330,7 +352,7 @@ func zlexer(s scanner.Scanner, c chan Lex) {
} }
brace-- brace--
if brace < 0 { if brace < 0 {
fmt.Printf("Error\n") fmt.Printf("%s\n", &ParseError{"Extra closing brace", l})
} }
default: default:
if commt { if commt {
@ -341,6 +363,4 @@ func zlexer(s scanner.Scanner, c chan Lex) {
} }
tok = s.Scan() 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. // All data from the channel c is either _STRING or _BLANK.
// After the rdata there may come 1 _BLANK and then a _NEWLINE // After the rdata there may come 1 _BLANK and then a _NEWLINE
// or immediately a _NEWLINE. If this is not the case we flag // 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) { func setRR(h RR_Header, c chan Lex) (RR, *ParseError) {
var ( var r RR
r RR e := new(ParseError)
e error
)
switch h.Rrtype { switch h.Rrtype {
case TypeA: case TypeA:
r, e = setA(h, c) r, e = setA(h, c)
@ -87,7 +85,7 @@ func setRR(h RR_Header, c chan Lex) (RR, error) {
return r, e return r, e
} }
func slurpRemainder(c chan Lex) error { func slurpRemainder(c chan Lex) *ParseError {
l := <-c l := <-c
if DEBUG { if DEBUG {
fmt.Printf("%\v", l) fmt.Printf("%\v", l)
@ -112,7 +110,7 @@ func slurpRemainder(c chan Lex) error {
return nil 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 := new(RR_A)
rr.Hdr = h rr.Hdr = h
@ -124,7 +122,7 @@ func setA(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_AAAA)
rr.Hdr = h rr.Hdr = h
@ -136,7 +134,7 @@ func setAAAA(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_NS)
rr.Hdr = h rr.Hdr = h
@ -148,7 +146,7 @@ func setNS(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_MX)
rr.Hdr = h rr.Hdr = h
@ -167,7 +165,7 @@ func setMX(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_CNAME)
rr.Hdr = h rr.Hdr = h
@ -179,7 +177,7 @@ func setCNAME(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_SOA)
rr.Hdr = h rr.Hdr = h
@ -198,7 +196,7 @@ func setSOA(h RR_Header, c chan Lex) (RR, error) {
<-c // _BLANK <-c // _BLANK
var j int var j int
var e error var e error
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
l = <-c l = <-c
if j, e = strconv.Atoi(l.token); e != nil { 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 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 := new(RR_RRSIG)
rr.Hdr = h rr.Hdr = h
l := <-c l := <-c
@ -297,7 +295,7 @@ func setRRSIG(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_NSEC)
rr.Hdr = h rr.Hdr = h
@ -328,7 +326,7 @@ func setNSEC(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_NSEC3)
rr.Hdr = h rr.Hdr = h
@ -382,7 +380,7 @@ func setNSEC3(h RR_Header, c chan Lex) (RR, error) {
return rr, nil 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 := new(RR_DNSKEY)
rr.Hdr = h 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 := new(RR_NSEC3PARAM)
rr.Hdr = h rr.Hdr = h
rdf := fields(data[mark:p], 4) 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 := new(RR_TXT)
rr.Hdr = h 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 := new(RR_DS)
rr.Hdr = h rr.Hdr = h
action setDS { action setDS {
@ -503,7 +501,7 @@ func setDS(h RR_Header, c chan Lex) (RR, error) {
zp.RR <- rr 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 := new(RR_CNAME)
rr.Hdr = h rr.Hdr = h
action setDLV { action setDLV {
@ -534,7 +532,7 @@ func setCNAME(h RR_Header, c chan Lex) (RR, error) {
zp.RR <- rr 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 := new(RR_CNAME)
rr.Hdr = h rr.Hdr = h
action setTA { 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 := new(RR_CNAME)
rr.Hdr = h rr.Hdr = h
var ( var (