diff options
author | Amir Gonnen <amirgonnen@gmail.com> | 2019-03-28 00:22:44 +0200 |
---|---|---|
committer | Eli Bendersky <eliben@users.noreply.github.com> | 2019-03-27 15:22:44 -0700 |
commit | e1a1d737be66308b633215fa26ac5ed30e890103 (patch) | |
tree | 05c2766212f9e5f14fa8b78743a4a8f2577b6508 | |
parent | 96059858252ea3673226a9a4d03a356bd51ba47e (diff) | |
download | pycparser-e1a1d737be66308b633215fa26ac5ed30e890103.tar.gz |
Generate pointer types correctly (#315)
* Add visit_PtrDecl to generate ptr types correctly
Also removed code duplication from visit_ArrayDecl and visit_TypeDecl by calling _generate_type instead, without emitting the declname.
Added tests for ptr type generation
* Truncate lines longer than 80 characters
per https://github.com/eliben/pycparser/pull/315/files#r269553083
-rw-r--r-- | pycparser/c_generator.py | 42 | ||||
-rw-r--r-- | tests/test_c_generator.py | 18 |
2 files changed, 37 insertions, 23 deletions
diff --git a/pycparser/c_generator.py b/pycparser/c_generator.py index bc22946..2cd83fa 100644 --- a/pycparser/c_generator.py +++ b/pycparser/c_generator.py @@ -292,18 +292,13 @@ class CGenerator(object): return self._generate_type(n) def visit_ArrayDecl(self, n): - s = '' - s += self.visit(n.type) + '[' - if n.dim_quals: s += ' '.join(n.dim_quals) + ' ' - if n.dim: s += self.visit(n.dim) - s += ']' - return s - + return self._generate_type(n, emit_declname=False) + def visit_TypeDecl(self, n): - s = '' - if n.quals: s += ' '.join(n.quals) + ' ' - s += self.visit(n.type) - return s + return self._generate_type(n, emit_declname=False) + + def visit_PtrDecl(self, n): + return self._generate_type(n, emit_declname=False) def _generate_struct_union_enum(self, n, name): """ Generates code for structs, unions, and enums. name should be @@ -373,7 +368,7 @@ class CGenerator(object): s += self._generate_type(n.type) return s - def _generate_type(self, n, modifiers=[]): + def _generate_type(self, n, modifiers=[], emit_declname = True): """ Recursive generation from a type node. n is the type node. modifiers collects the PtrDecl, ArrayDecl and FuncDecl modifiers encountered on the way down to a TypeDecl, to allow proper @@ -387,25 +382,29 @@ class CGenerator(object): if n.quals: s += ' '.join(n.quals) + ' ' s += self.visit(n.type) - nstr = n.declname if n.declname else '' + nstr = n.declname if n.declname and emit_declname else '' # Resolve modifiers. # Wrap in parens to distinguish pointer to array and pointer to # function syntax. # for i, modifier in enumerate(modifiers): if isinstance(modifier, c_ast.ArrayDecl): - if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)): - nstr = '(' + nstr + ')' + if (i != 0 and + isinstance(modifiers[i - 1], c_ast.PtrDecl)): + nstr = '(' + nstr + ')' nstr += '[' - if modifier.dim_quals: nstr += ' '.join(modifier.dim_quals) + ' ' + if modifier.dim_quals: + nstr += ' '.join(modifier.dim_quals) + ' ' nstr += self.visit(modifier.dim) + ']' elif isinstance(modifier, c_ast.FuncDecl): - if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)): - nstr = '(' + nstr + ')' + if (i != 0 and + isinstance(modifiers[i - 1], c_ast.PtrDecl)): + nstr = '(' + nstr + ')' nstr += '(' + self.visit(modifier.args) + ')' elif isinstance(modifier, c_ast.PtrDecl): if modifier.quals: - nstr = '* %s %s' % (' '.join(modifier.quals), nstr) + nstr = '* %s%s' % (' '.join(modifier.quals), + ' ' + nstr if nstr else '') else: nstr = '*' + nstr if nstr: s += ' ' + nstr @@ -413,11 +412,12 @@ class CGenerator(object): elif typ == c_ast.Decl: return self._generate_decl(n.type) elif typ == c_ast.Typename: - return self._generate_type(n.type) + return self._generate_type(n.type, emit_declname = emit_declname) elif typ == c_ast.IdentifierType: return ' '.join(n.names) + ' ' elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl, c_ast.FuncDecl): - return self._generate_type(n.type, modifiers + [n]) + return self._generate_type(n.type, modifiers + [n], + emit_declname = emit_declname) else: return self.visit(n) diff --git a/tests/test_c_generator.py b/tests/test_c_generator.py index e2f7bee..b48094e 100644 --- a/tests/test_c_generator.py +++ b/tests/test_c_generator.py @@ -336,8 +336,22 @@ class TestCtoC(unittest.TestCase): self._assert_ctoc_correct('int g(const int a[const 20]){}') ast = parse_to_ast('const int a[const 20];') generator = c_generator.CGenerator() - self.assertEqual(generator.visit(ast.ext[0].type), 'const int[const 20]') - self.assertEqual(generator.visit(ast.ext[0].type.type), 'const int') + self.assertEqual(generator.visit(ast.ext[0].type), + 'const int [const 20]') + self.assertEqual(generator.visit(ast.ext[0].type.type), + 'const int') + + def test_ptr_decl(self): + src = 'const int ** const x;' + self._assert_ctoc_correct(src) + ast = parse_to_ast(src) + generator = c_generator.CGenerator() + self.assertEqual(generator.visit(ast.ext[0].type), + 'const int ** const') + self.assertEqual(generator.visit(ast.ext[0].type.type), + 'const int *') + self.assertEqual(generator.visit(ast.ext[0].type.type.type), + 'const int') if __name__ == "__main__": unittest.main() |