2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008 Johan Dahlin
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program 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
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 from . import _giscanner
27 (CSYMBOL_TYPE_INVALID,
28 CSYMBOL_TYPE_ELLIPSIS,
31 CSYMBOL_TYPE_FUNCTION,
36 CSYMBOL_TYPE_MEMBER) = range(10)
47 CTYPE_FUNCTION) = range(10)
49 STORAGE_CLASS_NONE = 0
50 STORAGE_CLASS_TYPEDEF = 1 << 1
51 STORAGE_CLASS_EXTERN = 1 << 2
52 STORAGE_CLASS_STATIC = 1 << 3
53 STORAGE_CLASS_AUTO = 1 << 4
54 STORAGE_CLASS_REGISTER = 1 << 5
56 TYPE_QUALIFIER_NONE = 0
57 TYPE_QUALIFIER_CONST = 1 << 1
58 TYPE_QUALIFIER_RESTRICT = 1 << 2
59 TYPE_QUALIFIER_VOLATILE = 1 << 3
60 TYPE_QUALIFIER_EXTENSION = 1 << 4
63 FUNCTION_INLINE = 1 << 1
66 UNARY_POINTER_INDIRECTION,
69 UNARY_BITWISE_COMPLEMENT,
70 UNARY_LOGICAL_NEGATION) = range(6)
73 def symbol_type_name(symbol_type):
75 CSYMBOL_TYPE_INVALID: 'invalid',
76 CSYMBOL_TYPE_ELLIPSIS: 'ellipsis',
77 CSYMBOL_TYPE_CONST: 'const',
78 CSYMBOL_TYPE_OBJECT: 'object',
79 CSYMBOL_TYPE_FUNCTION: 'function',
80 CSYMBOL_TYPE_STRUCT: 'struct',
81 CSYMBOL_TYPE_UNION: 'union',
82 CSYMBOL_TYPE_ENUM: 'enum',
83 CSYMBOL_TYPE_TYPEDEF: 'typedef',
84 CSYMBOL_TYPE_MEMBER: 'member',
88 def ctype_name(ctype):
90 CTYPE_INVALID: 'invalid',
92 CTYPE_BASIC_TYPE: 'basic',
93 CTYPE_TYPEDEF: 'typedef',
94 CTYPE_STRUCT: 'struct',
97 CTYPE_POINTER: 'pointer',
99 CTYPE_FUNCTION: 'function',
103 class SourceType(object):
104 __members__ = ['type', 'base_type', 'name', 'type_qualifier',
107 def __init__(self, scanner, stype):
108 self._scanner = scanner
112 return '<%s type=%r name=%r>' % (
113 self.__class__.__name__,
114 ctype_name(self.type),
119 return self._stype.type
123 if self._stype.base_type is not None:
124 return SourceType(self._scanner, self._stype.base_type)
128 return self._stype.name
131 def type_qualifier(self):
132 return self._stype.type_qualifier
135 def child_list(self):
136 for symbol in self._stype.child_list:
139 yield SourceSymbol(self._scanner, symbol)
142 class SourceSymbol(object):
143 __members__ = ['const_int', 'const_string', 'ident', 'type', 'base_type']
145 def __init__(self, scanner, symbol):
146 self._scanner = scanner
147 self._symbol = symbol
150 return '<%s type=%r ident=%r>' % (
151 self.__class__.__name__,
152 symbol_type_name(self.type),
155 def directives(self):
157 for directive in self._scanner.get_directives(self._symbol.ident):
158 mapping[directive.name] = directive.options
163 return self._symbol.const_int
166 def const_string(self):
167 return self._symbol.const_string
171 return self._symbol.ident
175 return self._symbol.type
179 if self._symbol.base_type is not None:
180 return SourceType(self._scanner, self._symbol.base_type)
183 class SourceScanner(object):
186 self._scanner = _giscanner.SourceScanner()
188 self._cpp_options = []
192 def set_cpp_options(self, includes, defines, undefines):
193 for prefix, args in [('-I', includes),
196 for arg in (args or []):
198 if not opt in self._cpp_options:
199 self._cpp_options.append(opt)
201 def parse_files(self, filenames):
202 for filename in filenames:
203 filename = os.path.abspath(filename)
204 self._scanner.append_filename(filename)
207 for filename in filenames:
208 if filename.endswith('.c'):
209 filename = os.path.abspath(filename)
210 self._scanner.lex_filename(filename)
212 headers.append(filename)
215 self._filenames.extend(headers)
217 def parse_macros(self, filenames):
218 self._scanner.set_macro_scan(True)
219 self._scanner.parse_macros(filenames)
220 self._scanner.set_macro_scan(False)
222 def get_symbols(self):
223 for symbol in self._scanner.get_symbols():
224 yield SourceSymbol(self._scanner, symbol)
228 for symbol in self._scanner.get_symbols():
229 print symbol.ident, symbol.base_type.name, symbol.type
233 def _parse(self, filenames):
237 defines = ['__GI_SCANNER__']
239 cpp_args = ['gcc', '-E', '-C', '-I.', '-']
241 cpp_args += self._cpp_options
242 proc = subprocess.Popen(cpp_args,
243 stdin=subprocess.PIPE,
244 stdout=subprocess.PIPE)
246 for define in defines:
247 proc.stdin.write('#ifndef %s\n' % (define, ))
248 proc.stdin.write('# define %s\n' % (define, ))
249 proc.stdin.write('#endif\n')
251 proc.stdin.write('#undef %s\n' % (undef, ))
252 for filename in filenames:
253 filename = os.path.abspath(filename)
254 proc.stdin.write('#include <%s>\n' % (filename, ))
257 tmp = tempfile.mktemp()
260 data = proc.stdout.read(4096)
267 assert proc, 'Proc was none'
268 self._scanner.parse_file(fp.fileno())