Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r45:02683c15be69
Date: 2014-09-16 15:30 +0200
http://bitbucket.org/cffi/creflect/changeset/02683c15be69/

Log:    Next test

diff --git a/creflect/cparser.py b/creflect/cparser.py
--- a/creflect/cparser.py
+++ b/creflect/cparser.py
@@ -55,7 +55,6 @@
         self.cdefblock = cdefblock
         self.first_lineno = first_lineno
         self._struct_union_enum_decl = {}
-        self._count_anonymous_struct = 0
 
     def to_ast(self):
         cparser = pycparser.CParser()
@@ -94,7 +93,7 @@
     def _parse_decl(self, decl):
         node = decl.type
         if isinstance(node, pycparser.c_ast.FuncDecl):
-            tp = self._get_type(node, name=decl.name)
+            tp = self._get_type(node)
             assert isinstance(tp, model.RawFunctionType)
             tp = self._get_type_pointer(tp)
             self._declare('function ' + decl.name, tp)
@@ -133,7 +132,7 @@
               decl.type.type.type.names == ['__dotdotdot__']):
             realtype = model.unknown_ptr_type(decl.name)
         else:
-            realtype = self._get_type(decl.type, name=decl.name)
+            realtype = self._get_type(decl.type, approx_name = '$' + decl.name)
         self.declarations.append(model.TypeDef(decl.name, realtype))
 
     def _get_type_pointer(self, type, const):
@@ -141,7 +140,7 @@
             return type.as_function_pointer()
         return model.PointerType(type, const)
 
-    def _get_type(self, typenode, name=None, partial_length_ok=False):
+    def _get_type(self, typenode, approx_name=None, partial_length_ok=False):
         # first, dereference typedefs, if we have it already parsed, we're good
         if (isinstance(typenode, pycparser.c_ast.TypeDecl) and
             isinstance(typenode.type, pycparser.c_ast.IdentifierType) and
@@ -163,7 +162,10 @@
         if isinstance(typenode, pycparser.c_ast.PtrDecl):
             # pointer type
             const = 'const' in typenode.quals
-            return self._get_type_pointer(self._get_type(typenode.type), const)
+            if approx_name:
+                approx_name = '$' + approx_name
+            realtype = self._get_type(typenode.type, approx_name)
+            return self._get_type_pointer(realtype, const)
         #
         if isinstance(typenode, pycparser.c_ast.TypeDecl):
             const = 'const' in typenode.quals
@@ -175,17 +177,17 @@
             if isinstance(type, pycparser.c_ast.Struct):
                 # 'struct foobar'
                 return self._get_struct_union_enum_type('struct', type, const,
-                                                        name)
+                                                        approx_name)
             #
             if isinstance(type, pycparser.c_ast.Union):
                 # 'union foobar'
                 return self._get_struct_union_enum_type('union', type, const,
-                                                        name)
+                                                        approx_name)
             #
             if isinstance(type, pycparser.c_ast.Enum):
                 # 'enum foobar'
                 return self._get_struct_union_enum_type('enum', type, const,
-                                                        name)
+                                                        approx_name)
         #
         if isinstance(typenode, pycparser.c_ast.FuncDecl):
             # a function type
@@ -203,12 +205,11 @@
                 typenode.coord.line)
 
     def _get_struct_union_enum_type(self, kind, type, const, approx_name=None):
-        name = type.name
-        if not name:
-            if not approx_name:
-                self._count_anonymous_struct += 1
-                approx_name = '%d' % (self._count_anonymous_struct,)
-            name = '$%s' % approx_name
+        name = type.name or approx_name
+        if not name or name.startswith('$$$'):
+            self._parse_error("not implemented: anonymous 'struct' elsewhere "
+                              "than in 'typedef struct { ... } typename;' or "
+                              "'typedef struct { ... } *typename;'", type)
         result = model.StructOrUnionOrEnum(kind, name, const)
         #
         # get the type declaration or create it if needed
@@ -223,12 +224,16 @@
             else:
                 raise AssertionError("kind = %r" % (kind,))
             self._struct_union_enum_decl[key] = typedecl
-            self.declarations.append(typedecl)
+            must_add = True
+        else:
+            must_add = False
         #
         # is there a 'type.decls'?  If yes, then this is the place in the
         # C sources that declare the fields.
         if type.decls is not None:
             self._add_fields_declaration(typedecl, type.decls)
+        if must_add:
+            self.declarations.append(typedecl)
         return result
 
     def _add_fields_declaration(self, typedecl, fields):
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -15,6 +15,8 @@
                 for name in (self._attrs_ + 'const')]
 
     def inspect_type(self, block, inspect):
+        if inspect.started:
+            inspect.assign_to_p1('0')
         block.sprintf_add_both_sides(self.c_name_with_marker)
 
     def __eq__(self, other):
@@ -37,11 +39,6 @@
         if const:
             self.c_name_with_marker = 'const ' + self.c_name_with_marker
 
-    def inspect_type(self, block, inspect):
-        if inspect.started:
-            inspect.assign_to_p1('0')
-        BaseType.inspect_type(self, block, inspect)
-
 void_type = VoidType(const=False)
 const_void_type = VoidType(const=True)
 
@@ -262,7 +259,10 @@
 
     def start(self):
         if not self.started:
-            self.block.writedecl('%s *p1;' % (self.typename,))
+            if not self.typename.startswith('*'):
+                self.block.writedecl('%s *p1;' % (self.typename,))
+            else:
+                self.block.writedecl('%s p1;' % (self.typename[1:],))
             self.levels = []
             self.started = True
             self.after_star_p1_assignment = []
@@ -351,20 +351,37 @@
 
     def write_declaration(self, funcblock):
         tp = "%s %s" % (self.type.kind, self.type.name)
