Author: Armin Rigo <ar...@tunes.org>
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
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to