blob: 7ef66f7c4b5c79fde386f6c1a0be3d3e80a9b023 [file] [log] [blame]
eli.benderskyd5ba3452011-02-18 21:32:47 +02001#-----------------------------------------------------------------
2# pycparser: c-to-c.py
3#
eli.benderskyafcfaac2011-02-25 16:46:01 +02004# Example of a C code generator from pycparser AST nodes, serving
5# as a simplistic translator from C to AST and back to C.
eli.benderskyd5ba3452011-02-18 21:32:47 +02006#
7# Copyright (C) 2008-2011, Eli Bendersky
8# License: LGPL
9#-----------------------------------------------------------------
10from __future__ import print_function
11import sys
12
13# This is not required if you've installed pycparser into
14# your site-packages/ with setup.py
15#
16sys.path.insert(0, '..')
17
18from pycparser import c_parser, c_ast, parse_file
19
20
eli.benderskyafcfaac2011-02-25 16:46:01 +020021class CGenerator(object):
22 """ Uses the same visitor pattern as c_ast.NodeVisitor, but modified to
23 return a value from each visit method, using string accumulation in
24 generic_visit.
25 """
eli.benderskyd5ba3452011-02-18 21:32:47 +020026 def __init__(self):
27 self.output = ''
28
eli.benderskyafcfaac2011-02-25 16:46:01 +020029 # Statements start with indentation of self.indent_level spaces
30 #
31 self.indent_level = 0
32
33 def visit(self, node):
34 method = 'visit_' + node.__class__.__name__
35 return getattr(self, method, self.generic_visit)(node)
36
37 def generic_visit(self, node):
38 #~ print('generic:', type(node))
39 if node is None:
40 return ''
41 else:
42 return ''.join(self.visit(c) for c in node.children())
eli.benderskyd5ba3452011-02-18 21:32:47 +020043
44 def visit_Constant(self, n):
eli.benderskyafcfaac2011-02-25 16:46:01 +020045 return n.value
46
eli.benderskyd5ba3452011-02-18 21:32:47 +020047 def visit_ID(self, n):
eli.benderskyafcfaac2011-02-25 16:46:01 +020048 return n.name
eli.benderskyd5ba3452011-02-18 21:32:47 +020049
50 def visit_IdentifierType(self, n):
eli.benderskyafcfaac2011-02-25 16:46:01 +020051 return ' '.join(n.names) + ' '
eli.benderskyd5ba3452011-02-18 21:32:47 +020052
eli.benderskyafcfaac2011-02-25 16:46:01 +020053 def visit_Decl(self, n):
54 s = self._generate_decl(n)
55 if n.bitsize: s += ' : ' + self.visit(n.bitsize)
56 if n.init: s += ' = ' + self.visit(n.init)
57 return s
eli.benderskyd5ba3452011-02-18 21:32:47 +020058
eli.benderskyafcfaac2011-02-25 16:46:01 +020059 def visit_FuncDef(self, n):
60 decl = self.visit(n.decl)
61 self.indent_level = 0
62 body = self.visit(n.body)
63 return decl + '\n' + body
64
eli.benderskyd5ba3452011-02-18 21:32:47 +020065 def _generate_decl(self, n):
66 """ Generation from a Decl node.
67 """
eli.benderskyafcfaac2011-02-25 16:46:01 +020068 s = ''
69 if n.funcspec: s = ' '.join(n.funcspec) + ' '
70 if n.storage: s += ' '.join(n.storage) + ' '
71 s += self._generate_type(n.type)
72 return s
eli.benderskyd5ba3452011-02-18 21:32:47 +020073
74 def _generate_type(self, n, modifiers=[]):
75 """ Recursive generation from a type node. n is the type node.
eli.benderskyafcfaac2011-02-25 16:46:01 +020076 modifiers collects the PtrDecl, ArrayDecl and FuncDecl modifiers
77 encountered on the way down to a TypeDecl, to allow proper
78 generation from it.
eli.benderskyd5ba3452011-02-18 21:32:47 +020079 """
80 typ = type(n)
81 #~ print(n, modifiers)
82
83 if typ == c_ast.TypeDecl:
eli.benderskyafcfaac2011-02-25 16:46:01 +020084 s = ''
85 if n.quals: s += ' '.join(n.quals) + ' '
86 s += self.visit(n.type)
eli.benderskyd5ba3452011-02-18 21:32:47 +020087
88 nstr = n.declname if n.declname else ''
eli.benderskyafcfaac2011-02-25 16:46:01 +020089 # Resolve odifiers.
90 # Wrap in parens to distinguish pointer to array and pointer to
91 # function syntax.
eli.benderskyd5ba3452011-02-18 21:32:47 +020092 #
93 for i, modifier in enumerate(modifiers):
94 if isinstance(modifier, c_ast.ArrayDecl):
95 if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
96 nstr = '(' + nstr + ')'
eli.benderskyafcfaac2011-02-25 16:46:01 +020097 nstr += '[' + self.visit(modifier.dim) + ']'
98 elif isinstance(modifier, c_ast.FuncDecl):
99 if (i != 0 and isinstance(modifiers[i - 1], c_ast.PtrDecl)):
100 nstr = '(' + nstr + ')'
101 nstr += '(' + self.visit(modifier.args) + ')'
eli.benderskyd5ba3452011-02-18 21:32:47 +0200102 elif isinstance(modifier, c_ast.PtrDecl):
103 nstr = '*' + nstr
eli.benderskyafcfaac2011-02-25 16:46:01 +0200104 s += nstr
105 return s
eli.benderskyd5ba3452011-02-18 21:32:47 +0200106 elif typ in (c_ast.Typename, c_ast.Decl):
eli.benderskyafcfaac2011-02-25 16:46:01 +0200107 return self._generate_decl(n.type)
eli.benderskyd5ba3452011-02-18 21:32:47 +0200108 elif typ == c_ast.IdentifierType:
eli.benderskyafcfaac2011-02-25 16:46:01 +0200109 return ' '.join(n.names) + ' '
110 elif typ in (c_ast.ArrayDecl, c_ast.PtrDecl, c_ast.FuncDecl):
111 return self._generate_type(n.type, modifiers + [n])
eli.benderskyd5ba3452011-02-18 21:32:47 +0200112
113
114def translate_to_c(filename):
115 ast = parse_file(filename, use_cpp=True)
116 generator = CGenerator()
eli.benderskyafcfaac2011-02-25 16:46:01 +0200117 print(generator.visit(ast))
eli.benderskyd5ba3452011-02-18 21:32:47 +0200118
119
120if __name__ == "__main__":
121 if len(sys.argv) > 1:
122 translate_to_c(sys.argv[1])
123 else:
124 src = r'''
eli.benderskyafcfaac2011-02-25 16:46:01 +0200125 static const int (**c[chevo])[2] = t;
126 int (*joe)();
127
128 int main() {
129 int kk;
130 }
eli.benderskyd5ba3452011-02-18 21:32:47 +0200131 '''
132 parser = c_parser.CParser()
133 ast = parser.parse(src)
134 ast.show()
135 generator = CGenerator()
eli.benderskyafcfaac2011-02-25 16:46:01 +0200136 print(generator.visit(ast))
eli.benderskyd5ba3452011-02-18 21:32:47 +0200137
138 print("Please provide a filename as argument")