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