[pypy-commit] creflect default: Anonymous structure, but directly from a 'typedef'
arigo
noreply at buildbot.pypy.org
Tue Sep 16 15:30:10 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r44:c1f276dfda7b
Date: 2014-09-16 11:54 +0200
http://bitbucket.org/cffi/creflect/changeset/c1f276dfda7b/
Log: Anonymous structure, but directly from a 'typedef'
diff --git a/creflect/cparser.py b/creflect/cparser.py
--- a/creflect/cparser.py
+++ b/creflect/cparser.py
@@ -55,6 +55,7 @@
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()
@@ -173,15 +174,18 @@
#
if isinstance(type, pycparser.c_ast.Struct):
# 'struct foobar'
- return self._get_struct_union_enum_type('struct', type, name)
+ return self._get_struct_union_enum_type('struct', type, const,
+ name)
#
if isinstance(type, pycparser.c_ast.Union):
# 'union foobar'
- return self._get_struct_union_enum_type('union', type, name)
+ return self._get_struct_union_enum_type('union', type, const,
+ name)
#
if isinstance(type, pycparser.c_ast.Enum):
# 'enum foobar'
- return self._get_struct_union_enum_type('enum', type, name)
+ return self._get_struct_union_enum_type('enum', type, const,
+ name)
#
if isinstance(typenode, pycparser.c_ast.FuncDecl):
# a function type
@@ -189,18 +193,22 @@
#
# nested anonymous structs or unions end up here
if isinstance(typenode, pycparser.c_ast.Struct):
- return self._get_struct_union_enum_type('struct', typenode, name,
- nested=True)
+ return self._get_struct_union_enum_type('struct', typenode, const,
+ name, nested=True)
if isinstance(typenode, pycparser.c_ast.Union):
- return self._get_struct_union_enum_type('union', typenode, name,
- nested=True)
+ return self._get_struct_union_enum_type('union', typenode, const,
+ name, nested=True)
#
raise api.FFIError(":%d: bad or unsupported type declaration" %
typenode.coord.line)
- def _get_struct_union_enum_type(self, kind, type, const):
+ def _get_struct_union_enum_type(self, kind, type, const, approx_name=None):
name = type.name
- assert name # XXX
+ if not name:
+ if not approx_name:
+ self._count_anonymous_struct += 1
+ approx_name = '%d' % (self._count_anonymous_struct,)
+ name = '$%s' % approx_name
result = model.StructOrUnionOrEnum(kind, name, const)
#
# get the type declaration or create it if needed
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -241,7 +241,7 @@
self.kind = kind
self.name = name
self.const = const
- self.c_name_with_marker = '%s %s&' % (self.kind, self.name)
+ self.c_name_with_marker = '%s %s &' % (self.kind, self.name)
if const:
self.c_name_with_marker = 'const ' + self.c_name_with_marker
@@ -351,16 +351,20 @@
def write_declaration(self, funcblock):
tp = "%s %s" % (self.type.kind, self.type.name)
- extra1 = "(long long)sizeof(%s)" % (tp,) # total size
+ realtp = tp
+ if self.type.name.startswith('$'):
+ 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)" % (tp,)) # alignment
+ " - (char *)0)" % (realtp,)) # alignment
funcblock.sprintf(tp + r" {/*%lld,%lld*/\n",
extra="%s, %s" % (extra1, extra2),
extralength=40)
#
for fldname, fldtype in zip(self.fldnames, self.fldtypes):
block = CodeBlock(funcblock.tr)
- inspect = TypeInspector(block, tp, fldname)
+ inspect = TypeInspector(block, realtp, fldname)
inspect.start()
# get the offset of the field
arraylevels = 0
@@ -375,11 +379,12 @@
comment = " (%dx)" % arraylevels
comment = inspect.get_comment(0, False, "an array%s" % comment)
block.writedecl("long long o = offsetof(%s, %s%s);%s"
- % (tp, fldname, "[0]" * arraylevels, comment))
+ % (realtp, fldname, "[0]" * arraylevels,
+ comment))
else:
comment = inspect.get_comment(0, False, "not an array")
block.writedecl("long long o = ((char *)&((%s *)0)->%s)"
- " - (char *)0;%s" % (tp, fldname, comment))
+ " - (char *)0;%s" % (realtp, fldname, comment))
#
block.sprintf(" /*%lld*/", extra="o", extralength=20)
block.sprintf_add_right(r';\n')
diff --git a/test/codegen/struct-001.c b/test/codegen/struct-001.c
--- a/test/codegen/struct-001.c
+++ b/test/codegen/struct-001.c
@@ -1,6 +1,6 @@
struct foo_s {
int aa;
- int bb;
+ unsigned int bb;
};
# ____________________________________________________________
diff --git a/test/codegen/struct-005.c b/test/codegen/struct-005.c
new file mode 100644
--- /dev/null
+++ b/test/codegen/struct-005.c
@@ -0,0 +1,60 @@
+typedef struct { int aa; } foo_t;
+
+# ____________________________________________________________
+
+int teststruct_005(char *r)
+{
+ if (!r)
+ return 70 + 30 + 18 + 6 + 4 + 30;
+ r += sprintf(r, "struct $foo_t {/*%lld,%lld*/\n", (long long)sizeof(foo_t), (long long)(((char *)&((struct{char a; foo_t b;} *)0)->b) - (char *)0));
+ {
+ foo_t *p1;
+ long long o = ((char *)&((foo_t *)0)->aa) - (char *)0; /* check that 'foo_t::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_t::aa' is an integer type */
+ p1->aa = -1; /* check that 'foo_t::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");
+ {
+ r += sprintf(r, "typedef struct $foo_t foo_t;\n");
+ }
+ return 0;
+}
+
+#expect struct $foo_t {
+#expect int aa;
+#expect };
+#expect typedef struct $foo_t foo_t;
diff --git a/test/test_cgcompile.py b/test/test_cgcompile.py
--- a/test/test_cgcompile.py
+++ b/test/test_cgcompile.py
@@ -12,13 +12,17 @@
#
expected = []
for line in inputlines:
- if line.startswith('# _______'):
- break
- line = line.split('//')[0].strip()
- if line:
- expected.append(line)
- else:
- raise ValueError("no '# _______' found in %r" % (filename,))
+ if line.startswith('#expect'):
+ expected.append(line[8:].rstrip())
+ if not expected:
+ for line in inputlines:
+ if line.startswith('# _______'):
+ break
+ line = line.split('//')[0].rstrip()
+ if line:
+ expected.append(line)
+ else:
+ raise ValueError("no '# _______' found in %r" % (filename,))
#
basename = os.path.splitext(filename)[0]
infile = str(udir.join('cg-' + filename))
@@ -64,7 +68,7 @@
err = g.close()
assert not err
r_remove_addr = re.compile(r"/[*][-0-9a-fx,]+[*]/")
- got = [r_remove_addr.sub('', line.strip()) for line in lines]
+ got = [r_remove_addr.sub('', line.rstrip()) for line in lines]
compare_lists(got, expected)
More information about the pypy-commit
mailing list