2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008 Johan Dahlin
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the
17 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 # Boston, MA 02111-1307, USA.
21 from __future__ import with_statement
26 from .libtoolimporter import LibtoolImporter
29 (CSYMBOL_TYPE_INVALID,
30 CSYMBOL_TYPE_ELLIPSIS,
33 CSYMBOL_TYPE_FUNCTION,
38 CSYMBOL_TYPE_MEMBER) = range(10)
49 CTYPE_FUNCTION) = range(10)
51 STORAGE_CLASS_NONE = 0
52 STORAGE_CLASS_TYPEDEF = 1 << 1
53 STORAGE_CLASS_EXTERN = 1 << 2
54 STORAGE_CLASS_STATIC = 1 << 3
55 STORAGE_CLASS_AUTO = 1 << 4
56 STORAGE_CLASS_REGISTER = 1 << 5
58 TYPE_QUALIFIER_NONE = 0
59 TYPE_QUALIFIER_CONST = 1 << 1
60 TYPE_QUALIFIER_RESTRICT = 1 << 2
61 TYPE_QUALIFIER_VOLATILE = 1 << 3
62 TYPE_QUALIFIER_EXTENSION = 1 << 4
65 FUNCTION_INLINE = 1 << 1
68 UNARY_POINTER_INDIRECTION,
71 UNARY_BITWISE_COMPLEMENT,
72 UNARY_LOGICAL_NEGATION) = range(6)
75 def symbol_type_name(symbol_type):
77 CSYMBOL_TYPE_INVALID: 'invalid',
78 CSYMBOL_TYPE_ELLIPSIS: 'ellipsis',
79 CSYMBOL_TYPE_CONST: 'const',
80 CSYMBOL_TYPE_OBJECT: 'object',
81 CSYMBOL_TYPE_FUNCTION: 'function',
82 CSYMBOL_TYPE_STRUCT: 'struct',
83 CSYMBOL_TYPE_UNION: 'union',
84 CSYMBOL_TYPE_ENUM: 'enum',
85 CSYMBOL_TYPE_TYPEDEF: 'typedef',
86 CSYMBOL_TYPE_MEMBER: 'member',
90 def ctype_name(ctype):
92 CTYPE_INVALID: 'invalid',
94 CTYPE_BASIC_TYPE: 'basic',
95 CTYPE_TYPEDEF: 'typedef',
96 CTYPE_STRUCT: 'struct',
99 CTYPE_POINTER: 'pointer',
100 CTYPE_ARRAY: 'array',
101 CTYPE_FUNCTION: 'function',
105 class SourceType(object):
106 __members__ = ['type', 'base_type', 'name', 'type_qualifier',
107 'child_list', 'is_bitfield']
109 def __init__(self, scanner, stype):
110 self._scanner = scanner
114 return '<%s type=%r name=%r>' % (
115 self.__class__.__name__,
116 ctype_name(self.type),
121 return self._stype.type
125 if self._stype.base_type is not None:
126 return SourceType(self._scanner, self._stype.base_type)
130 return self._stype.name
133 def type_qualifier(self):
134 return self._stype.type_qualifier
137 def child_list(self):
138 for symbol in self._stype.child_list:
141 yield SourceSymbol(self._scanner, symbol)
144 def is_bitfield(self):
145 return self._stype.is_bitfield
148 class SourceSymbol(object):
149 __members__ = ['const_int', 'const_double', 'const_string', 'ident',
152 def __init__(self, scanner, symbol):
153 self._scanner = scanner
154 self._symbol = symbol
157 return '<%s type=%r ident=%r>' % (
158 self.__class__.__name__,
159 symbol_type_name(self.type),
164 return self._symbol.const_int
167 def const_double(self):
168 return self._symbol.const_double
171 def const_string(self):
172 return self._symbol.const_string
176 return self._symbol.ident
180 return self._symbol.type
184 if self._symbol.base_type is not None:
185 return SourceType(self._scanner, self._symbol.base_type)
188 def source_filename(self):
189 return self._symbol.source_filename
192 class SourceScanner(object):
195 with LibtoolImporter:
196 from giscanner._giscanner import SourceScanner
197 self._scanner = SourceScanner()
199 self._cpp_options = []
203 def set_cpp_options(self, includes, defines, undefines):
204 for prefix, args in [('-I', includes),
207 for arg in (args or []):
209 if not opt in self._cpp_options:
210 self._cpp_options.append(opt)
212 def parse_files(self, filenames):
213 for filename in filenames:
214 filename = os.path.abspath(filename)
215 self._scanner.append_filename(filename)
218 for filename in filenames:
219 if filename.endswith('.c'):
220 filename = os.path.abspath(filename)
221 self._scanner.lex_filename(filename)
223 headers.append(filename)
226 self._filenames.extend(headers)
228 def parse_macros(self, filenames):
229 self._scanner.set_macro_scan(True)
230 self._scanner.parse_macros(filenames)
231 self._scanner.set_macro_scan(False)
233 def get_symbols(self):
234 for symbol in self._scanner.get_symbols():
235 yield SourceSymbol(self._scanner, symbol)
237 def get_comments(self):
238 return self._scanner.get_comments()
242 for symbol in self._scanner.get_symbols():
243 print symbol.ident, symbol.base_type.name, symbol.type
247 def _parse(self, filenames):
251 defines = ['__GI_SCANNER__']
253 cpp_args = ['cc', '-E', '-C', '-I.', '-']
255 cpp_args += self._cpp_options
256 proc = subprocess.Popen(cpp_args,
257 stdin=subprocess.PIPE,
258 stdout=subprocess.PIPE)
260 for define in defines:
261 proc.stdin.write('#ifndef %s\n' % (define, ))
262 proc.stdin.write('# define %s\n' % (define, ))
263 proc.stdin.write('#endif\n')
265 proc.stdin.write('#undef %s\n' % (undef, ))
266 for filename in filenames:
267 filename = os.path.abspath(filename)
268 proc.stdin.write('#include <%s>\n' % (filename, ))
271 tmp = tempfile.mktemp()
274 data = proc.stdout.read(4096)
281 assert proc, 'Proc was none'
282 self._scanner.parse_file(fp.fileno())