1#!/usr/bin/env python 2# Copyright (c) 2007, Secure64 Software Corporation 3# 4# Permission is hereby granted, free of charge, to any person obtaining a copy 5# of this software and associated documentation files (the "Software"), to deal 6# in the Software without restriction, including without limitation the rights 7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8# copies of the Software, and to permit persons to whom the Software is 9# furnished to do so, subject to the following conditions: 10# 11# The above copyright notice and this permission notice shall be included in 12# all copies or substantial portions of the Software. 13# 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20# THE SOFTWARE. 21# 22# 23# 24# class to tokenize a named.conf file 25# 26# 27 28T_KEYWORD = 0 29T_STRING = 1 30T_LBRACE = 2 31T_RBRACE = 3 32T_SEMI = 4 33T_COMMA = 5 34T_QUAD = 6 35T_COMMENT = 7 36T_NAME = 8 37T_EOF = 9 38T_LPAREN = 10 39T_RPAREN = 11 40 41NAMED_KEYWORDS = [ 'algorithm', 'allow-notify', 'allow-recursion', 42 'allow-transfer', 'also-notify', 43 'category', 'channel', 'check-names', 'controls', 44 'coresize', 45 'directory', 'dump-file', 46 'file', 47 'IN', 'in', 'include', 48 'key', 'keys', 49 'logging', 50 'masters', 51 'options', 52 'pid-file', 'print-time', 53 'recursive-clients', 54 'secret', 'severity', 'statistics-file', 'syslog', 55 'transfer-format', 'type', 56 'version', 'versions', 57 'zone', 58 ] 59 60class Tokenizer: 61 62 def __init__(self, fname): 63 infile = file(fname) 64 self.data = ''.join(infile.readlines()) 65 self.curpos = 0 66 self.lastpos = len(self.data) 67 self.line = 1 68 return 69 70 def get(self): 71 tok = '' 72 done = False 73 while not done: 74 if self.curpos >= self.lastpos: 75 return (T_EOF, None, self.line) 76 c = self.data[self.curpos] 77 if c == '\n': 78 self.line += 1 79 if c.isspace(): 80 self.curpos += 1 81 continue 82 elif c == '{': 83 self.curpos += 1 84 return (T_LBRACE, c, self.line) 85 elif c == '}': 86 self.curpos += 1 87 return (T_RBRACE, c, self.line) 88 elif c == '(': 89 self.curpos += 1 90 return (T_LPAREN, c, self.line) 91 elif c == ')': 92 self.curpos += 1 93 return (T_RPAREN, c, self.line) 94 elif c == ';': 95 self.curpos += 1 96 return (T_SEMI, c, self.line) 97 elif c == '#': 98 while c != '\n': 99 tok += c 100 self.curpos += 1 101 c = self.data[self.curpos] 102 self.curpos += 1 103 if c == '\n': 104 self.line += 1 105 return (T_COMMENT, tok, self.line) 106 elif c == '"': 107 tok += c 108 self.curpos += 1 109 c = self.data[self.curpos] 110 while c != '"': 111 tok += c 112 self.curpos += 1 113 c = self.data[self.curpos] 114 tok += c 115 self.curpos += 1 116 return (T_STRING, tok, self.line) 117 elif c == '/' and self.data[self.curpos+1] == '/': 118 while c != '\n': 119 tok += c 120 self.curpos += 1 121 c = self.data[self.curpos] 122 if c == '\n': 123 self.line += 1 124 self.curpos += 1 125 return (T_COMMENT, tok, self.line) 126 elif c == '/' and self.data[self.curpos+1] == '*': 127 cmtDone = False 128 tok += c 129 tok += self.data[self.curpos+1] 130 self.curpos += 2 131 c = self.data[self.curpos] 132 while not cmtDone: 133 if c == '*' and self.data[self.curpos+1] == '/': 134 tok += c 135 tok += self.data[self.curpos+1] 136 self.curpos += 2 137 return (T_COMMENT, tok, self.line) 138 else: 139 tok += c 140 if c == '\n': 141 self.line += 1 142 self.curpos +=1 143 c = self.data[self.curpos] 144 return (T_COMMENT, tok, self.line) 145 elif c.isdigit(): 146 tok += c 147 self.curpos += 1 148 c = self.data[self.curpos] 149 while c.isdigit() or c == '.' or c == '/': 150 tok += c 151 self.curpos += 1 152 c = self.data[self.curpos] 153 return (T_QUAD, tok, self.line) 154 else: 155 while c.isalnum() or c == '_' or c == '-' or c == '.': 156 tok += c 157 self.curpos += 1 158 c = self.data[self.curpos] 159 if tok in NAMED_KEYWORDS: 160 return (T_KEYWORD, tok, self.line) 161 else: 162 return (T_NAME, tok, self.line) 163 164 return 165 166 def dump(self): 167 print 'Tokenizer raw data:' 168 print 'cur, last: %d, %d' % (self.curpos, self.lastpos) 169 print self.data 170 return 171 172