2 ##########################################################################
4 # Copyright 2010 VMware, Inc.
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 ##########################################################################/
35 def __init__(self, stream):
40 """Base class for parsers that read line-based formats."""
42 def __init__(self, stream):
50 raise NotImplementedError
53 line = self._stream.readline()
57 self._line = line.rstrip('\r\n')
60 assert self._line is not None
64 assert self._line is not None
70 assert self._line is not None
73 def skip_whitespace(self):
74 while not self.eof() and self.match_whitespace() or self.match_comment():
77 def match_whitespace(self):
78 line = self.lookahead()
79 return not line.strip()
81 def match_comment(self):
85 class TypemapParser(LineParser):
89 self.skip_whitespace()
92 fields = [field.strip() for field in line.split(',')]
95 self.skip_whitespace()
99 def match_comment(self):
100 line = self.lookahead()
101 return line.startswith('#')
104 class SpecParser(LineParser):
106 property_re = re.compile(r'^\w+:')
107 prototype_re = re.compile(r'^(\w+)\((.*)\)$')
109 def __init__(self, stream, prefix='', typemap = None):
110 LineParser.__init__(self, stream)
114 self.typemap = typemap
119 self.skip_whitespace()
120 while not self.eof():
121 line = self.lookahead()
122 if self.property_re.match(line):
123 self.parse_property()
124 elif self.prototype_re.match(line):
125 self.parse_prototype()
128 self.skip_whitespace()
130 def parse_property(self):
131 line = self.consume()
132 name, value = line.split(':', 1)
133 if name == 'category':
134 values = value.split()
135 #self.prefix = values[0]
137 get_function_re = re.compile(r'^Get[A-Z]\w+')
139 def parse_prototype(self):
140 line = self.consume()
141 mo = self.prototype_re.match(line)
142 function_name, arg_names = mo.groups()
143 arg_names = [arg_name.strip() for arg_name in arg_names.split(',') if arg_name.strip()]
148 line = self.lookahead()
149 while line.startswith('\t'):
150 fields = line.split(None, 2)
151 if fields[0] == 'return':
152 ret_type = self.parse_type(fields[1])
153 elif fields[0] == 'param':
154 arg_name, arg_type = fields[1:3]
155 arg_types[fields[1]] = self.parse_arg(arg_name, arg_type)
156 elif fields[0] == 'category':
161 line = self.lookahead()
163 args = [arg_types[arg_name] for arg_name in arg_names]
165 if category is not None:
166 if category == self.prefix:
167 category = self.prefix.upper()
169 category = self.prefix.upper() + '_' + category
170 if category != self.category:
171 if self.category is not None:
173 print ' # %s' % category
174 self.category = category
176 if self.prefix == 'wgl':
177 constructor = 'StdFunction'
179 constructor = 'glFunction'
181 if self.get_function_re.match(function_name):
182 extra += ', sideeffects=False'
183 print ' %s(%s, "%s%s", [%s]%s),' % (constructor, ret_type, self.prefix, function_name, ', '.join(args), extra)
185 array_re = re.compile(r'^array\s+\[(.*)\]$')
187 def parse_arg(self, arg_name, arg_type):
188 base_type, inout, kind = arg_type.split(' ', 2)
189 base_type = self.parse_type(base_type)
193 elif kind == 'reference':
194 arg_type = 'Pointer(%s)' % base_type
196 arg_type = 'Const(%s)' % arg_type
197 elif kind.startswith("array"):
198 mo = self.array_re.match(kind)
201 arg_type = 'Array(%s, "%s")' % (base_type, length)
203 arg_type = 'OpaquePointer(%s)' % base_type
205 arg_type = 'Const(%s)' % arg_type
209 arg = '(%s, "%s")' % (arg_type, arg_name)
220 def parse_type(self, type):
221 type = self.typemap.get(type, type)
222 type = self._typemap.get(type, type)
225 def match_comment(self):
226 line = self.lookahead()
227 return line.startswith('#')
233 parser = TypemapParser(open(sys.argv[2], 'rt'))
234 typemap = parser.parse()
236 for arg in sys.argv[3:]:
237 parser = SpecParser(open(arg, 'rt'), prefix=prefix, typemap=typemap)
241 if __name__ == '__main__':