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