summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Bendersky <eliben@gmail.com>2015-05-09 15:20:46 -0700
committerEli Bendersky <eliben@gmail.com>2015-05-09 15:20:46 -0700
commite59395be5f3f52693d49529368bc7850a3e761eb (patch)
tree4e64a44aedcd8bf28b00dc7bac70f79a96b9c760
parentf1b2db2a64afbbc2397cc860d4088317113a8c5f (diff)
downloadpycparser-e59395be5f3f52693d49529368bc7850a3e761eb.tar.gz
Adding support for offsetof()
-rw-r--r--pycparser/c_lexer.py3
-rw-r--r--pycparser/c_parser.py8
-rw-r--r--tests/test_c_lexer.py3
-rwxr-xr-xtests/test_c_parser.py15
4 files changed, 28 insertions, 1 deletions
diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py
index e8d2af0..ce53af0 100644
--- a/pycparser/c_lexer.py
+++ b/pycparser/c_lexer.py
@@ -102,7 +102,8 @@ class CLexer(object):
keywords = (
'_BOOL', '_COMPLEX', 'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST',
'CONTINUE', 'DEFAULT', 'DO', 'DOUBLE', 'ELSE', 'ENUM', 'EXTERN',
- 'FLOAT', 'FOR', 'GOTO', 'IF', 'INLINE', 'INT', 'LONG', 'REGISTER',
+ 'FLOAT', 'FOR', 'GOTO', 'IF', 'INLINE', 'INT', 'LONG',
+ 'REGISTER', 'OFFSETOF',
'RESTRICT', 'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT',
'SWITCH', 'TYPEDEF', 'UNION', 'UNSIGNED', 'VOID',
'VOLATILE', 'WHILE',
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
index 2041d4f..e4fa503 100644
--- a/pycparser/c_parser.py
+++ b/pycparser/c_parser.py
@@ -1572,6 +1572,14 @@ class CParser(PLYParser):
""" primary_expression : LPAREN expression RPAREN """
p[0] = p[2]
+ def p_primary_expression_5(self, p):
+ """ primary_expression : OFFSETOF LPAREN type_name COMMA identifier 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_argument_expression_list(self, p):
""" argument_expression_list : assignment_expression
| argument_expression_list COMMA assignment_expression
diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py
index 6d0b52d..033963e 100644
--- a/tests/test_c_lexer.py
+++ b/tests/test_c_lexer.py
@@ -84,6 +84,9 @@ class TestCLexerNoErrors(unittest.TestCase):
# - is MINUS, the rest a constnant
self.assertTokensTypes('-1', ['MINUS', 'INT_CONST_DEC'])
+ def test_special_names(self):
+ self.assertTokensTypes('sizeof offsetof', ['SIZEOF', 'OFFSETOF'])
+
def test_floating_constants(self):
self.assertTokensTypes('1.5f', ['FLOAT_CONST'])
self.assertTokensTypes('01.5', ['FLOAT_CONST'])
diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py
index 035182d..556748c 100755
--- a/tests/test_c_parser.py
+++ b/tests/test_c_parser.py
@@ -475,6 +475,21 @@ class TestCParser_fundamentals(TestCParser_base):
['TypeDecl',
['IdentifierType', ['int']]]]]])
+ def test_offsetof(self):
+ e = """
+ void foo() {
+ int a = offsetof(struct S, p);
+ a.b = offsetof(struct sockaddr, sp) + strlen(bar);
+ }
+ """
+ compound = self.parse(e).ext[0].body
+ s1 = compound.block_items[0].init
+ self.assertIsInstance(s1, FuncCall)
+ self.assertIsInstance(s1.name, ID)
+ self.assertEqual(s1.name.name, 'offsetof')
+ self.assertIsInstance(s1.args.exprs[0], Typename)
+ self.assertIsInstance(s1.args.exprs[1], ID)
+
# The C99 compound literal feature
#
def test_compound_literals(self):