#!/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()