[svn] commit: r908 - /experiments/each-zoneload/master.py

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Feb 22 05:49:59 UTC 2010


Author: each
Date: Mon Feb 22 05:49:59 2010
New Revision: 908

Log:
add support for $INCLUDE

Modified:
    experiments/each-zoneload/master.py

Modified: experiments/each-zoneload/master.py
==============================================================================
--- experiments/each-zoneload/master.py (original)
+++ experiments/each-zoneload/master.py Mon Feb 22 05:49:59 2010
@@ -4,7 +4,7 @@
 #########################################################################
 # define exceptions
 #########################################################################
-class ParseError(Exception):
+class MasterFileError(Exception):
     def __init__(self, value):
         self.value = value
     def __str__(self):
@@ -19,10 +19,10 @@
 defclass = 'IN'
 
 #########################################################################
-# cleanup: removes excess content from zone files, including comments
+# cleanup: removes excess content from zone file data, including comments
 # and extra whitespace
 # input:
-#   a line of text
+#   line of text
 # returns:
 #   the same line, with comments removed, leading and trailing
 #   whitespace removed, and all other whitespace compressed to
@@ -149,12 +149,12 @@
 # returns:
 #   int
 # throws:
-#   ParseError
+#   MasterFileError
 #########################################################################
 def parse_ttl(s):
     m = re.match('([0-9]+)(.*)', s)
     if not m:
-        raise ParseError('Invalid TTL: ' + s)
+        raise MasterFileError('Invalid TTL: ' + s)
     ttl, suffix = int(m.group(1)), m.group(2)
     if suffix.lower() == 'w':
         ttl *= 604800
@@ -167,24 +167,24 @@
     return ttl
 
 #########################################################################
-# directive: handle $ORIGIN, $TTL, $INCLUDE and $GENERATE directives
+# directive: handle $ORIGIN, $TTL and $GENERATE directives
 # (currently only $ORIGIN and $TTL are implemented)
 # input:
 #   a line from a zone file
 # returns:
 #   a boolean indicating whether a directive was found
 # throws:
-#   ParseError
+#   MasterFileError
 #########################################################################
 def directive(s):
     global origin, defttl, maxttl
-    first, xx, more = s.partition(' ')
-    second, xx, more = more.partition(' ')
+    first, more = pop(s)
+    second, more = pop(more)
     if re.match('\$origin', first, re.I):
         if not isname(second):
-            raise ParseError('Invalid $ORIGIN')
+            raise MasterFileError('Invalid $ORIGIN')
         if more:
-            raise ParseError('Invalid $ORIGIN')
+            raise MasterFileError('Invalid $ORIGIN')
         if second[-1] == '.':
             origin = second
         else:
@@ -192,19 +192,36 @@
         return True
     elif re.match('\$ttl', first, re.I):
         if not isttl(second):
-            raise ParseError('Invalid $TTL: ' + second)
+            raise MasterFileError('Invalid $TTL: ' + second)
         if more:
-            raise ParseError('Invalid $TTL statement')
+            raise MasterFileError('Invalid $TTL statement')
         defttl = parse_ttl(second)
         if defttl > maxttl:
-            raise ParseError('TTL too high: ' + second)
-        return True
-    elif re.match('\$include', first, re.I):
-        raise ParseError('$INCLUDE not yet implemented')
+            raise MasterFileError('TTL too high: ' + second)
+        return True
     elif re.match('\$generate', first, re.I):
-        raise ParseError('$GENERATE not yet implemented')
-    else:
-        return False
+        raise MasterFileError('$GENERATE not yet implemented')
+    else:
+        return False
+
+#########################################################################
+# include: handle $INCLUDE directives
+# input:
+#   a line from a zone file
+# returns:
+#   the parsed output of the included file, if any, or an empty array
+# throws:
+#   MasterFileError
+#########################################################################
+filename=re.compile('[\"\']*([^\'\"]+)[\"\']*')
+def include(s):
+    global origin, defttl, maxttl
+    first, rest = pop(s)
+    if re.match('\$include', first, re.I):
+        m = filename.match(rest)
+        if m:
+            file = m.group(1)
+            return parse(file)
 
 #########################################################################
 # four: try parsing on the assumption that the RR type is specified in
@@ -215,7 +232,7 @@
 # returns:
 #   empty list if parse failed, else name, ttl, class, type, rdata
 # throws:
-#   ParseError
+#   MasterFileError
 #########################################################################
 def four(record, curname):
     ret = ''
@@ -237,7 +254,7 @@
 # returns:
 #   empty list if parse failed, else name, ttl, class, type, rdata
 # throws:
-#   ParseError
+#   MasterFileError
 #########################################################################
 def three(record, curname):
     global defttl, defclass
@@ -259,7 +276,7 @@
             ttl = parse_ttl(list[1])
             name = curname
         else:
-            raise ParseError("Cannot parse RR: " + record)
+            raise MasterFileError("Cannot parse RR: " + record)
 
         rrtype = list[2]
         rdata = ' '.join(list[3:])
@@ -274,7 +291,7 @@
 # returns:
 #   empty list if parse failed, else name, ttl, class, type, rdata
 # throws:
-#   ParseError
+#   MasterFileError
 #########################################################################
 def two(record, curname):
     global defttl, defclass
@@ -286,7 +303,7 @@
         if isname(list[0]):
             name = list[0]
         else:
-            raise ParseError("Cannot parse RR: " + record)
+            raise MasterFileError("Cannot parse RR: " + record)
 
         ttl = defttl
         rrclass = defclass
@@ -296,10 +313,10 @@
     return ret
 
 #########################################################################
-# parse_zonefile: parse a zone master file and return it as an array of
+# parse: parse a zone master file and return it as an array of
 # tuples
 #########################################################################
-def parse_zonefile(file):
+def parse(file):
     global defttl, defclass
     data = open(file).read().splitlines()
     zone = []
@@ -309,6 +326,11 @@
         if directive(record):
             continue;
 
+        incl = include(record)
+        if incl:
+            zone += incl
+            continue
+    
         first = record.split()[0]
         if first == '@':
             name = origin
@@ -328,19 +350,19 @@
                 result = name, defttl, defclass, first, rdata
 
         if not result:
-            raise ParseError("Cannot parse RR: " + record)
+            raise MasterFileError("Cannot parse RR: " + record)
 
         name, ttl, rrclass, rrtype, rdata = result
         if name[-1] != '.':
             name += '.' + origin
 
         if rrclass.upper() != 'IN':
-            raise ParseError("CH and HS zones not supported")
+            raise MasterFileError("CH and HS zones not supported")
 
         # add origin to rdata if necessary
         if rrtype.lower() in ('cname', 'dname', 'ns'):
             if not isname(rdata):
-                raise ParseError("Invalid " + rrtype + ": " + rdata)
+                raise MasterFileError("Invalid " + rrtype + ": " + rdata)
             if rdata[-1] != '.':
                 rdata += '.' + origin
 
@@ -354,7 +376,7 @@
 #########################################################################
 def main():
     print ('---------------------')
-    zone = parse_zonefile('testfile')
+    zone = parse('testfile')
     for name, ttl, rrclass, rrtype, rdata in zone:
         print ('name: ' + name)
         print ('ttl: ' + str(ttl))




More information about the bind10-changes mailing list