Author: Ronan Lamy <[email protected]>
Branch: rffi-parser-2
Changeset: r89612:ce1401635012
Date: 2017-01-16 17:04 +0000
http://bitbucket.org/pypy/pypy/changeset/ce1401635012/

Log:    Allow parsing multiple headers into the same cts

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
@@ -685,9 +685,9 @@
 
 
 class CTypeSpace(object):
-    def __init__(self, source, parser=None, definitions=None, macros=None,
+    def __init__(self, parser=None, definitions=None, macros=None,
                  headers=None, includes=None):
-        self.source = source
+        self.sources = []
         self.definitions = definitions if definitions is not None else {}
         self.macros = macros if macros is not None else {}
         self.structs = {}
@@ -697,6 +697,7 @@
         self._TYPES = {}
         self.includes = []
         self.struct_typedefs = {}
+        self._handled = set()
         if includes is not None:
             for header in includes:
                 self.include(header)
@@ -706,6 +707,11 @@
         self.structs.update(other.structs)
         self.includes.append(other)
 
+    def parse_source(self, source):
+        self.sources.append(source)
+        self.ctx.parse(source)
+        self.configure_types()
+
     def add_typedef(self, name, obj, quals):
         assert name not in self.definitions
         tp = self.convert_type(obj, quals)
@@ -746,7 +752,10 @@
         return struct.TYPE
 
     def build_eci(self):
-        all_sources = [x.source for x in self.includes] + [self.source]
+        all_sources = []
+        for cts in self.includes:
+            all_sources.extend(cts.sources)
+        all_sources.extend(self.sources)
         all_headers = self.headers
         for x in self.includes:
             for hdr in x.headers:
@@ -759,6 +768,9 @@
         for name, (obj, quals) in self.ctx._declarations.iteritems():
             if obj in self.ctx._included_declarations:
                 continue
+            if name in self._handled:
+                continue
+            self._handled.add(name)
             if name.startswith('typedef '):
                 name = name[8:]
                 self.add_typedef(name, obj, quals)
@@ -771,6 +783,7 @@
             del TYPE._hints['eci']
             if name in self._TYPES:
                 self._TYPES[name].become(TYPE)
+                del self._TYPES[name]
 
     def convert_type(self, obj, quals=0):
         if isinstance(obj, model.PrimitiveType):
@@ -825,7 +838,6 @@
 
 
 def parse_source(source, includes=None, headers=None, configure_now=True):
-    src = CTypeSpace(source, headers=headers, includes=includes)
-    src.ctx.parse(source)
-    src.configure_types()
-    return src
+    cts = CTypeSpace(headers=headers, includes=includes)
+    cts.parse_source(source)
+    return cts
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
@@ -1,5 +1,5 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.cparser import parse_source
+from pypy.module.cpyext.cparser import parse_source, CTypeSpace
 
 def test_configure():
     decl = """
@@ -67,6 +67,34 @@
     Object = cts2.definitions['Object']
     assert Object.c_type.TO is Type
 
+def test_multiple_sources():
+    cdef1 = """
+    typedef ssize_t Py_ssize_t;
+
+    #define PyObject_HEAD  \
+        Py_ssize_t ob_refcnt;        \
+        Py_ssize_t ob_pypy_link;     \
+
+    typedef struct {
+        char *name;
+    } Type;
+    """
+    cdef2 = """
+    typedef struct {
+        PyObject_HEAD
+        Py_ssize_t ob_foo;
+        Type *type;
+    } Object;
+    """
+    cts = CTypeSpace()
+    cts.parse_source(cdef1)
+    Type = cts.definitions['Type']
+    assert isinstance(Type, lltype.Struct)
+    assert 'Object' not in cts.definitions
+    cts.parse_source(cdef2)
+    Object = cts.definitions['Object']
+    assert Object.c_type.TO is Type
+
 def test_incomplete():
     cdef = """
     typedef ssize_t Py_ssize_t;
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to