-        realtp = tp
-        if self.type.name.startswith('$'):
+        if not self.type.name.startswith('$'):
+            realtp = tp
+        else:
             realtp = self.type.name[1:]
-            assert not realtp.isdigit()    # XXX
-        extra1 = "(long long)sizeof(%s)" % (realtp,)    # total size
-        extra2 = ("(long long)(((char *)&((struct{char a; %s b;} *)0)->b)"
-                  " - (char *)0)" % (realtp,))          # alignment
-        funcblock.sprintf(tp + r" {/*%lld,%lld*/\n",
-                          extra="%s, %s" % (extra1, extra2),
-                          extralength=40)
+        if not realtp.startswith('$'):
+            sizetp = realtp
+            insptp = realtp
+            ptrtp = '%s *' % (realtp,)
+            include_alignment = True
+        else:
+            ptrtp = realtp[1:]
+            assert not ptrtp.startswith('$')
+            sizetp = '*(%s)0' % ptrtp
+            insptp = '*%s' % ptrtp
+            include_alignment = False
+        #
+        extra1 = "(long long)sizeof(%s)" % (sizetp,)    # total size
+        if include_alignment:
+            extra2 = ("(long long)(((char *)&((struct{char a; %s b;} *)0)->b)"
+                    " - (char *)0)" % (realtp,))          # alignment
+            funcblock.sprintf(tp + r" {/*%lld,%lld*/\n",
+                              extra="%s, %s" % (extra1, extra2),
+                              extralength=40)
+        else:
+            funcblock.sprintf(tp + r" {/*%lld*/\n",
+                              extra=extra1,
+                              extralength=20)
         #
         for fldname, fldtype in zip(self.fldnames, self.fldtypes):
             block = CodeBlock(funcblock.tr)
-            inspect = TypeInspector(block, realtp, fldname)
+            inspect = TypeInspector(block, insptp, fldname)
             inspect.start()
             # get the offset of the field
             arraylevels = 0
@@ -383,8 +400,8 @@
                                    comment))
             else:
                 comment = inspect.get_comment(0, False, "not an array")
-                block.writedecl("long long o = ((char *)&((%s *)0)->%s)"
-                                " - (char *)0;%s" % (realtp, fldname, comment))
+                block.writedecl("long long o = ((char *)&((%s)0)->%s)"
+                                " - (char *)0;%s" % (ptrtp, fldname, comment))
             #
             block.sprintf("  /*%lld*/", extra="o", extralength=20)
             block.sprintf_add_right(r';\n')
diff --git a/test/codegen/struct-005b.c b/test/codegen/struct-005b.c
new file mode 100644
--- /dev/null
+++ b/test/codegen/struct-005b.c
@@ -0,0 +1,64 @@
+typedef struct { int aa; } *foo_p;
+
+# ____________________________________________________________
+
+int teststruct_005b(char *r)
+{
+    if (!r)
+        return 46 + 30 + 18 + 6 + 4 + 32;
+    r += sprintf(r, "struct $$foo_p {/*%lld*/\n", (long 
long)sizeof(*(foo_p)0));
+    {
+        foo_p p1;
+        long long o = ((char *)&((foo_p)0)->aa) - (char *)0;  /* check that 
'*foo_p::aa' is not an array */
+        char b[sizeof(p1->aa)];
+        r += sprintf(r, "  /*%lld*/", o);
+        p1 = (void *)(((char *)b) - o);
+        (void)(p1->aa << 1);  /* check that '*foo_p::aa' is an integer type */
+        p1->aa = -1;  /* check that '*foo_p::aa' is not declared 'const' */
+        if (p1->aa > 0) {
+            if (sizeof(p1->aa) == 1 && p1->aa == 1)
+                r += sprintf(r, "_Bool");
+            else if (sizeof(p1->aa) == sizeof(unsigned int))
+                r += sprintf(r, "unsigned int");
+            else if (sizeof(p1->aa) == sizeof(unsigned short))
+                r += sprintf(r, "unsigned short");
+            else if (sizeof(p1->aa) == sizeof(unsigned char))
+                r += sprintf(r, "unsigned char");
+            else if (sizeof(p1->aa) == sizeof(unsigned long))
+                r += sprintf(r, "unsigned long");
+            else if (sizeof(p1->aa) == sizeof(unsigned long long))
+                r += sprintf(r, "unsigned long long");
+            else
+                r += sprintf(r, "uint%u_t", (int)sizeof(p1->aa) * 8);
+        }
+        else {
+            if (sizeof(p1->aa) == sizeof(int))
+                r += sprintf(r, "int");
+            else if (sizeof(p1->aa) == sizeof(short))
+                r += sprintf(r, "short");
+            else if (sizeof(p1->aa) == sizeof(signed char))
+                r += sprintf(r, "signed char");
+            else if (sizeof(p1->aa) == sizeof(long))
+                r += sprintf(r, "long");
+            else if (sizeof(p1->aa) == sizeof(long long))
+                r += sprintf(r, "long long");
+            else
+                r += sprintf(r, "int%u_t", (int)sizeof(p1->aa) * 8);
+        }
+        r += sprintf(r, " aa;\n");
+    }
+    r += sprintf(r, "};\n");
+    {
+        foo_p *p1;
+        char *p2;
+        p1 = (void *)&p2;
+        *p1 = (void *)0;    /* check that 'foo_p' is a pointer type */
+        r += sprintf(r, "typedef struct $$foo_p *foo_p;\n");
+    }
+    return 0;
+}
+
+#expect struct $$foo_p {
+#expect   int aa;
+#expect };
+#expect typedef struct $$foo_p *foo_p;
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to