Author: Ronan Lamy <ronan.l...@gmail.com> Branch: rffi-parser Changeset: r89116:078ef51e7af9 Date: 2016-12-17 15:24 +0000 http://bitbucket.org/pypy/pypy/changeset/078ef51e7af9/
Log: Handle includes diff --git a/pypy/module/cpyext/cparser.py b/pypy/module/cpyext/cparser.py --- a/pypy/module/cpyext/cparser.py +++ b/pypy/module/cpyext/cparser.py @@ -26,12 +26,11 @@ _parser_cache = pycparser.CParser() return _parser_cache -def _preprocess(csource): +def _preprocess(csource, macros): # Remove comments. NOTE: this only work because the cdef() section # should not contain any string literal! csource = _r_comment.sub(' ', csource) # Remove the "#define FOO x" lines - macros = OrderedDict() for match in _r_define.finditer(csource): macroname, macrovalue = match.groups() macrovalue = macrovalue.replace('\\\n', '').strip() @@ -102,9 +101,11 @@ self._options = {} self._int_constants = {} self._recomplete = [] + self._macros = OrderedDict() def _parse(self, csource): - csource, macros = _preprocess(csource) + # modifies self._macros in-place + csource, macros = _preprocess(csource, self._macros) # XXX: for more efficiency we would need to poke into the # internals of CParser... the following registers the # typedefs, because their presence or absence influences the @@ -633,10 +634,12 @@ if name.startswith('anonymous $enum_$'): continue # fix for test_anonymous_enum_include kind = name.split(' ', 1)[0] - if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'): + if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef', 'macro'): self._declare(name, tp, included=True, quals=quals) for k, v in other._int_constants.items(): self._add_constants(k, v) + for k, v in other._macros.items(): + self._macros[k] = v CNAME_TO_LLTYPE = { 'char': rffi.CHAR, @@ -671,11 +674,12 @@ class ParsedSource(object): - def __init__(self, source, definitions=None, macros=None): + def __init__(self, source, parser, definitions=None, macros=None): self.source = source self.definitions = definitions if definitions is not None else {} self.macros = macros if macros is not None else {} self.structs = {} + self.ctx = parser def add_typedef(self, name, obj): assert name not in self.definitions @@ -711,11 +715,17 @@ raise NotImplementedError -def parse_source(source): +def parse_source(source, includes=None): ctx = Parser() + if includes is not None: + for header in includes: + ctx.include(header.ctx) + ctx.parse(source) - src = ParsedSource(source) + src = ParsedSource(source, ctx) for name, (obj, quals) in ctx._declarations.iteritems(): + if obj in ctx._included_declarations: + continue if name.startswith('typedef '): name = name[8:] src.add_typedef(name, obj) diff --git a/pypy/module/cpyext/test/test_cparser.py b/pypy/module/cpyext/test/test_cparser.py --- a/pypy/module/cpyext/test/test_cparser.py +++ b/pypy/module/cpyext/test/test_cparser.py @@ -39,3 +39,21 @@ hdr = parse_source(decl) assert 'PyFloatObject' in hdr.definitions assert 'PyObject_HEAD' in hdr.macros + +def test_include(): + cdef1 = """ + typedef ssize_t Py_ssize_t; + + #define PyObject_HEAD \ + Py_ssize_t ob_refcnt; \ + Py_ssize_t ob_pypy_link; \ + """ + hdr1 = parse_source(cdef1) + cdef2 = """ + typedef struct { + PyObject_HEAD + Py_ssize_t ob_foo; + } Object; + """ + hdr2 = parse_source(cdef2, includes=[hdr1]) + assert 'Object' in hdr2.definitions _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit