]>
Commit | Line | Data |
---|---|---|
892c1fce DM |
1 | #!/usr/bin/python |
2 | """ | |
3 | Filters 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 | ||
7 | When passed one or more filenames, acts on those files and prints the | |
8 | results to stdout. | |
9 | ||
10 | When run without a filename, runs a unit-testing suite. | |
11 | """ | |
12 | import re | |
13 | import sys | |
14 | import unittest | |
15 | ||
16 | # Optional whitespace | |
17 | OPT_WS = '\s*' | |
18 | ||
19 | def 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. | |
7f1b5019 ML |
37 | # |
38 | text = re.sub(r'^/\*\* ', | |
39 | r'/** @verbatim ', | |
40 | text, | |
41 | flags=re.MULTILINE) | |
892c1fce DM |
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 | ||
7f1b5019 ML |
66 | # Replace 'ENUM_BITFIELD(enum_name)' with 'enum enum_name'. |
67 | text = re.sub('ENUM_BITFIELD\s*\(([^\)]*)\)', | |
68 | r'enum \1', | |
69 | text) | |
70 | ||
892c1fce DM |
71 | return text |
72 | ||
73 | class 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 | ||
7f1b5019 ML |
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 | ||
892c1fce DM |
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 | ||
7f1b5019 ML |
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 | ||
892c1fce DM |
164 | def 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 | ||
170 | if __name__ == '__main__': | |
171 | if len(sys.argv) > 1: | |
172 | act_on_files(sys.argv) | |
173 | else: | |
174 | unittest.main() |