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