def test_keep_parentheses_in_nested_expression(self): evaluator = ( macro_expression_evaluator_visitor.MacroExpressionEvaluatorVisitor( object_likes=self.object_likes, function_likes=self.function_likes, functions=self.functions, lazy_functions=self.lazy_functions, keep_parentheses=True, ) ) self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNumber(42), string_replacement='42', ), 'bar': pre_ast.DefineObjectLike( name='bar', replacement=c_ast.CNumber(33), string_replacement='33', ), }) expression = c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('foo'), closer=')', ) actual = evaluator.evaluate(expression) expected = c_ast.CNestedExpression( opener='(', content=c_ast.CNumber(42), closer=')', ) self.assertEqual(actual, expected)
def test_preproces_define_object_like_with_already_defined_name(self): define_object_like_1 = pre_ast.DefineObjectLike( name='some_name', replacement='some_replacement_1', string_replacement='some_string_replacement_2', ) self.object_likes['some_name'] = define_object_like_1 define_object_like_2 = pre_ast.DefineObjectLike( name='some_name', replacement='some_replacement_2', string_replacement='some_string_replacement_2', ) actual = self.preprocessing_visitor.preprocess(define_object_like_2) self.assertIsNone(actual) self.assertEquals(self.object_likes['some_name'], define_object_like_2)
def test_evaluate_function_call_with_identifier_defined_to_other_identifier( self, ): self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CVariable('bar'), string_replacement='bar', ), }) self.function_likes.update({ 'bar': pre_ast.DefineFunctionLike( name='bar', arguments=['x'], replacement=c_ast.CNumber(42), string_replacement='42', ), }) expression = c_ast.CFunctionCall( function_name='foo', arguments=[c_ast.CVariable('x')], ) actual = self.evaluator.evaluate(expression) expected = c_ast.CNumber(42) self.assertEqual(actual, expected)
def create_define_object_like(identifier, string_replacement): replacement = _try_to_parse(replacement_list, string_replacement) return pre_ast.DefineObjectLike( name=identifier, replacement=replacement, string_replacement=string_replacement, )
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.File( pre_ast.CompositeBlock([ pre_ast.If([ pre_ast.ConditionalBlock( conditional_expression=c_ast.CFunctionCall( function_name='!', arguments=[ c_ast.CFunctionCall( function_name='defined', arguments=[ c_ast.CVariable('_SOMETHING_H') ]), ], ), content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='_SOMETHING_H', replacement=None, string_replacement='', ), ]), ), ]), ]), ) self.assertEqual(actual, expected)
def test_evaluate_function_variable_cycle( self, ): self.object_likes.update({ 'y': pre_ast.DefineObjectLike( name='y', replacement=c_ast.CFunctionCall( function_name='f', arguments=[c_ast.CVariable('x')], ), string_replacement='f(x)', ), }) self.function_likes.update({ 'f': pre_ast.DefineFunctionLike( name='f', arguments=['x'], replacement=c_ast.CVariable('y'), string_replacement='y', ), }) expression = c_ast.CFunctionCall( function_name='f', arguments=[c_ast.CNumber(42)], ) actual = self.evaluator.evaluate(expression) expected = c_ast.CFunctionCall( function_name='f', arguments=[c_ast.CVariable('x')], ) self.assertEqual(actual, expected)
def test_evaluate_with_argument_to_resolve_named_as_unresolvable_object( self, ): self.object_likes.update({ 'x': pre_ast.DefineObjectLike( name='x', replacement=c_ast.CFunctionCall( function_name='f', arguments=[c_ast.CNumber(42)], ), string_replacement='f(42)', ), }) self.function_likes.update({ 'f': pre_ast.DefineFunctionLike( name='f', arguments=['x'], replacement=c_ast.CVariable('x'), string_replacement='x', ), }) expression = c_ast.CVariable('x') actual = self.evaluator.evaluate(expression) expected = c_ast.CNumber(42) self.assertEqual(actual, expected)
def test_evaluate_argument_overshadows_top_level_variable( self, ): self.object_likes.update({ 'x': pre_ast.DefineObjectLike( name='x', replacement=c_ast.CNumber(33), string_replacement='33', ), }) self.function_likes.update({ 'f': pre_ast.DefineFunctionLike( name='f', arguments=['x'], replacement=c_ast.CVariable('x'), string_replacement='x', ), }) expression = c_ast.CFunctionCall( function_name='f', arguments=[c_ast.CNumber(42)], ) actual = self.evaluator.evaluate(expression) expected = c_ast.CNumber(42) self.assertEqual(actual, expected)
def test_collect_includes_with_define_object_like(self): node = pre_ast.DefineObjectLike( name='some_name', replacement='some_replacement', string_replacement='some_string_replacement', ) actual = self.include_collector.collect_includes(node) expected = [] self.assertEqual(actual, expected)
def test_evaluate_identifier_defined_to_identifier_defined_to_undefined_id( self, ): self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CVariable('bar'), string_replacement='bar', ), 'bar': pre_ast.DefineObjectLike( name='bar', replacement=c_ast.CLiteral('baz'), string_replacement='baz', ), }) expression = c_ast.CVariable('foo') actual = self.evaluator.evaluate(expression) expected = c_ast.CVariable('baz') self.assertEqual(actual, expected)
def test_parse_define_object_like(self): source = '#define foo bar' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CVariable('bar'), string_replacement=' bar', ), ]), ) self.assertEqual(actual, expected)
def test_preproces_undef_with_existing_object_like(self): define_object_like = pre_ast.DefineObjectLike( name='some_name', replacement='some_replacement', string_replacement='some_string_replacement', ) self.object_likes['some_name'] = define_object_like undef = pre_ast.Undef('some_name') actual = self.preprocessing_visitor.preprocess(undef) self.assertIsNone(actual) self.assertFalse('some_name' in self.object_likes)
def test_parse_define_string(self): source = '#define foo "bar"' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CLiteral('"bar"'), string_replacement=' "bar"', ), ]), ) self.assertEqual(actual, expected)
def test_parse_define_object_like_as_numeric_constant_with_comment(self): source = '#define foo 42 /* bar */' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNumber(42), string_replacement=' 42 ', ), ]), ) self.assertEqual(actual, expected)
def test_evaluate_identifier_defined_to_empty_string(self): self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=None, string_replacement='', ), }) expression = c_ast.CVariable('foo') actual = self.evaluator.evaluate(expression) expected = c_ast.CLiteral('') self.assertEqual(actual, expected)
def test_evaluate_nested_expression(self): self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNumber(42), string_replacement='42', ), 'bar': pre_ast.DefineObjectLike( name='bar', replacement=c_ast.CNumber(33), string_replacement='33', ), }) expression = c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('foo'), closer=')', ) actual = self.evaluator.evaluate(expression) expected = c_ast.CNumber(42) self.assertEqual(actual, expected)
def _get_object_like_macros(config_flags): """A function that produces object like macros from config flags.""" macros = {} # Add object like intrinsics from gcc. macros.update(gcc_constants.get_x86_64_kernel_compile_object_likes()) # Append config vars. for flag, value in config_flags.iteritems(): macros[flag] = pre_ast.DefineObjectLike( name=flag, replacement=value, string_replacement=str(value.value), ) return macros
def test_evaluate_object_like_with_simple_recursion( self, ): self.object_likes.update({ 'x': pre_ast.DefineObjectLike( name='x', replacement=c_ast.CVariable('x'), string_replacement='x', ), }) expression = c_ast.CVariable('x') actual = self.evaluator.evaluate(expression) expected = c_ast.CVariable('x') self.assertEqual(actual, expected)
def test_evaluate_cycle_in_object_like_definitions( self, ): self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CVariable('bar'), string_replacement='bar', ), 'bar': pre_ast.DefineObjectLike( name='bar', replacement=c_ast.CVariable('baz'), string_replacement='baz', ), 'baz': pre_ast.DefineObjectLike( name='baz', replacement=c_ast.CVariable('foo'), string_replacement='foo', ), }) expression = c_ast.CVariable('foo') actual = self.evaluator.evaluate(expression) expected = c_ast.CVariable('foo') self.assertEqual(actual, expected)
def test_parse_define_object_like_with_parentheses_expression(self): source = '#define foo (bar)' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('bar'), closer=')', ), string_replacement=' (bar)', ), ]), ) self.assertEqual(actual, expected)
def test_parse_define_object_like_as_function_call(self): source = '#define foo bar(x)' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CFunctionCall( function_name='bar', arguments=[ c_ast.CVariable('x'), ], ), string_replacement=' bar(x)', ), ]), ) self.assertEqual(actual, expected)
def test_evaluate_defined_with_defined_object_like( self, ): self.object_likes.update({ 'x': pre_ast.DefineObjectLike( name='x', replacement=c_ast.CLiteral(''), string_replacement='', ), }) expression = c_ast.CFunctionCall( function_name='defined', arguments=[c_ast.CVariable('x')], ) actual = self.evaluator.evaluate(expression) expected = c_ast.CNumber(1) self.assertEqual(actual, expected)
def get_x86_64_kernel_compile_object_likes(): return { '__STDC__': pre_ast.DefineObjectLike( name='__STDC__', replacement=c_ast.CNumber(1), string_replacement='1', ), '__STDC_VERSION__': pre_ast.DefineObjectLike( name='__STDC_VERSION__', replacement=c_ast.CNumber(201112L), string_replacement='201112L', ), '_XOPEN_SOURCE': pre_ast.DefineObjectLike( name='_XOPEN_SOURCE', replacement=c_ast.CNumber(500), string_replacement='500', ), '__GNUC__': pre_ast.DefineObjectLike( name='__GNUC__', replacement=c_ast.CNumber(4), string_replacement='4', ), '__GNUC_MINOR__': pre_ast.DefineObjectLike( name='__GNUC_MINOR__', replacement=c_ast.CNumber(8), string_replacement='8', ), '__GNUC_PATCHLEVEL__': pre_ast.DefineObjectLike( name='__GNUC_PATCHLEVEL__', replacement=c_ast.CNumber(4), string_replacement='4', ), '__x86_64__': pre_ast.DefineObjectLike( name='__x86_64__', replacement=c_ast.CNumber(1), string_replacement='1', ), '__KERNEL__': pre_ast.DefineObjectLike( name='__KERNEL__', replacement=c_ast.CLiteral(''), string_replacement='', ), }
def test_parse_multiline_define(self): source = '\n'.join([ '#define foo bar\\', ' baz', ' 42', ]) actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=pre_ast.CompositeBlock([ c_ast.CVariable('bar'), c_ast.CVariable('baz'), ]), string_replacement=' bar baz', ), pre_ast.TextBlock('\n 42'), ])) self.assertEqual(actual, expected)
def test_parse_define_object_with_statement_concatenation(self, ): source = '#define foo bar ## baz;' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=pre_ast.CompositeBlock([ c_ast.CFunctionCall( function_name='##', arguments=[ c_ast.CVariable('bar'), c_ast.CVariable('baz'), ], ), c_ast.CLiteral(';'), ]), string_replacement=' bar ## baz;', ), ]), ) self.assertEqual(actual, expected)
def test_parse_define_object_like_as_attribute(self): source = '#define foo __attribute__((packed))' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CFunctionCall( function_name='__attribute__', arguments=[ c_ast.CNestedExpression( opener='(', content=c_ast.CVariable('packed'), closer=')', ), ], ), string_replacement=' __attribute__((packed))', ), ]), ) self.assertEqual(actual, expected)
def test_evaluate_variable_cycle_with_self_call( self, ): self.object_likes.update({ 'x': pre_ast.DefineObjectLike( name='x', replacement=c_ast.CFunctionCall( function_name='x', arguments=[c_ast.CVariable('x')], ), string_replacement='x(x)', ), }) expression = c_ast.CVariable('x') actual = self.evaluator.evaluate(expression) expected = c_ast.CFunctionCall( function_name='x', arguments=[c_ast.CVariable('x')], ) self.assertEqual(actual, expected)
def test_evaluate_argument( self, ): self.object_likes.update({ 'foo': pre_ast.DefineObjectLike( name='foo', replacement=c_ast.CNumber(42), string_replacement='42', ) }) expression = c_ast.CFunctionCall( function_name='f', arguments=[c_ast.CVariable('foo')], ) actual = self.evaluator.evaluate(expression) expected = c_ast.CFunctionCall( function_name='f', arguments=[c_ast.CNumber(42)], ) self.assertEqual(actual, expected)
def test_parse_define_object_with_multiple_expressions_and_concatenation( self, ): source = '#define foo x y ## u v' actual = self.parser.parse(source) expected = pre_ast.File(content=pre_ast.CompositeBlock([ pre_ast.DefineObjectLike( name='foo', replacement=pre_ast.CompositeBlock([ c_ast.CVariable('x'), c_ast.CFunctionCall( function_name='##', arguments=[ c_ast.CVariable('y'), c_ast.CVariable('u'), ], ), c_ast.CVariable('v') ]), string_replacement=' x y ## u v', ), ]), ) self.assertEqual(actual, expected)
def test_preproces_undef_with_undefined_name(self): define_object_like = pre_ast.DefineObjectLike( name='some_name_1', replacement='some_replacement_1', string_replacement='some_string_replacement_1', ) self.object_likes['some_name_1'] = define_object_like define_function_like = pre_ast.DefineFunctionLike( name='some_name_2', arguments='some_arguments_2', replacement='some_replacement_2', string_replacement='some_string_replacement_2', ) self.function_likes['some_name_2'] = define_function_like undef = pre_ast.Undef('some_name_3') actual = self.preprocessing_visitor.preprocess(undef) self.assertIsNone(actual) self.assertEqual(self.object_likes['some_name_1'], define_object_like) self.assertEqual(self.function_likes['some_name_2'], define_function_like) self.assertFalse('some_name_3' in self.object_likes) self.assertFalse('some_name_3' in self.function_likes)