aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmir Gonnen <amirgonnen@gmail.com>2019-03-28 00:22:44 +0200
committerEli Bendersky <eliben@users.noreply.github.com>2019-03-27 15:22:44 -0700
commite1a1d737be66308b633215fa26ac5ed30e890103 (patch)
tree05c2766212f9e5f14fa8b78743a4a8f2577b6508
parent96059858252ea3673226a9a4d03a356bd51ba47e (diff)
downloadpycparser-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.py42
-rw-r--r--tests/test_c_generator.py18
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()