Author: Armin Rigo <[email protected]>
Branch:
Changeset: r99:4c7a226a0be6
Date: 2014-11-28 12:58 +0100
http://bitbucket.org/cffi/creflect/changeset/4c7a226a0be6/
Log: Support for "typedef ... sometype;"
diff --git a/creflect/cparser.py b/creflect/cparser.py
--- a/creflect/cparser.py
+++ b/creflect/cparser.py
@@ -28,7 +28,8 @@
r_comment1 = re.compile(r"//.*")
r_comment2 = re.compile(r"/[*]")
r_comment3 = re.compile(r"[*]/")
-r_empty_braces = re.compile(r"{\s*}") # after comments have been removed
+r_empty_braces = re.compile(r"{(\s*)}") # after comments have been removed
+r_typedef_dotdodot = re.compile(r"\btypedef(\s*)[.][.][.]")
def remove_comments(csource):
csource = r_comment1.sub('', csource) # remove the '//' comments
@@ -50,7 +51,10 @@
return ''.join(parts)
def expand_empty_braces(csource):
- return r_empty_braces.sub('{ char __crx_empty__; }', csource)
+ return r_empty_braces.sub(r'{ char __crx_empty__;\1}', csource)
+
+def expand_typedef_dotdotdot(csource):
+ return r_typedef_dotdodot.sub(r'typedef\1 __crx_unknown_t ', csource)
class CSource(object):
@@ -60,10 +64,15 @@
self.first_lineno = first_lineno
self._struct_union_enum_decl = {}
- def to_ast(self):
- cparser = pycparser.CParser()
+ def prepare_source(self):
csource = remove_comments(self.cdefblock)
csource = expand_empty_braces(csource)
+ csource = expand_typedef_dotdotdot(csource)
+ return 'typedef int __crx_unknown_t; ' + csource
+
+ def to_ast(self):
+ csource = self.prepare_source()
+ cparser = pycparser.CParser()
try:
ast = cparser.parse(csource)
except pycparser.c_parser.ParseError as e:
@@ -85,7 +94,8 @@
self.declarations = []
self.typedefs = {}
ast = self.to_ast()
- for decl in ast.ext:
+ assert ast.ext[0].name == '__crx_unknown_t'
+ for decl in ast.ext[1:]:
if isinstance(decl, pycparser.c_ast.Decl):
self._parse_decl(decl)
elif isinstance(decl, pycparser.c_ast.Typedef):
@@ -148,9 +158,13 @@
# 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
- len(typenode.type.names) == 1 and
- typenode.type.names[0] in self.typedefs):
- return self.typedefs[typenode.type.names[0]]
+ len(typenode.type.names) == 1):
+ typename = typenode.type.names[0]
+ if typename in self.typedefs:
+ return self.typedefs[typenode.type.names[0]]
+ if typename == '__crx_unknown_t':
+ assert approx_name, "XXX"
+ return model.UnknownType(approx_name)
#
if isinstance(typenode, pycparser.c_ast.ArrayDecl):
# array type
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -476,6 +476,20 @@
self.name,))
+class UnknownType(BaseType):
+ _attrs_ = ('approx_name',)
+ const = False
+
+ def __init__(self, approx_name):
+ self.approx_name = approx_name
+ self.c_name_with_marker = '... &'
+
+ def inspect_nonconst_type(self, block, inspect):
+ inspect.flush()
+ return block.write_crx_type_var('cb->get_unknown_type(cb, "%s")' % (
+ self.approx_name,))
+
+
# ____________________________________________________________
diff --git a/creflect/src/creflect.h b/creflect/src/creflect.h
--- a/creflect/src/creflect.h
+++ b/creflect/src/creflect.h
@@ -52,6 +52,7 @@
crx_type_t *(*get_union_type)(CRX_SELF, const char *);
crx_type_t *(*get_enum_type)(CRX_SELF, const char *);
crx_type_t *(*get_user_type)(CRX_SELF, const char *);
+ crx_type_t *(*get_unknown_type)(CRX_SELF, const char *);
void (*complete)(CRX_SELF, crx_type_t *,
size_t, size_t, crx_field_t[], int);
void (*complete_enum)(CRX_SELF, crx_type_t *, crx_type_t *);
diff --git a/creflect/src/creflect_print.h b/creflect/src/creflect_print.h
--- a/creflect/src/creflect_print.h
+++ b/creflect/src/creflect_print.h
@@ -167,6 +167,11 @@
return newtype(name);
}
+static crx_type_t *tst_get_unknown_type(crx_builder_t *cb, const char *name)
+{
+ return newtype2("UNKNOWN ", name);
+}
+
static void tst_complete(crx_builder_t *cb, crx_type_t *t,
size_t sz, size_t align,
crx_field_t fields[], int nfields)
@@ -258,6 +263,7 @@
tst_get_union_type,
tst_get_enum_type,
tst_get_user_type,
+ tst_get_unknown_type,
tst_complete,
tst_complete_enum,
tst_define_type,
diff --git a/test/codegen/007.c b/test/codegen/007.c
new file mode 100644
--- /dev/null
+++ b/test/codegen/007.c
@@ -0,0 +1,13 @@
+typedef ... num_t;
+
+# ____________________________________________________________
+
+void test007(crx_builder_t *cb)
+{
+ crx_type_t *t1;
+ {
+ t1 = cb->get_unknown_type(cb, "$num_t");
+ cb->define_type(cb, "num_t", t1);
+#expect TYPEDEF num_t = UNKNOWN $num_t
+ }
+}
diff --git a/test/test_cgcompile.py b/test/test_cgcompile.py
--- a/test/test_cgcompile.py
+++ b/test/test_cgcompile.py
@@ -25,6 +25,8 @@
f.write('\n')
for line in inputlines:
if not (line.startswith('# ') or line.startswith('#expect')):
+ if line.startswith('typedef ...'):
+ line = 'typedef struct _missing ' + line[11:]
f.write(line)
f.write('\n')
f.write('#include "%s/../../creflect/src/creflect_print.h"\n' % path)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit