2 ##########################################################################
4 # Copyright 2011 Jose Fonseca
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 ##########################################################################/
28 '''Script to parse C declarations and spew API definitions.
39 token_re = re.compile(r'(\w+|\s+|.)')
41 multi_comment_re = re.compile(r'/\*.*?\*/', flags = re.DOTALL)
42 single_comment_re = re.compile(r'//.*',)
47 def has_side_effects(self, name):
51 s = self.multi_comment_re.sub('', s)
52 s = self.single_comment_re.sub('', s)
53 self.tokens = self.token_re.split(s)
54 self.tokens = [token for token in self.tokens if self.filter_token(token)]
57 #print self.tokens[0:10]
58 self.parse_declaration()
60 def filter_token(self, token):
61 if not token or token.isspace():
63 if token.startswith('AVAILABLE_') or token.startswith('DEPRECATED_'):
69 def parse_declaration(self):
70 if self.tokens[0] == 'mask':
71 self.parse_value('mask', 'Flags')
72 elif self.tokens[0] == 'value':
73 self.parse_value('value', 'FakeEnum')
74 elif self.tokens[0] == 'interface':
75 self.parse_interface()
77 self.parse_prototype()
79 def parse_value(self, ref_token, constructor):
81 type = self.tokens.pop(0)
82 name = self.tokens.pop(0)
85 print '%s = %s(%s, [' % (name, constructor, type)
87 while self.tokens[0] != '}':
90 name = self.tokens.pop(0)
91 value = self.tokens.pop(0)
92 tag = self.parse_tag()
93 #print ' "%s",\t# %s' % (name, value)
94 print ' "%s",' % (name,)
101 def parse_interface(self):
102 self.match('interface')
103 name = self.tokens.pop(0)
105 base = self.tokens.pop(0)
108 print '%s = Interface("%s", %s)' % (name, name, base)
109 print '%s.methods += [' % (name,)
111 while self.tokens[0] != '}':
112 self.parse_prototype('Method')
119 def parse_prototype(self, creator = 'Function'):
120 if self.tokens[0] == 'extern':
123 ret = self.parse_type()
125 name = self.tokens.pop(0)
127 if not self.has_side_effects(name):
128 extra += ', sideeffects=False'
133 if self.tokens[0] == 'void' and self.tokens[1] == ')':
135 while self.tokens[0] != ')':
136 arg = self.parse_arg()
138 if self.tokens[0] == ',':
140 self.tokens.pop(0) == ')'
142 if self.tokens and self.tokens[0] == ';':
145 print ' %s(%s, "%s", [%s]%s),' % (creator, ret, name, ', '.join(args), extra)
148 tag = self.parse_tag()
150 type = self.parse_type()
151 name = self.tokens.pop(0)
153 arg = '(%s, "%s")' % (type, name)
160 if self.tokens[0] == '[':
162 tag = self.tokens.pop(0)
166 int_tokens = ('unsigned', 'signed', 'int', 'long', 'short', 'char')
174 'uint16_t': 'UInt16',
176 'uint32_t': 'UInt32',
178 'uint64_t': 'UInt64',
181 def parse_type(self):
182 token = self.tokens.pop(0)
184 return 'Const(%s)' % self.parse_type()
187 elif token in self.int_tokens:
193 while token in self.int_tokens:
194 if token == 'unsigned':
196 if token == 'signed':
204 if self.tokens[0] in self.int_tokens:
205 token = self.tokens.pop(0)
221 type = self.type_table.get(token, token)
222 while self.tokens[0] == '*':
223 type = 'OpaquePointer(%s)' % type
227 def match(self, ref_token):
229 raise Exception('unexpected EOF')
230 token = self.tokens.pop(0)
231 if token != ref_token:
232 raise Exception('token mismatch', token, ref_token)
240 for arg in sys.argv[1:]:
241 parser.parse(open(arg, 'rt').read())
244 if __name__ == '__main__':