filter_params.py 5.8 KB

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