blob: a82a8d5728cdb3b282ec80e2c5fb991c1de19702 [file] [log] [blame]
#!/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()