From 749650a2e24051cdd6a7bfa803c03e0a5fa77103 Mon Sep 17 00:00:00 2001 From: ksero Date: Fri, 9 Sep 2016 07:31:09 +0200 Subject: Fix eliben/pycparser#87 : offsetof() support is incomplete --- pycparser/c_parser.py | 17 ++++++++++++++++- tests/test_c_parser.py | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py index 53f445a..cf062fb 100644 --- a/pycparser/c_parser.py +++ b/pycparser/c_parser.py @@ -1608,13 +1608,28 @@ class CParser(PLYParser): p[0] = p[2] def p_primary_expression_5(self, p): - """ primary_expression : OFFSETOF LPAREN type_name COMMA identifier RPAREN + """ primary_expression : OFFSETOF LPAREN type_name COMMA offsetof_member_designator RPAREN """ coord = self._coord(p.lineno(1)) p[0] = c_ast.FuncCall(c_ast.ID(p[1], coord), c_ast.ExprList([p[3], p[5]], coord), coord) + def p_offsetof_member_designator(self, p): + """ offsetof_member_designator : identifier + | offsetof_member_designator PERIOD identifier + | offsetof_member_designator LBRACKET expression RBRACKET + """ + if len(p) == 2: + p[0] = p[1] + elif len(p) == 4: + field = c_ast.ID(p[3], self._coord(p.lineno(3))) + p[0] = c_ast.StructRef(p[1], p[2], field, p[1].coord) + elif len(p) == 5: + p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord) + else: + raise NotImplementedError("Unexpected parsing state. len(p): %u" % len(p)) + def p_argument_expression_list(self, p): """ argument_expression_list : assignment_expression | argument_expression_list COMMA assignment_expression diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py index 277c750..3adb62c 100755 --- a/tests/test_c_parser.py +++ b/tests/test_c_parser.py @@ -480,6 +480,8 @@ class TestCParser_fundamentals(TestCParser_base): void foo() { int a = offsetof(struct S, p); a.b = offsetof(struct sockaddr, sp) + strlen(bar); + int a = offsetof(struct S, p.q.r); + int a = offsetof(struct S, p[5].q[4][5]); } """ compound = self.parse(e).ext[0].body @@ -489,6 +491,10 @@ class TestCParser_fundamentals(TestCParser_base): self.assertEqual(s1.name.name, 'offsetof') self.assertTrue(isinstance(s1.args.exprs[0], Typename)) self.assertTrue(isinstance(s1.args.exprs[1], ID)) + s3 = compound.block_items[2].init + self.assertTrue(isinstance(s3.args.exprs[1], StructRef)) + s4 = compound.block_items[3].init + self.assertTrue(isinstance(s4.args.exprs[1], ArrayRef)) # The C99 compound literal feature # -- cgit v1.2.1