import sys import unittest # Run from the root dir sys.path.insert(0, '.') from pycparser import c_parser, c_generator _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 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);') 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_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); } ''') if __name__ == "__main__": unittest.main()