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()