package dns
import (
"bytes"
"fmt"
"io"
"strconv"
"strings"
)
func (zp *ZoneParser ) generate (l lex ) (RR , bool ) {
token := l .token
step := int64 (1 )
if i := strings .IndexByte (token , '/' ); i >= 0 {
if i +1 == len (token ) {
return zp .setParseError ("bad step in $GENERATE range" , l )
}
s , err := strconv .ParseInt (token [i +1 :], 10 , 64 )
if err != nil || s <= 0 {
return zp .setParseError ("bad step in $GENERATE range" , l )
}
step = s
token = token [:i ]
}
startStr , endStr , ok := strings .Cut (token , "-" )
if !ok {
return zp .setParseError ("bad start-stop in $GENERATE range" , l )
}
start , err := strconv .ParseInt (startStr , 10 , 64 )
if err != nil {
return zp .setParseError ("bad start in $GENERATE range" , l )
}
end , err := strconv .ParseInt (endStr , 10 , 64 )
if err != nil {
return zp .setParseError ("bad stop in $GENERATE range" , l )
}
if end < 0 || start < 0 || end < start || (end -start )/step > 65535 {
return zp .setParseError ("bad range in $GENERATE range" , l )
}
l , ok = zp .c .Next ()
if !ok || l .value != zBlank {
return zp .setParseError ("garbage after $GENERATE range" , l )
}
var s string
for l , ok := zp .c .Next (); ok ; l , ok = zp .c .Next () {
if l .err {
return zp .setParseError ("bad data in $GENERATE directive" , l )
}
if l .value == zNewline {
break
}
s += l .token
}
r := &generateReader {
s : s ,
cur : start ,
start : start ,
end : end ,
step : step ,
file : zp .file ,
lex : &l ,
}
zp .sub = NewZoneParser (r , zp .origin , zp .file )
zp .sub .includeDepth , zp .sub .includeAllowed = zp .includeDepth , zp .includeAllowed
zp .sub .generateDisallowed = true
zp .sub .SetDefaultTTL (defaultTtl )
return zp .subNext ()
}
type generateReader struct {
s string
si int
cur int64
start int64
end int64
step int64
mod bytes .Buffer
escape bool
eof bool
file string
lex *lex
}
func (r *generateReader ) parseError (msg string , end int ) *ParseError {
r .eof = true
l := *r .lex
l .token = r .s [r .si -1 : end ]
l .column += r .si
return &ParseError {file : r .file , err : msg , lex : l }
}
func (r *generateReader ) Read (p []byte ) (int , error ) {
panic ("not implemented" )
}
func (r *generateReader ) ReadByte () (byte , error ) {
if r .eof {
return 0 , io .EOF
}
if r .mod .Len () > 0 {
return r .mod .ReadByte ()
}
if r .si >= len (r .s ) {
r .si = 0
r .cur += r .step
r .eof = r .cur > r .end || r .cur < 0
return '\n' , nil
}
si := r .si
r .si ++
switch r .s [si ] {
case '\\' :
if r .escape {
r .escape = false
return '\\' , nil
}
r .escape = true
return r .ReadByte ()
case '$' :
if r .escape {
r .escape = false
return '$' , nil
}
mod := "%d"
if si >= len (r .s )-1 {
fmt .Fprintf (&r .mod , mod , r .cur )
return r .mod .ReadByte ()
}
if r .s [si +1 ] == '$' {
r .si ++
return '$' , nil
}
var offset int64
if r .s [si +1 ] == '{' {
sep := strings .Index (r .s [si +2 :], "}" )
if sep < 0 {
return 0 , r .parseError ("bad modifier in $GENERATE" , len (r .s ))
}
var errMsg string
mod , offset , errMsg = modToPrintf (r .s [si +2 : si +2 +sep ])
if errMsg != "" {
return 0 , r .parseError (errMsg , si +3 +sep )
}
if r .start +offset < 0 || r .end +offset > 1 <<31 -1 {
return 0 , r .parseError ("bad offset in $GENERATE" , si +3 +sep )
}
r .si += 2 + sep
}
fmt .Fprintf (&r .mod , mod , r .cur +offset )
return r .mod .ReadByte ()
default :
if r .escape {
r .escape = false
return r .ReadByte ()
}
return r .s [si ], nil
}
}
func modToPrintf(s string ) (string , int64 , string ) {
offStr , s , ok0 := strings .Cut (s , "," )
widthStr , s , ok1 := strings .Cut (s , "," )
base , _ , ok2 := strings .Cut (s , "," )
if !ok0 {
widthStr = "0"
}
if !ok1 {
base = "d"
}
if ok2 {
return "" , 0 , "bad modifier in $GENERATE"
}
switch base {
case "o" , "d" , "x" , "X" :
default :
return "" , 0 , "bad base in $GENERATE"
}
offset , err := strconv .ParseInt (offStr , 10 , 64 )
if err != nil {
return "" , 0 , "bad offset in $GENERATE"
}
width , err := strconv .ParseUint (widthStr , 10 , 8 )
if err != nil {
return "" , 0 , "bad width in $GENERATE"
}
if width == 0 {
return "%" + base , offset , ""
}
return "%0" + widthStr + base , offset , ""
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .