Author: Armin Rigo <ar...@tunes.org>
Branch: cffi-1.0
Changeset: r1783:68760daf07ab
Date: 2015-04-24 09:00 +0200
http://bitbucket.org/cffi/cffi/changeset/68760daf07ab/

Log:    in-progress

diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -568,23 +568,48 @@
             return ffi._get_cached_btype(tp)
 
 def _set_cdef_types(ffi):
+    from . import model
+
+    all_structs = {}
+    all_typedefs = {}
+    for name, tp in ffi._parser._declarations.items():
+        kind, basename = name.split(' ', 1)
+        if kind == 'struct' or kind == 'union' or kind == 'anonymous':
+            all_structs[tp.name] = tp
+        elif kind == 'typedef':
+            all_typedefs[basename] = tp
+            if getattr(tp, "origin", None) == "unknown_type":
+                all_structs[tp.name] = tp
+            elif isinstance(tp, model.NamedPointerType):
+                all_structs[tp.totype.name] = tp.totype
+
     struct_unions = []
     pending_completion = []
-    lst = ffi._parser._declarations.items()
-    lst = sorted(lst, key=lambda x: x[0].split(' ', 1)[1])
-    for name, tp in lst:
-        kind, basename = name.split(' ', 1)
-        if kind == 'struct' or kind == 'union':
-            if kind == 'struct':
-                BType = _cffi1_backend.new_struct_type(basename)
-            else:
-                BType = _cffi1_backend.new_union_type(basename)
-            struct_unions.append(basename)
-            struct_unions.append(BType)
-            if not tp.partial and tp.fldtypes is not None:
-                pending_completion.append((tp, BType))
+    for name, tp in sorted(all_structs.items()):
+        if not isinstance(tp, model.UnionType):
+            BType = _cffi1_backend.new_struct_type(name)
+        else:
+            BType = _cffi1_backend.new_union_type(name)
+        struct_unions.append(name)
+        struct_unions.append(BType)
+        if not tp.partial and tp.fldtypes is not None:
+            pending_completion.append((tp, BType))
     #
-    ffi.__set_types(struct_unions)
+    typenames = []
+    for name, tp in sorted(all_typedefs.items()):
+        cname = tp._get_c_name()
+        if cname == name:
+            assert isinstance(tp, model.StructOrUnionOrEnum)
+            cname = '%s %s' % (tp.kind, tp.name)
+        try:
+            BType = ffi.typeof(cname)
+        except ffi.error:
+            ffi.__set_types(struct_unions, typenames)
+            BType = ffi.typeof(cname)
+        typenames.append(name)
+        typenames.append(BType)
+    #
+    ffi.__set_types(struct_unions, typenames)
     #
     for tp, BType in pending_completion:
         fldtypes = [ffi.typeof(ftp._get_c_name()) for ftp in tp.fldtypes]
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -459,7 +459,7 @@
 
 def unknown_ptr_type(name, structname=None):
     if structname is None:
-        structname = '*$%s' % name
+        structname = '$$%s' % name
     tp = StructType(structname, None, None, None)
     return NamedPointerType(tp, name)
 
diff --git a/new/ffi_obj.c b/new/ffi_obj.c
--- a/new/ffi_obj.c
+++ b/new/ffi_obj.c
@@ -525,15 +525,18 @@
 
 static PyObject *ffi__set_types(FFIObject *self, PyObject *args)
 {
-    PyObject *lst1;
+    PyObject *lst1, *lst2;
     _cffi_opcode_t *types = NULL;
     struct _cffi_struct_union_s *struct_unions = NULL;
+    struct _cffi_typename_s *typenames = NULL;
 
-    if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &lst1))
+    if (!PyArg_ParseTuple(args, "O!O!",
+                          &PyList_Type, &lst1, &PyList_Type, &lst2))
         return NULL;
 
     if (self->ctx_is_static) {
      bad_usage:
+        PyMem_Free(typenames);
         PyMem_Free(struct_unions);
         PyMem_Free(types);
         if (!PyErr_Occurred())
@@ -543,19 +546,24 @@
 
     cleanup_builder_c(self->types_builder);
 
-    int i, lst_length = PyList_GET_SIZE(lst1) / 2;
-    Py_ssize_t new_size_1 = sizeof(_cffi_opcode_t) * lst_length;
-    Py_ssize_t new_size_2 = sizeof(struct _cffi_struct_union_s) * lst_length;
-    types = PyMem_Malloc(new_size_1);
-    struct_unions = PyMem_Malloc(new_size_2);
-    if (!types || !struct_unions) {
+    int i;
+    int lst1_length = PyList_GET_SIZE(lst1) / 2;
+    int lst2_length = PyList_GET_SIZE(lst2) / 2;
+    Py_ssize_t newsize0 = sizeof(_cffi_opcode_t) * (lst1_length + lst2_length);
+    Py_ssize_t newsize1 = sizeof(struct _cffi_struct_union_s) * lst1_length;
+    Py_ssize_t newsize2 = sizeof(struct _cffi_typename_s) * lst2_length;
+    types = PyMem_Malloc(newsize0);
+    struct_unions = PyMem_Malloc(newsize1);
+    typenames = PyMem_Malloc(newsize2);
+    if (!types || !struct_unions || !typenames) {
         PyErr_NoMemory();
         goto bad_usage;
     }
-    memset(types, 0, new_size_1);
-    memset(struct_unions, 0, new_size_2);
+    memset(types, 0, newsize0);
+    memset(struct_unions, 0, newsize1);
+    memset(typenames, 0, newsize2);
 
-    for (i = 0; i < lst_length; i++) {
+    for (i = 0; i < lst1_length; i++) {
         PyObject *x = PyList_GET_ITEM(lst1, i * 2);
         if (!PyString_Check(x))
             goto bad_usage;
@@ -570,18 +578,32 @@
         struct_unions[i].size = (size_t)-2;
         struct_unions[i].alignment = -2;
     }
-    for (i = 0; i < lst_length; i++) {
+    for (i = 0; i < lst2_length; i++) {
+        PyObject *x = PyList_GET_ITEM(lst2, i * 2);
+        if (!PyString_Check(x))
+            goto bad_usage;
+        typenames[i].name = PyString_AS_STRING(x);
+        typenames[i].type_index = lst1_length + i;
+
+        x = PyList_GET_ITEM(lst2, i * 2 + 1);
+        if (!CTypeDescr_Check(x))
+            goto bad_usage;
+        types[lst1_length + i] = x;
+    }
+    for (i = 0; i < lst1_length + lst2_length; i++) {
         PyObject *x = (PyObject *)types[i];
         Py_INCREF(x);
     }
 
-    Py_INCREF(lst1);     /* to keep alive the strings in '.name' */
+    Py_INCREF(args);     /* to keep alive the strings in '.name' */
     Py_XDECREF(self->dynamic_types);
-    self->dynamic_types = lst1;
+    self->dynamic_types = args;
     self->types_builder->ctx.types = types;
-    self->types_builder->num_types_imported = lst_length;
+    self->types_builder->num_types_imported = lst1_length + lst2_length;
     self->types_builder->ctx.struct_unions = struct_unions;
-    self->types_builder->ctx.num_struct_unions = lst_length;
+    self->types_builder->ctx.num_struct_unions = lst1_length;
+    self->types_builder->ctx.typenames = typenames;
+    self->types_builder->ctx.num_typenames = lst2_length;
 
     Py_INCREF(Py_None);
     return Py_None;
diff --git a/new/parse_c_type.c b/new/parse_c_type.c
--- a/new/parse_c_type.c
+++ b/new/parse_c_type.c
@@ -56,7 +56,9 @@
 
 static int is_ident_first(char x)
 {
-    return (('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '_');
+    return (('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '_' ||
+            x == '$');   /* '$' in names is supported here, for the struct
+                            names invented by cparser */
 }
 
 static int is_digit(char x)
diff --git a/new/recompiler.py b/new/recompiler.py
--- a/new/recompiler.py
+++ b/new/recompiler.py
@@ -508,8 +508,17 @@
     _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype
 
     def _generate_cpy_struct_decl(self, tp, name):
-        cname = tp.get_c_name('')
-        self._struct_decl(tp, cname, cname.replace(' ', '_'))
+        cname = tp._get_c_name()
+        if ' ' in cname:
+            prefix, declname = cname.split(' ', 1)
+        else:
+            prefix, declname = '', cname
+        while declname.startswith('$'):
+            prefix += 'D'
+            declname = declname[1:]
+        approxname = prefix + '_' + declname
+        assert '$' not in approxname
+        self._struct_decl(tp, cname, approxname)
     _generate_cpy_union_decl = _generate_cpy_struct_decl
 
     def _generate_cpy_struct_ctx(self, tp, name, prefix='s'):
@@ -518,28 +527,6 @@
     _generate_cpy_union_ctx = _generate_cpy_struct_ctx
 
     # ----------
-    # 'anonymous' declarations.  These are produced for anonymous structs
-    # or unions; the 'name' is obtained by a typedef.
-
-    def _generate_cpy_anonymous_collecttype(self, tp, name):
-        if isinstance(tp, model.EnumType):
-            self._generate_cpy_enum_collecttype(tp, name)
-        else:
-            self._struct_collecttype(tp)
-
-    def _generate_cpy_anonymous_decl(self, tp, name):
-        if isinstance(tp, model.EnumType):
-            self._generate_cpy_enum_decl(tp, name, '')
-        else:
-            self._struct_decl(tp, name, 'typedef_' + name)
-
-    def _generate_cpy_anonymous_ctx(self, tp, name):
-        if isinstance(tp, model.EnumType):
-            self._generate_cpy_enum_ctx(tp, name, '')
-        else:
-            self._struct_ctx(tp, name, 'typedef_' + name)
-
-    # ----------
     # constants, declared with "static const ..."
 
     def _generate_cpy_const(self, is_int, name, tp=None, category='const',
diff --git a/new/test_dlopen.py b/new/test_dlopen.py
--- a/new/test_dlopen.py
+++ b/new/test_dlopen.py
@@ -19,6 +19,34 @@
     assert ffi.sizeof("union bar_s") == 4
     assert ffi.sizeof("struct foo_s") == 4
 
+def test_cdef_struct_typename_1():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int a; } t1; typedef struct { t1* m; } t2;")
+    assert ffi.sizeof("t2") == ffi.sizeof("void *")
+    assert ffi.sizeof("t1") == 4
+
+def test_cdef_struct_typename_2():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int a; } *p1; typedef struct { p1 m; } *p2;")
+    p2 = ffi.new("p2")
+    assert ffi.sizeof(p2[0]) == ffi.sizeof("void *")
+    assert ffi.sizeof(p2[0].m) == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_1():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int a; } t1; struct foo_s { t1* m; };")
+    assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_2():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int a; } *p1; struct foo_s { p1 m; };")
+    assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_3():
+    ffi = FFI()
+    ffi.cdef("typedef struct { int a; } **pp; struct foo_s { pp m; };")
+    assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
 def test_math_sin():
     py.test.skip("XXX redo!")
     ffi = FFI()
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to