mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			175 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
| #!/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()
 |