blob: cb3bd08856f42e297f5ad4ffde32b2d7b80362ef [file] [log] [blame]
import sys
import unittest
# Run from the root dir
sys.path.insert(0, '.')
from pycparser import c_parser, c_generator, c_ast
_c_parser = c_parser.CParser(
lex_optimize=False,
yacc_debug=True,
yacc_optimize=False,
yacctab='yacctab')
def compare_asts(ast1, ast2):
if type(ast1) != type(ast2):
return False
if isinstance(ast1, tuple) and isinstance(ast2, tuple):
if ast1[0] != ast2[0]:
return False
ast1 = ast1[1]
ast2 = ast2[1]
return compare_asts(ast1, ast2)
for attr in ast1.attr_names:
if getattr(ast1, attr) != getattr(ast2, attr):
return False
for i, c1 in enumerate(ast1.children()):
if compare_asts(c1, ast2.children()[i]) == False:
return False
return True
def parse_to_ast(src):
return _c_parser.parse(src)
class TestFunctionDeclGeneration(unittest.TestCase):
class _FuncDeclVisitor(c_ast.NodeVisitor):
def __init__(self):
self.stubs = []
def visit_FuncDecl(self, node):
gen = c_generator.CGenerator()
self.stubs.append(gen.visit(node))
def test_partial_funcdecl_generation(self):
src = r'''
void noop(void);
void *something(void *thing);
int add(int x, int y);'''
ast = parse_to_ast(src)
v = TestFunctionDeclGeneration._FuncDeclVisitor()
v.visit(ast)
self.assertEqual(len(v.stubs), 3)
self.assertTrue(r'void noop(void)' in v.stubs)
self.assertTrue(r'void *something(void *thing)' in v.stubs)
self.assertTrue(r'int add(int x, int y)' in v.stubs)
class TestCtoC(unittest.TestCase):
def _run_c_to_c(self, src):
ast = parse_to_ast(src)
generator = c_generator.CGenerator()
return generator.visit(ast)
def _assert_ctoc_correct(self, src):
""" Checks that the c2c translation was correct by parsing the code
generated by c2c for src and comparing the AST with the original
AST.
"""
src2 = self._run_c_to_c(src)
self.assertTrue(compare_asts(parse_to_ast(src), parse_to_ast(src2)),
src2)
def test_trivial_decls(self):
self._assert_ctoc_correct('int a;')
self._assert_ctoc_correct('int b, a;')
self._assert_ctoc_correct('int c, b, a;')
def test_complex_decls(self):
self._assert_ctoc_correct('int** (*a)(void);')
self._assert_ctoc_correct('int** (*a)(void*, int);')
self._assert_ctoc_correct('int (*b)(char * restrict k, float);')
self._assert_ctoc_correct('int test(const char* const* arg);')
self._assert_ctoc_correct('int test(const char** const arg);')
#s = 'int test(const char* const* arg);'
#parse_to_ast(s).show()
def test_ternary(self):
self._assert_ctoc_correct('''
int main(void)
{
int a, b;
(a == 0) ? (b = 1) : (b = 2);
}''')
def test_casts(self):
self._assert_ctoc_correct(r'''
int main() {
int b = (int) f;
int c = (int*) f;
}''')
def test_initlist(self):
self._assert_ctoc_correct('int arr[] = {1, 2, 3};')
def test_exprs(self):
self._assert_ctoc_correct('''
int main(void)
{
int a;
int b = a++;
int c = ++a;
int d = a--;
int e = --a;
}''')
def test_statements(self):
# note two minuses here
self._assert_ctoc_correct(r'''
int main() {
int a;
a = 5;
;
b = - - a;
return a;
}''')
def test_casts(self):
self._assert_ctoc_correct(r'''
int main() {
int a = (int) b + 8;
int t = (int) c;
}
''')
def test_struct_decl(self):
self._assert_ctoc_correct(r'''
typedef struct node_t {
struct node_t* next;
int data;
} node;
''')
def test_krstyle(self):
self._assert_ctoc_correct(r'''
int main(argc, argv)
int argc;
char** argv;
{
return 0;
}
''')
def test_switchcase(self):
self._assert_ctoc_correct(r'''
int main() {
switch (myvar) {
case 10:
{
k = 10;
p = k + 1;
break;
}
case 20:
case 30:
return 20;
default:
break;
}
}
''')
def test_nest_initializer_list(self):
self._assert_ctoc_correct(r'''
int main()
{
int i[1][1] = { { 1 } };
}''')
def test_nest_named_initializer(self):
self._assert_ctoc_correct(r'''struct test
{
int i;
struct test_i_t
{
int k;
} test_i;
int j;
};
struct test test_var = {.i = 0, .test_i = {.k = 1}, .j = 2};
''')
def test_expr_list_in_initializer_list(self):
self._assert_ctoc_correct(r'''
int main()
{
int i[1] = { (1, 2) };
}''')
def test_issue36(self):
self._assert_ctoc_correct(r'''
int main() {
}''')
def test_issue37(self):
self._assert_ctoc_correct(r'''
int main(void)
{
unsigned size;
size = sizeof(size);
return 0;
}''')
def test_issue83(self):
self._assert_ctoc_correct(r'''
void x(void) {
int i = (9, k);
}
''')
def test_issue84(self):
self._assert_ctoc_correct(r'''
void x(void) {
for (int i = 0;;)
i;
}
''')
def test_exprlist_with_semi(self):
self._assert_ctoc_correct(r'''
void x() {
if (i < j)
tmp = C[i], C[i] = C[j], C[j] = tmp;
if (i <= j)
i++, j--;
}
''')
def test_exprlist_with_subexprlist(self):
self._assert_ctoc_correct(r'''
void x() {
(a = b, (b = c, c = a));
}
''')
def test_comma_operator_funcarg(self):
self._assert_ctoc_correct(r'''
void f(int x) { return x; }
int main(void) { f((1, 2)); return 0; }
''')
def test_comma_op_in_ternary(self):
self._assert_ctoc_correct(r'''
void f() {
(0, 0) ? (0, 0) : (0, 0);
}
''')
def test_comma_op_assignment(self):
self._assert_ctoc_correct(r'''
void f() {
i = (a, b, c);
}
''')
def test_pragma(self):
self._assert_ctoc_correct(r'''
#pragma foo
void f() {
#pragma bar
i = (a, b, c);
}
''')
if __name__ == "__main__":
unittest.main()