diff options
Diffstat (limited to 'libc/kernel/tools/cpp.py')
-rwxr-xr-x | libc/kernel/tools/cpp.py | 231 |
1 files changed, 224 insertions, 7 deletions
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py index 1ada59e09..b6a153881 100755 --- a/libc/kernel/tools/cpp.py +++ b/libc/kernel/tools/cpp.py @@ -30,10 +30,7 @@ from clang.cindex import TranslationUnit # Note that setting LD_LIBRARY_PATH with os.putenv() sometimes doesn't help. clang.cindex.Config.set_library_file(os.path.join(top, 'prebuilts/sdk/tools/linux/lib64/libclang_android.so')) -from defaults import kCppUndefinedMacro -from defaults import kernel_remove_config_macros -from defaults import kernel_struct_replacements -from defaults import kernel_token_replacements +from defaults import * debugBlockParser = False @@ -1198,6 +1195,52 @@ class BlockList(object): if b.isIf(): b.expr.optimize(macros) + def removeStructs(self, structs): + """Remove structs.""" + for b in self.blocks: + # Have to look in each block for a top-level struct definition. + if b.directive: + continue + num_tokens = len(b.tokens) + # A struct definition has at least 5 tokens: + # struct + # ident + # { + # } + # ; + if num_tokens < 5: + continue + # This is a simple struct finder, it might fail if a top-level + # structure has an #if type directives that confuses the algorithm + # for finding th end of the structure. Or if there is another + # structure definition embedded in the structure. + i = 0 + while i < num_tokens - 2: + if (b.tokens[i].kind != TokenKind.KEYWORD or + b.tokens[i].id != "struct"): + i += 1 + continue + if (b.tokens[i + 1].kind == TokenKind.IDENTIFIER and + b.tokens[i + 2].kind == TokenKind.PUNCTUATION and + b.tokens[i + 2].id == "{" and b.tokens[i + 1].id in structs): + # Search forward for the end of the structure. + # Very simple search, look for } and ; tokens. If something + # more complicated is needed we can add it later. + j = i + 3 + while j < num_tokens - 1: + if (b.tokens[j].kind == TokenKind.PUNCTUATION and + b.tokens[j].id == "}" and + b.tokens[j + 1].kind == TokenKind.PUNCTUATION and + b.tokens[j + 1].id == ";"): + b.tokens = b.tokens[0:i] + b.tokens[j + 2:num_tokens] + num_tokens = len(b.tokens) + j = i + break + j += 1 + i = j + continue + i += 1 + def optimizeAll(self, macros): self.optimizeMacros(macros) self.optimizeIf01() @@ -1755,7 +1798,6 @@ class OptimizerTests(unittest.TestCase): def parse(self, text, macros=None): out = utils.StringOutput() blocks = BlockParser().parse(CppStringTokenizer(text)) - blocks.replaceTokens(kernel_token_replacements) blocks.optimizeAll(macros) blocks.write(out) return out.get() @@ -1931,8 +1973,8 @@ class OptimizerTests(unittest.TestCase): #endif /* SIGRTMAX */ """ expected = """\ -#ifndef __SIGRTMAX -#define __SIGRTMAX 123 +#ifndef SIGRTMAX +#define SIGRTMAX 123 #endif """ self.assertEqual(self.parse(text), expected) @@ -1948,6 +1990,146 @@ class OptimizerTests(unittest.TestCase): expected = "" self.assertEqual(self.parse(text), expected) +class RemoveStructsTests(unittest.TestCase): + def parse(self, text, structs): + out = utils.StringOutput() + blocks = BlockParser().parse(CppStringTokenizer(text)) + blocks.removeStructs(structs) + blocks.write(out) + return out.get() + + def test_remove_struct_from_start(self): + text = """\ +struct remove { + int val1; + int val2; +}; +struct something { + struct timeval val1; + struct timeval val2; +}; +""" + expected = """\ +struct something { + struct timeval val1; + struct timeval val2; +}; +""" + self.assertEqual(self.parse(text, set(["remove"])), expected) + + def test_remove_struct_from_end(self): + text = """\ +struct something { + struct timeval val1; + struct timeval val2; +}; +struct remove { + int val1; + int val2; +}; +""" + expected = """\ +struct something { + struct timeval val1; + struct timeval val2; +}; +""" + self.assertEqual(self.parse(text, set(["remove"])), expected) + + def test_remove_minimal_struct(self): + text = """\ +struct remove { +}; +""" + expected = ""; + self.assertEqual(self.parse(text, set(["remove"])), expected) + + def test_remove_struct_with_struct_fields(self): + text = """\ +struct something { + struct remove val1; + struct remove val2; +}; +struct remove { + int val1; + struct something val3; + int val2; +}; +""" + expected = """\ +struct something { + struct remove val1; + struct remove val2; +}; +""" + self.assertEqual(self.parse(text, set(["remove"])), expected) + + def test_remove_consecutive_structs(self): + text = """\ +struct keep1 { + struct timeval val1; + struct timeval val2; +}; +struct remove1 { + int val1; + int val2; +}; +struct remove2 { + int val1; + int val2; + int val3; +}; +struct keep2 { + struct timeval val1; + struct timeval val2; +}; +""" + expected = """\ +struct keep1 { + struct timeval val1; + struct timeval val2; +}; +struct keep2 { + struct timeval val1; + struct timeval val2; +}; +""" + self.assertEqual(self.parse(text, set(["remove1", "remove2"])), expected) + + def test_remove_multiple_structs(self): + text = """\ +struct keep1 { + int val; +}; +struct remove1 { + int val1; + int val2; +}; +struct keep2 { + int val; +}; +struct remove2 { + struct timeval val1; + struct timeval val2; +}; +struct keep3 { + int val; +}; +""" + expected = """\ +struct keep1 { + int val; +}; +struct keep2 { + int val; +}; +struct keep3 { + int val; +}; +""" + self.assertEqual(self.parse(text, set(["remove1", "remove2"])), expected) + + class FullPathTest(unittest.TestCase): """Test of the full path parsing.""" @@ -1956,9 +2138,12 @@ class FullPathTest(unittest.TestCase): keep = set() out = utils.StringOutput() blocks = BlockParser().parse(CppStringTokenizer(text)) + + blocks.removeStructs(kernel_structs_to_remove) blocks.removeVarsAndFuncs(keep) blocks.replaceTokens(kernel_token_replacements) blocks.optimizeAll(None) + blocks.write(out) return out.get() @@ -2241,6 +2426,38 @@ something that should still be kept """ self.assertEqual(self.parse(text), expected) + def test_verify_timeval_itemerval(self): + text = """\ +struct __kernel_old_timeval { + struct something val; +}; +struct __kernel_old_itimerval { + struct __kernel_old_timeval val; +}; +struct fields { + struct __kernel_old_timeval timeval; + struct __kernel_old_itimerval itimerval; +}; +""" + expected = """\ +struct fields { + struct timeval timeval; + struct itimerval itimerval; +}; +""" + self.assertEqual(self.parse(text), expected) + + def test_token_replacement(self): + text = """\ +#define SIGRTMIN 32 +#define SIGRTMAX _NSIG +""" + expected = """\ +#define __SIGRTMIN 32 +#define __SIGRTMAX _KERNEL__NSIG +""" + self.assertEqual(self.parse(text), expected) + if __name__ == '__main__': unittest.main() |