def test_parse_with_nested_if_blocks(self): source = """ #if CONFIG_SOMETHING #if CONFIG_SOMETHING_ELSE #define FOO #endif #else #define BAR #endif """ actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.If(conditional_blocks=[ pre_ast.ConditionalBlock( conditional_expression='CONFIG_SOMETHING', content=[ pre_ast.If(conditional_blocks=[ pre_ast.ConditionalBlock( conditional_expression="CONFIG_SOMETHING_ELSE", content=[ pre_ast.DefineObjectLike(name="FOO", replacement="") ], ) ]) ]), pre_ast.ConditionalBlock( conditional_expression='1', content=[ pre_ast.DefineObjectLike(name="BAR", replacement="") ], ), ]), ]) self.assertASTEqual(actual, expected)
def test_ifdef(self): parsed_pre_ast = self.parser.parse(""" #define BAZ 1024 int Some(text); # if BAZ > 1000 #define BOO 2 int more_Text(); # else #define BOO 4 #endif """) # Learn about the macros defined above. actual = self.visitor.preprocess(parsed_pre_ast) expected = pre_ast.CompositeBlock([ pre_ast.TextBlock(content='int Some(text);'), pre_ast.CompositeBlock( [pre_ast.TextBlock(content='int more_Text();')]) ]) self.assertASTEqual(actual, expected) # Make sure that the right macro was defined. self.assertASTEqual( self.macros.object_likes["BOO"], pre_ast.DefineObjectLike(name="BOO", replacement="2"))
def test_collect_includes_with_define_object_like(self): node = pre_ast.DefineObjectLike( name='some_name', replacement='some_replacement', ) actual = self.include_collector.collect_includes(node) expected = [] self.assertEqual(actual, expected)
def test_parse_define_object_like_as_numeric_constant(self): source = '#define foo 42' actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement='42', ), ]) self.assertASTEqual(actual, expected)
def test_parse_define_empty_object_like(self): source = '#define foo' actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement="", ), ]) self.assertASTEqual(actual, expected)
def test_parse_define_empty_object_like_looks_like_func(self): # https://gcc.gnu.org/onlinedocs/cpp/Function-like-Macros.html # This is not a function like macro. source = '#define foo (bar)' actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement="(bar)", ), ]) self.assertASTEqual(actual, expected)
def _get_object_like_macros(self): """A function that produces object like macros from config flags.""" # Add object like intrinsics from gcc. result = gcc_constants.get_x86_64_kernel_compile_object_likes() # Append config vars. for flag, value in self.config_flags.iteritems(): result[flag] = pre_ast.DefineObjectLike( name=flag, # Macros replacements are always strings - even for CNumber() # config options. replacement=str(value.value), ) return result
def test_ternary_operations(self): self.macros.add_object_likes(__BYTE_ORDER=pre_ast.DefineObjectLike( name="__BYTE_ORDER", replacement="2")) expressions = [ ("defined(__BYTE_ORDER) ? __BYTE_ORDER == 20 : 1", 0), ("defined(__BYTE_ORDER) ? __BYTE_ORDER == 2 : 0", 1), ("!defined(__BYTE_ORDER) ? __BYTE_ORDER == 2 : 0", 0), ] for code, expected in expressions: actual = self.macro_expander.expand(code) expression_ast = self.expression_parser.parse(actual) result = self.expression_evaluator.evaluate(expression_ast) self.assertEqual(result, expected)
def test_parse_multiline_define(self): source = '\n'.join([ '#define foo bar\\', ' baz', ' 42', ]) actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement='bar baz', ), pre_ast.TextBlock('42'), ]) self.assertASTEqual(actual, expected)
def test_parse_with_empty_ifndef_header_guard(self): source = """ #ifndef _SOMETHING_H #define _SOMETHING_H #endif """ actual = self.parser.parse(source) expected = pre_ast.CompositeBlock([ pre_ast.If([ pre_ast.ConditionalBlock( conditional_expression="!defined(_SOMETHING_H)", content=[ pre_ast.DefineObjectLike( name='_SOMETHING_H', replacement="", ), ], ), ]), ]) self.assertASTEqual(actual, expected)
def get_x86_64_kernel_compile_object_likes(): return { '__STDC__': pre_ast.DefineObjectLike( name='__STDC__', replacement='1', ), '__STDC_VERSION__': pre_ast.DefineObjectLike( name='__STDC_VERSION__', replacement='201112L', ), '_XOPEN_SOURCE': pre_ast.DefineObjectLike( name='_XOPEN_SOURCE', replacement='500', ), '__GNUC__': pre_ast.DefineObjectLike( name='__GNUC__', replacement='4', ), '__GNUC_MINOR__': pre_ast.DefineObjectLike( name='__GNUC_MINOR__', replacement='8', ), '__GNUC_PATCHLEVEL__': pre_ast.DefineObjectLike( name='__GNUC_PATCHLEVEL__', replacement='4', ), '__x86_64__': pre_ast.DefineObjectLike( name='__x86_64__', replacement='1', ), '__KERNEL__': pre_ast.DefineObjectLike( name='__KERNEL__', replacement='', ), '__cplusplus': pre_ast.DefineObjectLike( name='__cplusplus', replacement='', ), '__GLIBC__': pre_ast.DefineObjectLike( name='__GLIBC__', replacement='2', ), '__GLIBC_MINOR__': pre_ast.DefineObjectLike( name='__GLIBC_MINOR__', replacement='19', ), # Derived from scripts/gcc-goto.sh "CC_HAVE_ASM_GOTO": pre_ast.DefineObjectLike( name='CC_HAVE_ASM_GOTO', replacement='1', ), }
def _add_object_like(self, tok): self.current_node.content.append( pre_ast.DefineObjectLike(name=tok.name, replacement=tok.replacement.strip()))