1#!/usr/bin/python 2""" 3Filters out some of the #defines used throughout the GCC sources: 4- GTY(()) marks declarations for gengtype.c 5- PARAMS(()) is used for K&R compatibility. See ansidecl.h. 6 7When passed one or more filenames, acts on those files and prints the 8results to stdout. 9 10When run without a filename, runs a unit-testing suite. 11""" 12import re 13import sys 14import unittest 15 16# Optional whitespace 17OPT_WS = '\s*' 18 19def filter_src(text): 20 """ 21 str -> str. We operate on the whole of the source file at once 22 (rather than individual lines) so that we can have multiline 23 regexes. 24 """ 25 26 # Convert C comments from GNU coding convention of: 27 # /* FIRST_LINE 28 # NEXT_LINE 29 # FINAL_LINE. */ 30 # to: 31 # /** @verbatim FIRST_LINE 32 # NEXT_LINE 33 # FINAL_LINE. @endverbatim */ 34 # so that doxygen will parse them. 35 # 36 # Only comments that begin on the left-most column are converted. 37 # 38 text = re.sub(r'^/\*\* ', 39 r'/** @verbatim ', 40 text, 41 flags=re.MULTILINE) 42 text = re.sub(r'^/\* ', 43 r'/** @verbatim ', 44 text, 45 flags=re.MULTILINE) 46 text = re.sub(r'\*/', 47 r' @endverbatim */', 48 text) 49 50 # Remove GTY markings (potentially multiline ones): 51 text = re.sub('GTY' + OPT_WS + r'\(\(.*?\)\)\s+', 52 '', 53 text, 54 flags=(re.MULTILINE|re.DOTALL)) 55 56 # Strip out 'ATTRIBUTE_UNUSED' 57 text = re.sub('\sATTRIBUTE_UNUSED', 58 '', 59 text) 60 61 # PARAMS(()) is used for K&R compatibility. See ansidecl.h. 62 text = re.sub('PARAMS' + OPT_WS + r'\(\((.*?)\)\)', 63 r'(\1)', 64 text) 65 66 # Replace 'ENUM_BITFIELD(enum_name)' with 'enum enum_name'. 67 text = re.sub('ENUM_BITFIELD\s*\(([^\)]*)\)', 68 r'enum \1', 69 text) 70 71 return text 72 73class FilteringTests(unittest.TestCase): 74 ''' 75 Unit tests for filter_src. 76 ''' 77 def assert_filters_to(self, src_input, expected_result): 78 # assertMultiLineEqual was added to unittest in 2.7/3.1 79 if hasattr(self, 'assertMultiLineEqual'): 80 assertion = self.assertMultiLineEqual 81 else: 82 assertion = self.assertEqual 83 assertion(expected_result, filter_src(src_input)) 84 85 def test_comment_example(self): 86 self.assert_filters_to( 87 ('/* FIRST_LINE\n' 88 ' NEXT_LINE\n' 89 ' FINAL_LINE. */\n'), 90 ('/** @verbatim FIRST_LINE\n' 91 ' NEXT_LINE\n' 92 ' FINAL_LINE. @endverbatim */\n')) 93 94 def test_comment_example_gengtype(self): 95 self.assert_filters_to( 96 ('/** Allocate and initialize an input buffer state.\n' 97 ' * @param file A readable stream.\n' 98 ' * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.\n' 99 ' * \n' 100 ' * @return the allocated buffer state.\n' 101 ' */'), 102 ('/** @verbatim Allocate and initialize an input buffer state.\n' 103 ' * @param file A readable stream.\n' 104 ' * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.\n' 105 ' * \n' 106 ' * @return the allocated buffer state.\n' 107 ' @endverbatim */')) 108 109 def test_oneliner_comment(self): 110 self.assert_filters_to( 111 '/* Returns the string representing CLASS. */\n', 112 ('/** @verbatim Returns the string representing CLASS. @endverbatim */\n')) 113 114 def test_multiline_comment(self): 115 self.assert_filters_to( 116 ('/* The thread-local storage model associated with a given VAR_DECL\n' 117 " or SYMBOL_REF. This isn't used much, but both trees and RTL refer\n" 118 " to it, so it's here. */\n"), 119 ('/** @verbatim The thread-local storage model associated with a given VAR_DECL\n' 120 " or SYMBOL_REF. This isn't used much, but both trees and RTL refer\n" 121 " to it, so it's here. @endverbatim */\n")) 122 123 def test_GTY(self): 124 self.assert_filters_to( 125 ('typedef struct GTY(()) alias_pair {\n' 126 ' tree decl;\n' 127 ' tree target;\n' 128 '} alias_pair;\n'), 129 ('typedef struct alias_pair {\n' 130 ' tree decl;\n' 131 ' tree target;\n' 132 '} alias_pair;\n')) 133 134 def test_multiline_GTY(self): 135 # Ensure that a multiline GTY is filtered out. 136 self.assert_filters_to( 137 ('class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),\n' 138 '\t chain_next ("%h.next"), chain_prev ("%h.previous")))\n' 139 ' symtab_node_base\n' 140 '{\n'), 141 ('class symtab_node_base\n' 142 '{\n')) 143 144 def test_ATTRIBUTE_UNUSED(self): 145 # Ensure that ATTRIBUTE_UNUSED is filtered out. 146 self.assert_filters_to( 147 ('static void\n' 148 'record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED)\n' 149 '{\n'), 150 ('static void\n' 151 'record_set (rtx dest, const_rtx set, void *data)\n' 152 '{\n')) 153 154 def test_PARAMS(self): 155 self.assert_filters_to( 156 'char *strcpy PARAMS ((char *dest, char *source));\n', 157 'char *strcpy (char *dest, char *source);\n') 158 159 def test_ENUM_BITFIELD(self): 160 self.assert_filters_to( 161 ' ENUM_BITFIELD (sym_intent) intent:2;\n', 162 ' enum sym_intent intent:2;\n') 163 164def act_on_files(argv): 165 for filename in argv[1:]: 166 with open(filename) as f: 167 text = f.read() 168 print(filter_src(text)) 169 170if __name__ == '__main__': 171 if len(sys.argv) > 1: 172 act_on_files(sys.argv) 173 else: 174 unittest.main() 175